Firebase 教程: iOS A/B 测试

原文:Firebase Tutorial: iOS A/B Testing
作者:Todd Kerpelman
译者:kmyhy

更新说明:本教程由 Kerpelman 升级至 iOS 11、Swift 4 和 Firebase 4.x。原文作者是 Todd Kerpelman。

我们都听过一些事情,比如某些开发者在修改了按钮标签或者他们的欢迎屏之后,突然发现他们的滞留率或 app 内购比例出现疯狂的增长。

可能在你的待办列表中,你还有一个“用我的购买按钮做实验”的项目,等待划勾,因为你发现正确运行这些实验实际上是一项很大的工作。

Firebase 远程配置 iOS教程中,我们演示了如何使用远程配置动态更新应用程序的某些内容,并向特定国家的用户提供定制的内容。

接下来本教程将探讨如何使用Firebase远程配置来进行 A/B 测试,通过试验不同的值并查看结果,以发现哪些值更好。接下来,我们将学习如何基于用户属性执行更高级的定制。

需要条件:本教程基于第一个Firebase远程配置 iOS 教程。也就是说,如果你非常熟悉Firebase远程配置并之前曾经使用过它,那么你很可能在没有完成第一个教程的情况下就可以使用它。

开始

这里下载 Planet Tour 2 Starter app。如果你有之前的远程配置教程项目就更好,你也可以使用它,因为它已经升级至 iOS 11、Swift 4 和 Firebase 4 了。在这个开始项目中,已经包含了要用到的CocoaPods库。

用 Xcode 打开项目,注意打开 .xcworkspace 文件,而不是 .xcodeproj 文件。

你需要为这个 app 创建一个 Firebase 项目,从控制台中下载一个 GoogleServices-info.plist 文件,你可以直接用以下方式下载这个文件:

  1. 浏览 console.firebase.google.com
  2. 点击 Add project。
  3. 项目命名为 Planet Tour,选好你的地区,然后点 CREATE PROJECT。

  4. 点击 Add Firebase to your iOS app.

  5. 填入你的项目的 bundle ID(com.razeware.Planet-Tour),给它一个好听的名字,App Store ID 字段留空,然后点击 REGISTER APP。

  6. 然后,你就可以在浏览器中下载 GoogleServices-info.plist 文件了。

  7. 在 Xcode 中打开 Planet Tour.xcworkspace,将这个文件拖进 Planet Tour 项目中(勾选 Copy Items if Needed)。
  8. 接下来的步骤点击 CONTINUE 就可以了。我们已经为做好了一切。

Build & run,你可以开始太阳系之旅了。点击几颗行星看看。

如果之前没看过这个项目,请看一下 RCValues.swift 来理解我们如何在这个项目中使用远程配置。回到主界面,看一下底部的 bar,它会让你订阅。

介绍一下 iOS A/B 测试

Planet Tour 公司的高层非常担心没有足够的用户来订阅 Planet Tour 杂志。毕竟,如果你不能通过 email 告诉人们 Planet Tour 的精彩的价格的话,你怎么在市场上获得成功呢?

有办法让订阅按钮变得更有吸引力吗?

市场部的家伙们有一个理论。如果你将按钮上的订阅按钮修改成“继续”按钮的话,你有可能获得更多的订阅量。同时,你可以把 banner 上的 Get our newsletter 改成 Get more facts 试试。

这种改变对于使用远程配置的 app 来说非常容易。在 Firebase 控制台中发布新值只是几秒钟的事情。一个星期后,你会订阅数增加了。简单吧?

别急,等等。你知道你的修改是怎样影响你看到的结果的吗?如果某个有影响力的博主在他们最近的文章中提到你的app中的 Newsletter,会发生什么?或者,你最终会在另一个app 的 newsletter 中进行广告宣传,从而在吸引喜欢订阅newsletter 的读者。

有许多因素你无法控制,而它们往往会让你得出错误的结论。

只要这两组人是无偏向性的,你就可以比较他们之间的结果,并有理由相信差异是因为你所做的改变,而不是一些外部因素。

