https://google-admob-japan.connpass.com/event/138083/
2019/07/22 @Google AdMob Japan Meetup #5Yutaro Muta @yutailang0119ͯͳϒοΫϚʔΫiOSΞϓϦͷFirst Screen A/Bςετͷཪଆwith Firebase A/B Testing
View Slide
• Yutaro Muta @yutailang0119• Hatena Co., Ltd. @Kyoto• Conference Staff• builderscon 2017, 2018• try! Swift Tokyo 2019, 2020• ࠷ۙͷਪ͠Combine frameworkWho am I ?
͢͜ͱ• ͯͳϒοΫϚʔΫͷiOSΞϓϦͰߦͬͨA/Bςετͷ֓ཁ• ্هʹ͓͚ΔFirebase A/B Testingͷׂ• ઃఆํ๏• Tips
͞ͳ͍͜ͱ• AdMobʹΑΔΞϓϦࠂ
ͯϒͷεϚϗΞϓϦΛ͍ͬͯΔਓʙ
ͯϒεϚϗΞϓϦ• https:b.hatena.ne.jp ͷεϚϗΞϓϦ• ίϝϯτ͖ͰϒοΫϚʔΫͰ͖Δ• ײΛڞ༗Ͱ͖Δ• ͷϖʔδΛൃݟͰ͖Δ• iOS / Android
࠷ۙͯϒΞϓϦͷϗʔϜը໘͕มΘͬͨͳʔͱؾ͍ͮͨਓʙ
Before
After
Before After
มߋ• First ScreenͰΧςΰϦຖͷਓؾʹΓସ͑ΒΕΔ• ݩʑ૯߹ͷਓؾͱ৽ணͷΈ͕දࣔ͞Ε͍ͯͨ• ΧςΰϦͷฒͼॱɺҙʹฒͼସ͑ΒΕΔ
ͰɺFirst ScreenΛΤΠϠοͱมߋ͢Δͷා͍ͳ͊
ͦ͜ͰA/Bςετ
A/BςετπʔϧʹٻΊͨ͜ͱ• [Must] A or BͷΓସ͑Λ֎෦ (ΞϓϦϦϦʔεαΠΫϧ֎) ͔Βߦ͑Δ• ঢ়ଶʹ߹Θͤͯը໘ଆΛΓସ͑Δ• ςετதͷෆ۩߹݁Ռʹ໌Β͔ʹେ͖ͳ͕ࠩग़ͨࡍʹɺׂ߹Λมߋ• Ϗδωεతͳ͋Ε͜ΕʹରԠͰ͖ΔΑ͏• [Better] ੳπʔϧͱͷ૬ੑݕূͷ͢͠͞
Firebase A/B Testing
Firebase A/B Testing• ͢ͰʹFirebaseϓϥοτϑΥʔϜΛར༻͍ͯ͠Δͱɺಋೖίετ͕গͳ͍• Google Analytics for Firebaseͱ࿈ܞ͕Մೳ• Remote Configͱͯ͠ѻ͏ͷͰɺखܰ
Firebase A/B Testingͷઃఆ
ઃఆελʔτ
λʔήοτͷઃఆ
λʔήοτͷઃఆAnalytics.logEvent(_:, parameters:) ͰૹΔΠϕϯτΛͬͯɺಛఆͷૢ࡞Λͨ͠ϢʔβʔͷΈΛλʔήοτʹࢦఆՄೳ
ඪઃఆ
όϦΞϯτͷઃఆ
ΞϓϦͷ࣮
Remote Config͔ΒΛऔಘ// Fetch from Remote Configfunc fetch() {let expiration: TimeInterval = (60 * 60 * 3)remoteConfig.fetch(withExpirationDuration: expiration,completionHandler: nil)}// Activate fetched Remote Config settingsfunc activateFetched() {remoteConfig.activateFetched()}
Remote ConfigͰऔಘͨ͠ઃఆ͔Βը໘Λग़͚͠Δlet viewController: UIViewControllerswitch remoteConfig.viewSetting {case .a:viewController = AViewController()case .b:viewController = BViewController()}// Add to ContainerViewviewController.view.translatesAutoresizingMaskIntoConstraints = falseaddChild(viewController)containerViewController.addSubview(viewController.view)viewController.didMove(toParent: self)NSLayoutConstraint.activate([NSLayoutConstraint])// Switch ViewController by Remote Configlet viewController: UIViewControllerswitch remoteConfig {case .a:viewController = AViewController()case .b:viewController = BViewController()default:viewController = DefaultViewController()}// Add to ContainerViewviewController.view.translatesAutoresizingMaskIntoConstraints = falseaddChild(viewController)containerViewController.addSubview(viewController.view)viewController.didMove(toParent: self)NSLayoutConstraint.activate([NSLayoutConstraint]())
ⷁ ⷂ
A/Bςετ։࢝
~͕࣌ྲྀΕͯ~
ςετ݁Ռ• ͓Αͦ1ϲ݄΄ͲͷςετΛ࣮ࢪͨ͠• ςετ࣮ࢪલ͔Β΄΅ఆ௨Γͷظؒ• ৽ը໘ͷํ͕ɺچը໘ΑΓઃఆͨ͠ࢦඪʹ͓͍ͯ༏ҐͳࠩΛಘΒΕͨ• ࢦඪൿີ
ίϯιʔϧը໘
ςετྃ
ςετ݁ՌΛݩʹ...• ຬΛ࣋ͯ͠ɺ৽ը໘Λ100%ʹมߋ• AndroidͰ৽ը໘Λ࣮ɺϦϦʔε• ݁ՌɺAndroidͰྑ͍݁ՌΛಘΒΕͨ
A/B Testing Q&A
Q. ॳճىಈ࣌ʹA/BςετΛө͍ͨ͠
Q. ॳճىಈ࣌ʹA/BςετΛө͍ͨ͠• Remote ConfigɺωοτϫʔΫ௨৴Λ௨ͯ͡ઃఆΛऔಘ͢Δ• ॳճFetch࣌ʹઃఆແ͍• ίʔυ্Ͱͷdefault༻ҙͰ͖Δ• (ಛʹ) First ScreenͷA/BςετͰɺөλΠϛϯάʹ͕ඞཁʹͳΔ
ॳճFetchͷҊ1. Fetch͕ྃ͢Δ·Ͱɺը໘Λwait͢ΔPros: ॳճA/BςετͷઃఆΛөͰ͖ΔCons: ͕ͪ࣌ؒൃੜɺFetch͕ࣦഊͨ࣌͠Ͳ͏͢Δʁ2. Fetch͕ྃͨ͠Βଈ࠲ʹөͤ͞Δ-> ࠷ॳdefaultͰը໘Λදࣔ -> Fetchޙ͙͢ʹ RemoteConfig.activateFetched() -> ը໘ͷߋ৽Pros: ্࣮ͷߟྀগͳ͍Cons: Ϣʔβʔ༻தʹUI͕มߋ͞ΕΔͷͰɺڻ͔͘3. ࣍ճىಈ࣌·Ͱͭ-> ىಈ࣌ʹͷΈ RemoteConfig.activateFetched()Pros: ্࣮ͷߟྀগͳ͍Cons: 2ճҎ߱ͷىಈʹͨͲΓண͚ͳ͍ͱɺςετͰ͖ͳ͍
Q. A/Bςετͷσόοάେม͡Όͳ͍ʁ
Q. A/Bςετͷσόοάେม͡Όͳ͍ʁ• betaϏϧυͰͷΈ Khan/SwiftTweaks Λ͍ɺΓସ͑Մೳʹͨ͠• A/BςετҎ֎ʹ௨৴ͦͷଞઃఆͷΓସ͑ɺσόοάʹ͍ͬͯΔ
&OKPZ"#5FTUJOH 5IBOLTw NVUBZVUBSP!HNBJMDPNw IUUQTUXJUUFSDPNZVUBJMBOHw IUUQTHJUIVCDPNZVUBJMBOH