实验启动 - Firebase A/B Testing 的用户分组机制
1,实验启动后流程:创建试验后点击启动实验等于正式发布了一个实验规则,规则运行期间如果用户启动应用并获取Remote Config时,Firebase会自动进行条件判断(国家是美国,版本号>=26),条件不满足不参与实验,如果条件满足就会将其随机分配到某个组中并将结果持久化,已经分配的用户会永远保持在同一组,直到实验结束。
2,如果实验只是创建了没有启动:等于实验规则没有发布,那么它也不会生效,所有用户打开app也均不会被进行分组,客户端请求Remote Config时永远拿到的是默认值。
Firebase如何保证随机分组的公平性?
Firebase使用用户唯一标识进行实验分组,针对同一个用户的分组它不是今天随机一次明天又重新随机一次,而是通过用户id和实验id结合哈希算法将用户固定到一个组中,所以如果一个用户一旦被分配到了某个组中,那这个用户之后就永远属于这个组。
客户端如何主动知道当前用户属于哪个实验以及属于此实验下的哪个分组?
客户端通常不需要、也不应该主动查询“我属于哪个实验、哪个分组”。
Firebase A/B Testing 的设计理念是:客户端只读取 Remote Config 参数,通过参数值间接知道自己拿到了哪个分组。
更合理的方式:专门增加一个Remote Config 参数作为分组标识,在每个分组中赋予一个固定不变的值(例如字母A,B),客户端拿到这个参数值直接就作为组标识。
为什么不建议在第一次获取到分组信息时再持久化到客户端本地?
先说结论:Firebase 已经做了“持久化用户实验分组”,客户端再自己持久化一份分组信息通常不是一个好设计,原因不是性能,而是一致性和实验生命周期管理。
通过前面的Firebase分组机制我们知道用户一旦被分到某个组下之后,之后就永远固定在这个分组下了不会变,因此即使每次启动都动态反推属于哪个组,结果也都是固定且一致的,如下:
App启动1 Remote Config ->B App启动2 Remote Config ->B....App启动100 Remote Config ->B如果在第一次获取到分组B之后,客户端持久化保存到本地,之后每次启动都从本地直接读取,这样看起来更快也更方便,但是却存在如下几个问题:
1,Remote Config 不只是“分组系统”,还是“配置系统”
分组信息本身就是根据属性值反推的,如果中间修改了属性值,本来值3对应的是B组修改之后变成值2对应的是B组了,以及实验结束后全部用户都会恢复到默认值,此时如果客户端一直只从本地缓存读就会存在B组明明已经结束了,但是客户端还依然判定自己属于B组。
2,实验不是永久存在的
这个是最大的问题:实验结束之后,客户端持久化保存的分组数据会变得没有任何意义,之后再开启新的实验,这个分组应该要动态更新才对。
3,Remote Config 本身已经有本地缓存机制
实际上 Firebase Remote Config SDK 已经帮你做了一层缓存,客户端再做持久化保存本身也是在重复实现 Firebase 已经做的事情。
提示:如果非要使用客户端持久化,必须还得搭配动态获取Remote Config,等获取到结果之后实时更新本地缓存,下一次是用的就是更新后的本地缓存,绝不推荐单纯客户端本地化写死。
如果实验中途修改分组比例?
修改之前已经进入实验的用户通常不会被重新洗牌否则会污染实验数据,只会影响修改之后再次进入实验的用户分配。
是否可以借助实验来完成国家判断?
场景:我的实验是面向100%的美国用户创建的,刚好我的业务逻辑中需要判断当前用户所处的国家是否是在美国,我是不是可以不用自己写判断逻辑,直接依赖实验来进行国际判断?
结论:不建议这么做!!
原因:你的想法看起来很合理,但是忽略了一个问题:实验条件 ≠ 用户属性,并且实验条件只存在当前实验中,如果之后试验结束那么你的国家判断逻辑也会跟着一起消失。而且当实验一多的时候,这种依赖实验判断的逻辑会越来越混乱,所有
激活事件到底是什么?(谁才算真正参加实验)
官方解释:
意思是:实验开始后,所有被分配进入实验的用户都将受到实验变体中变量的影响,但是只有触发激活事件的用户才会被纳入最终的实验效果衡量中。
为什么需要激活事件?
原因:因为在很多实验中并不是所有进入实验的用户都有意义。
举例:假设你实验的目的是为了看广告策略是否影响收入以及留存
实验变体A:启动广告展示5秒
实验变体B:启动页广告展示3秒
如果被分配到该实验下的用户打开app因为网络原因导致根本就没有看到启动广告,那么这个用户其实不应该影响实验结果,所以我们可以将激活事件设置为 splash_ad_show,只让真正看到启动广告的人才进入实验分析。
如果不设置激活事件会怎么样?
如果不设置这个激活事件,Firebase就会认为所有被分配到实验的用户,从分组那一刻开始就是最终实验效果衡量的参与者,如果每天有1万人打开app这1万人全部都会进入实验统计(有可能其中只有1000人看到了广告,其他用户都是无效实验对象,不设置激活事件他们的行为会导致实验结果被严重稀释),设置了激活事件就等于对参与实验的用户又做了一层关键行为过滤,在实验中且触发了激活事件的用户才会被纳入最终实现效果衡量的数据样本中。
实验相关的信息是如何关联到Firebase Analytics自定义事件上的?
须知实验信息归属的是用户级别而不是事件级别,也就是说在实验启动期间,当用户启动app参与了实验并被随机分配到某个分组下之后,实验信息就会被同步写入用户属性User Property中,之后该用户在应用中触发的所有自定义事件就会自动共享被写入到该用户属性中的实验信息,从而实现的将某个自定义事件和实验信息绑定,这也是为什么Firebase 能知道这些事件属于哪个实验组的原因。
注意一个前提:只有在实验启动之后,实验用户在应用中产生的行为才会有,因为这个时候产生该行为的用户才会有实验属性,未启动实验之前的历史数据不会被关联。
提示:在Firebase Console的A/B Testing 页面我们会自动看到主要指标的统计数据,示例如下:
Variant A: Revenue$10000Variant B: Revenue$12000这是因为firebase自动帮我们把用户事件和用户的实验属性进行了join关联,但是如果你导出BigQuery执行如下的SQL命令查询:
select* from events whereevent_name='purchase'你不会直接看到类似这样的数据,你需要再将user_properties展开在里面去找实验数据,即你需要自己手动去join解析。
Remote Config 的默认值在什么时候会被用到?
0,分组下没有为字段设置新值,会使用默认值。
1,用户不满足实验条件会直接返回默认值。
2,实验没有覆盖到这个用户,例如实验流量设置的是20%,那么其余80%没有参与实验的用户也会直接拿到默认值。
3,如果启动时因为网络原因导致拉取Remote Config参数值失败则会返回SDK的本地默认值。
3,实验结束:取默认值(分有条件和无条件)
结束实验后的处理
例如:Remote Config参数默认值为0
对照组:参数值为1
实验组1:参数值为2
现在实验组1胜出,接下来我们要关闭实验,在Firebase后台关闭实验时选择发布获胜变体,firebase会将该变体对应的参数值设置为Remote Config的正式配置,这里分两种情况:
1,没有 Remote Config 条件时
发布获胜变体后其实就是用该变体的值直接修改了默认值,之后所有用户都拿到的是默认值2。
2,存在 Remote Config 条件时(更接近真实项目)
发布获胜变体后不是直接修改默认值,而是更改对应条件下的默认值,等于Remote Config中配置了两个默认值,如下图:
建议发布后去Config Remote配置中去检查一下值对不对。