对,这就是 A/B 测试,非常简单的一种进行某种实验的的方式。许多大公司会构建自己的架构来运行、评估这些测试,而Firebase远程配置则是基于Firebase已有的架构实现的。

在 App 中添加 Analytics

创建A/B测试的一个主要步骤是告诉Firebase你的实验目标是什么。有时,这可能是一个高层次的目标,比如增加滞留率(几天后你的用户回来了多少)或用户参与度(你的用户每天花在app上的时间)。但其他时候,这可能是一个非常具体的目标,比如增加访问应用程序内商店的用户数量,或者,在我们的例子中,增加注册“星球之旅”期刊的用户数量。

当然,Firebase知道你的用户是否已经注册了你的 Newsletter 的唯一方法是你来告诉它,这时你可以用Google Analytics for Firebase(之前叫做 Firebase Analytics)。如果你不熟悉移动分析的概念,这里有一篇很好的教程

所以,在你开始在创建一个A/B测试之前,让我们先向 app 中添加 Analytics,这样你就可以有一个清晰的目标。

添加事件

Google Analytics for Firebase,和其它移动分析方案一样,使用事件驱动模型。当用户在 app 中执行某些操作,Analytics 会向服务器发送事件。然后,服务器处理事件并将之转换成有意义的图表供你分析。

打开 ContainerViewController.swift。在文件头部加入:

import Firebase

然后,在 viewDidLoad() 中

Analytics.logEvent("mainPageLoaded", parameters: nil)

当用户打开 app 并进入主界面时发送一个 mainPageLoaded 事件。parameters 参数是一个可空字典,字典中存放了相关键值对。这里我们不需要它,因此传入 nil。

然后打开 GetNewsletterViewController.swift。在文件头部加入:

import Firebase

在 viewDidLoad() 最后一句加入:

Analytics.logEvent("newsletterPageLoaded", parameters: nil)

然后在 submitButtonWasPressed(_:)最后添加:

Analytics.logEvent("newsletterSubscribed", parameters: nil)

这样,当用户打开主界面、newsletter 页和点击注册 newsletter 的按钮时都会触发事件。

在 build & run 之前,需要将 Firebase Analytics 的 debug 模式打开,以便在控制台中查看 Analytics 调用的结果。

点击菜单 Product\Scheme\Edit Scheme。在 Run scheme 中,选择Arguments。在 Arguments Passed On Launch 下面,点击 + 号,输入参数 -FIRAnalyticsDebugEnabled。注意前面有一个 - 号。

完成后的界面如下图所示:

关闭对话框,build & run。控制台中有很多删除。你看到的内容类似这个样子:

[Firebase/Analytics][I-ACS023051] Logging event: origin, name, params: app, mainPageLoaded, {
    firebase_event_origin (_o) = app;
    firebase_screen_class (_sc) = WaitingViewController;
    firebase_screen_id (_si) = -5666061486001356881;
}

当你点击 Get our newsletters!(或者 Get more facts!) 按钮时,控制台会输出:

[Firebase/Analytics][I-ACS023051] Logging event: origin, name, params: app, newsletterPageLoaded, {
    firebase_event_origin (_o) = app;
    firebase_screen_class (_sc) = ContainerViewController;
    firebase_screen_id (_si) = 8191694734847900543;
}

当你点击 Subscribe 按钮时也会输出类似的事件。

你还可以在 Firebase 控制台的 DebugView 几乎实时地看到的类似的结果。这将让你在 debug 模式下看到所有 Firebase 收到的事件。

因为你已经打开了 debug 模式,Firebase Analytics 会非常频繁地向服务器发送数据。当它的数据过时 10 秒或者当 app 进入后台时就会发送一批数据。对于生产 app,这种行为会导致电池寿命降低。因此,如果你关闭 debug 模式,Firebase Analytics 会在数据过时 1 小时或者app 进入后台时才会发送数据。

偶然情况下,debug 设置会一直生效。如果你想关闭它(假设你想对app 的电池性能进行压力测试),你可以关闭这个标志、删除/重装 app、或者将这个参数显式地修改成 -noFIRAnalyticsDebugEnabled。

这样,你创建的 A/B 测试事件会 24 小时才发送一次。你不用等那么长时间来继续下面的教程;记住除了这些事件你还有其它事情要做。

静默状态: 在 RCValues.swift 中,你打开了开发者模式,因此 Firebase 不会阻止频繁的更新。有时,尤其是在新项目中,你可能处于静默状态。如果是那样,要么等一小时,要么重置模拟器,然后重试。

创建第一个 A/B 测试

在 Firebase 控制台中找到远程配置。如果提示你选择一个项目,请选择刚才创建的 Planet Tour 项目。

这次不创建新参数,点击页面中的 A/B 测试标签栏。然后,点击弹出面板中的 CREATE EXPERIMENT 按钮。

你会看到一个表单。前面几个字段非常简单。给一个实验名,比如 Newsletter sign-ups 以及描述。

Target users 字段,从下拉列表中选择你的 iOS app。你并没有 Android app,哪怕有,将它们分成不同的实验也更好,因为你的 app——或者你的用户——在不同的平台上行为是非常不同的。

因为你在对文字表签进行实验,将你的实验局限于英语用户更好一些。点击 AND 按钮,选择 Device language,从第二个下拉列表中选择 English。

最后,你可以设置添加到这个实验中的用户的百分比。参与实验的用户越多,最终结果的可信度越高。但如果你正在实验的东西有可能触怒你的社群或者会让你的app 内的收益受损,那么将比例调低一点会更好。

因为你的改变是很安全的,你可以将百分比设得稍大一点。30 是一个不错的数字。

最终,实验面板的第一步会是这个样子:

点击 NEXT。现在你可以为参与实验的不同人群分配不同的远程配置数值了(即变体——Variants)。

我们开始改变主界面底部 banner 的文字吧。这个值是通过远程配置变量 subscribeBannerButton 来设置的。

点击 ADD PARAMETER。如果你在之前的远程配置教程中使用过这个 app,那么你可以在下拉列表中看到一些名字,但你没有必要一定要使用它们;你也可以创建新的变量!因此输入 subscribeBannerButton 然后选择 Create parameter 选项。

现在你就可以为 subscribeBannerButton 添加在实验中用到的不同值了。

对于对照组(control group),保留值为默认(no value)。这会告诉远程配置,如果用户不在实验中,它将使用任意值。在你的例子中,即在 RCValues.swift 中的默认值 Get our newsletter!。一般情况下,最好让对照组保持 no value —— 这是将你的修改和当前 app 中运行的值进行对比的最佳方式。

对于第二个变量,给 subscribeBannerButton 赋值为 Get more facts!。

你的面板看起来像这个样子。

你还想实验一下 GetNewsletterViewController 中的按钮——这个参数叫做 subscribeVCButton。点击 ADD PARAMETER 新建一个参数,参数名使用这个参数名。

你可以这样修改 Variant A :

但这会带来一个问题。假设你发现 Variant A 比对照组表现更好,但你怎样才能知道这个改变是由于前一页的 Get more facts! 按钮导致的,还是将 Subscribe 按钮修改为 Continue 按钮导致的呢?你真的不知道。事实上,如果你不修改 Subscribe 按钮的话 Variant A 甚至能表现得更好。

因此一个更好的办法是,尝试几种变量的不同组合——即所谓的多变量测试,接下来你将执行它的一个简单版本。将 Variant A 中的 subscribeVCButton 设置为 (no value) 。

点击 Add Variant,这次将 subscribeBannerButton 设置为默认,将 subscribeVCButton 设置为 Continue。然后再次点 Add Variant, 将 subscribeBannerButton 设置为 Get more facts! ,将 subscribeVCButton 设为 Continue。

你的 experiment 面板现在变成:

点击 NEXT 来到最后一步,指定一个目标。也就是你希望在 app 中最大化的东西。这里,你希望增加 newsletterSubscribed 事件(这是在上一节中创建的)出现的几率。

假设已经过去了足够的时间,你在上一节中创建的事件已经进入了A/B测试系统,你应该会在下拉列表中看到一个目标 newsletterSubscribed。如果看到,请选择它。如果没有看到,你可能需要等待 1-2 天,让事件上传到系统。如果你等不了这么久,你可以选择另外一个目标比如 Retention (1 day).

Firebase 已经内置了大量和主要目标一起进行测算的次要目标。这些目标对于形成实验的“大图”视图是很有用的,以免你偶尔会因为大过专注于提升 Newsletter 订阅数而降低了 app 的留存率。

你已经创建好实验了!点 REVIEW。

测试你的实验

在向外发布之前你可能想测试一下实验。幸运的是,Firebase 运行你轻易在一台设备上测试你是实验变体。这需要用到你的 Instance ID token,这是一个分配给每个 app 实例的唯一标识。

要获得这个 ID,需要回到 Planet Tour 项目打开 AppDelegate.swift。在调 FirebaseApp.configure() 一句后添加:

let idToken = InstanceID.instanceID().token()
print ("Your instance ID token is \(idToken ?? "n/a")")

Build & run。你会在 Xcode 控制台中看到这一行:

如果你的示例 ID token 显示为 n/a,那么等上几秒重试。(instance ID token 的抓取是异步的。我简化了这个过程,并假设在上一次会话你的 app 已经抓取并缓存了一个 token)

回到 Firebase 控制台的实验页,展开实验详情。点击 Manage test devices。当对话框弹出,复制并粘贴你从 Xcode 控制台中获得的字符串。然后从下拉列表中选择一个变体——我喜欢测试 Option C 因为你可以一次性测试两种改变。

点击 ADD、SAVE。

退出并重启 app。因为你的 app 已经将远程配置缓存时间设置为 0(会议之前的教程),你会看到新的值已经出来了。

你可以随意测试其它变体。只需要重新访问 Manage test devices 对话框,在下拉列表中选择不同的变体,点击 Save,你就可以在测试机上看到不同的变体。

开始试验

测试完所有的变体并在测试机上看完每个变体的样子后,你可以真正开始试验了。回到 Firebase A/B 测试控制台,点击 START EXPERIMENT 按钮,然后点击 START。

这样,英语用户中的 30% 会随机看到 4 种变体之一。记录他们中有多少人达到了最终目标——订阅 newsletter,最后报告你哪个变体在引导用户达到目标这一方面做得最好。

读懂试验结果

FireBase A/B测试不仅能告诉你哪一种变体的“用户订阅”率最高。它还使用一个被称为贝叶斯统计的高等数学方法,让你知道这些差异是由于 app 的更改导致,还是随机的因素导致的。这就是人们用“统计意义”这一词时的通常意义。

要使这个数学方法,Firebase需要基于大量用户尝试这些不同的变体。虽然Planet Tour 确实是一个可爱的 app ,但它仍然是一个测试应用,用户总数为1。这意味着在本教程中,Firebase A/B 测试是无法收集足够的数据以给出任何有意义的结果的,你可能会看到如下所示画面:

幸运的是,通过想象力(以及一点点 ps),我们可以想象一些实际的结果可能是什么样子。

这里有许多统计数字,我们会对几个重要的数组进行说明。

顶部最大的标签是试验概要。这里,它告诉你 Variant B 是在主要目标(让用户订阅 Newsletter)上做的最好的。

下面,对每个变体和对照组进行比较,看看每个测算目标的总体提升范围。

例如,你会看到,它预测变体 A 和对照组相比,导致 newsletterSubscribed 事件在 -4% 到 +14% 之间变化。由于这是一个相当广泛的范围,它不能肯定这是一个更好的变化,所以它是以这种浅灰色的颜色。

另一方面,变体B 在促使人们订阅 newsletter 方面比对照组增加了 10-29% 。因为这肯定是一个更好的变化,所以有一个亮绿色与向上的箭头。

继续往下,你会看到更多关于你正在测量的目标的细节。你会看到 A/B 测试是否认为每个变体都比对照组做得更好,以及A/B测试中哪个变体表现最好。因此,虽然所有的变体似乎比我们的对照组更好,但很明显,变体B是所有三个变体中最好的。

右边的两列测量更多的实验原始数据。它们也很有意思,但我通常无法用它们来做任何事情。

推广实验

根据实验结果,你可能想将一个变体推广到所有用户。如果实验有一个明显的优胜者,你会看到一个按钮叫做“ROLL OUT THE LEADER”。

点击这个按钮,实验会停止,弹出一个对话框,允许你将获胜变体中的所有变量作为每个人的新值。这样,你的新的 newsletter 选项可以供全世界使用了!

带用户属性的高级用户目标

“冥王星回归!”

让我们换个角度来思考一下,除了A/B测试之外,我们还可以用Firebase远程配置做些什么。

在我们的上一篇教程中,你为斯堪的纳维亚的用户的 shouldWeIncludePluto 设置为 true,从而避免了一场国际危机。然而,事实证明,仅仅按国家设置这一设置是不够的。冥王星是否是一颗行星的选择是一个非常个人化的选择,来自世界各地的许多人对冥王星的行星地位有强烈的反应。我们如何为所有这些人定制Planet Tour 呢?

对,不仅仅根据国家来修改这个值,而是要根据某个用户属性来更细粒度的控制这个设置。

Analytics 的用户属性

Google Analytics for Firebase 中的用户属性是只与特定用户有关的属性。

举几个用户属性的例子,比如你的 app 中的高级用户、在你的运动 app 中的用户健身目标、或其它你想用来过滤事件数据的与用户相关的数据。

在这个例子中,你将记录一个类似 likesSmallRocks 的属性来记录用户对于太阳系外围的那些小而冷的石头的态度。然后,用该属性和远程配置一起向用户提供自定义的体验。

虽然可以用另外的方法来确定用户是否是喜欢太空中小的、遥远的石头,但最简单的方法就是直接询问用户。

在 PlanetsCollectionViewController.swift 顶部添加:

import Firebase

然后,在 reuseIdentifier 上面加一句:

private let takenSurveyKey = "takenSurvey"

最后,在写有 MARK: - Internal 一句的扩展、addFancyBackground() 函数前面加入一个函数。

@objc func runUserSurvey() {
  let alertController = UIAlertController(title: "User survey",
    message: "How do you feel about small, remote, cold rocks in space?",
    preferredStyle: .actionSheet)

  let fanOfPluto = UIAlertAction(title: "They're planets, too!", style: .default) { _ in
      Analytics.setUserProperty("true", forName: "likesSmallRocks")
  }

  let notAFan = UIAlertAction(title: "Not worth my time", style: .default) { _ in
      Analytics.setUserProperty("false", forName: "likesSmallRocks")
  }

  alertController.addAction(fanOfPluto)
  alertController.addAction(notAFan)
  navigationController?.present(alertController, animated: true)

  UserDefaults.standard.set(true, forKey: takenSurveyKey)
}

在添加调查时,要注意两件事:首先,当从用户那里得到回应后,将它记录在一个名为 likesSmallRocks 的新用户属性中。第二,在 UserDefaults 中做一个记录——表示这个用户已做过调查了,所以他们不会下次访问时再次被询问。

现在你已经在代码中设置了用户属性,接下来执行第二步,即让 Firebase 控制台知道这个属性,以便它可以开始基于它来生成报告。这是一个良好习惯,即在代码中添加用户属性的同时将它添加到 Firebase 控制台。打开 Firebase 控制台,选择 Analytics,然后选择 User Properties。

现在,在接下来这一步骤要注意——Firebase 控制台不允许在创建用户属性后编辑或删除它们!选择 NEW USER PROPERTY 并创建一个名为 likesSmallRocks 的新属性。我建议这里用复制粘贴,以确保完全一致。然后单击 Create。

回到 PlanetsCollectionViewController.swift,在 viewDidAppear(_:) 添加这句,确保你在 app 每次安装后进行询问:

if !UserDefaults.standard.bool(forKey: takenSurveyKey) {
  runUserSurvey()
}

如果你想让测试过程简单些,将这句代码添加到 customizeNavigationBar() 前面的 viewWillAppear(_:) 中,这会在导航栏上添加一个按钮,用于在任何时候都可以执行调查,无论我们是否已经看过它:

let retakeSurveyButton = UIBarButtonItem(barButtonSystemItem: .compose,
                                         target: self,
                                         action: #selector(runUserSurvey))
parent?.navigationItem.rightBarButtonItem = retakeSurveyButton

Build& run。你会被问到是否喜欢太空中的小石头。请根据自己的喜好回答。

定制 app

现在,你可以根据这个值来调整远程配置的值。打开 Firebase 控制台并选择Remote Config。如果你做过上一篇教程,你就会看到你的 shouldWeIncludePluto 条目。如果没有,那么请创建它。

如果你必须创建它,首先请点击 ADD YOUR FIRST PARAMETER。然后输入 shouldWeIncludePluto 作为参数名,值保留默认的空白。然后点 ADD PARAMETER。

点击 shouldWeIncludePluto 旁边的铅笔图标进行编辑,选择 Add value for condition > Define new condition。将新条件命名为 Small rock fans,然后定义条件为 applies if User property > likesSmallRocks | exactly matches | true

注意: 在这个对话框中不要用 == 比较操作符——那仅可用于数字比较。

点击 CREATE CONDITION,然后, 将 value 设为 true ,default value 设为 false。

注意:如果你没有做过上一篇教程,你在这里不会看到 “Pluto fans” 条件。那是 OK 的。

点击 UPDATE,然后点击 PUBLISH CHANGES。

再次 Build & run。

如果你回答你是一个遥远的小石头的爱好者,你会看到冥王星列在了行星之中。如果否,你就看不到冥王星……除非你的设备设置为斯堪的纳维亚国家,这样冥王星就还是会显示(假定你完整做完了上一篇教程并创建了那个条件)。

如果你想看看不同回答的 app 是什么样子,你可以点击顶部的 bar 按钮重新进行调查,然后退出并重启 app。

如何给你的冥王星粉丝呈现一些微妙的改变? 在你的应用中有一个变量——PlaneMagnEleefactor——它确定行星图像的大小与行星真实大小有多接近。

当值为 1.0 时,它们的大小是完美的,所以像冥王星这样的行星几乎还不到一个像素。当数值为0.0时,所有的行星都是相同大小的。现在,这个变量的默认值是0.33,这让你能够感觉到行星的相对大小,同时也使得较小的行星更容易被看到。

对于冥王星爱好者,这个值需要再小一点,以便冥王星和水星这样的小行星看起来比它们原来要大一些。

回到 Firebase 控制台的远程配置,创建一个新的参数 planetImageScaleFactor,在 Value for Small rock fans 一栏下面将值设置为 0.2,而 Default value 设置为 0.45。点击 UPDATE、PUBLISH CHANGES。

Build & run。取决于你对冥王星的喜好,火星或冥王星会相应地变得稍大或稍小。

火星看上去这么苗条,大概是因为它“非碳基生命”的食谱吧。

虽然这种修改无关紧要,但这种自定义也可能非常强大。随着对用户和他们对 app 的偏好了解得越多,你可以为你的用户提供真正的定制体验,确保那些吸引他们的元素始终是最重要的。

而且,你可以对这些参数做一些A、B测试,看看是什么能让你的 app 用户最开心!

接下来做什么

你可以在这里下载本教程的完整示例项目。但是请注意,你仍然需要在 Firebase 控制台中创建一个项目,并拖入GoogleServices-info.plist 文件。

你还可以用FireBase Analytics和远程配置来做更多事情,更多内容请阅读文档。

同时,思考你的 app 中有什么值得实验的元素?用 A/B 测试来测试它们,请在下面的评论中告诉我们你的发现。

猜你喜欢

转载自blog.csdn.net/kmyhy/article/details/80333451