关于前端AB实验,我是这么思考的

简介: 背景大家好, 我是Fly哥, 这次分享的内容主要是关于ABtest ,我们是做用户增长的,说白了就是对应下面几个关键词。拉新、激活、留存,留存的话 又分为 次日留存、 3日留存,这些都是我们的指标, 但是产品设计一个需求的时候, 可能会有实验的性质,不确定哪一组实验,对于指标的反馈是正向的,或者是那一组实验的效果更加明显。 这时候产品就会去创建AB实验,然后拿线上的一部分流量,去做实验, 分析数据, 得出实验结论,然后看是否满足预期, 如果不满足 就暂停实验, 或者进行全量实验。 大家可以看下下面这张流程图:图片然后对于我们前端而言,我们关心的点只有两个第一个就是接入ABtest,

背景



大家好, 我是Fly哥, 这次分享的内容主要是关于ABtest ,我们是做用户增长的,说白了就是对应下面几个关键词。拉新、激活、留存,留存的话 又分为 次日留存、 3日留存,这些都是我们的指标, 但是产品设计一个需求的时候, 可能会有实验的性质,不确定哪一组实验,对于指标的反馈是正向的,或者是那一组实验的效果更加明显。 这时候产品就会去创建AB实验,然后拿线上的一部分流量,去做实验, 分析数据, 得出实验结论,然后看是否满足预期, 如果不满足 就暂停实验, 或者进行全量实验。 大家可以看下下面这张流程图:


image.png


然后对于我们前端而言,我们关心的点只有两个


  1. 第一个就是接入ABtest,然后去做逻辑处理, 根据当前用户命中的不同实验,走不同的逻辑


  1. 第二个就是实验结束后的操作,不管是应用实验 还是 暂停实验, 那么对于我们而言都是进行代码删除


ab实验是什么??


可能很多同学讲到这里还是有点模糊,我在这里举一个最简单的例子, 我们在实际开发过程中的


我们通常在页面有样式变化,但又不确定是修改影响好坏的时候进行 AB 实验,实验数据可以为改版提供有力支持。

某公司日常(1)产品:把页面标题变成之前的两倍。标题就是要醒目,要大大大

image.png

image-20220604101406387


设计:打死都不同意,太大的标题不精致不优雅。 BOSS:下面的按钮点击导流就是收入。收入就是一切!!!你们做下实验,采用收入高的方案。 前端:哦。


从上面的图片 可以看出, 其实我们采取了AB 实验, 对于不同的用户,页面可能展示 不一样, 其实就是选取线上一部分流量,去进行实验, 然后划定目标人群, 对比数据的变化, 最终采取是否运用。


如何接入ABtest



我们先看下第一个问题, 前端如何ABTest。 我们看下老的接入AB流程图, 基本上是 产品创建一个AB 实验, 后端同学就要写一个接口, 我们去调用。 然后得到的该用户命中的分组信息,然后我们在根据逻辑判定。 如下图:


image.pngabtest1.


通过与产品交流得知, 目前得物的AB 实验平台分为下面三种


  1. 客户端实验


  1. 后端实验


  1. H5实验


用户的分组信息, 以及实验的名称都是产品在 AB 实验平台进行创建的,产品会在prd上


写上, 如:


key: 'xxxx',
value: 'old' 对照组
value: 'new1' 实验组1
value: 'new2' 实验组2


而后端获取用户AB信息 也是AB平台提供的分流接口, 然后在转发给我们, 所以后端接口起到了一层中间层,那就没必要了,这个链路是可以优化的,我们可以在创建实验的时候,拉上产品和后端同学进行沟通, 确认你是不是需要用户AB的信息,进行逻辑处理,如果完全不需要的。那么产品创建的时候,就创建H5 实验, 然后我们就直接调用AB 平台提供的H5接口,获取AB 信息就可以了。 如图所示 :

image.png


一个实验倒还好, 但是如果有很多实验, 并且对应的是不同的业务, 所以没办法保证每个开发接口的同学,保证接口的返回值统一,有的返回一个布尔值, 有的返回字符串。 但是这部分逻辑就是通用的,所以当后端不需要拿到用户的AB 信息,去对不同的用户 做逻辑处理的话, 我们就可以不走他们接口,将这部分逻辑统一封装到sdk 中,方便各个业务线调用,专注业务开发,不需要关心用户的分组信息


image.png


当时这么设计的原因主要有下面几点: 因为团队的技术栈有laya, cocos, react,他们在渲染层的处理方式都不一样, 所以分了两个npm包一个负责逻辑处理,一个负责渲染层, 做到解耦。 因为AB 平台后续会支持H5实验,传入 多个key ,得到当前用户在多组实验对应的分组信息,所以对应的设计图如下:

image.png

代码删除

谈到做AB 实验, 我拿我目前负责的一款游戏点鞋成金举例子: 产品要对游戏的头部进行做实验,看是不是直接凸出奖励,对于用户的吸引力更大

分别对应3个组 第一个是对照组

image.png

第二个是实验组1

image.png

第三个是实验组2:

image.png

如果要要去开发的话其实就会这么去写:


if (info === 'A') {
  // 实验A 用户的展示逻辑
} else if (info === 'B') {
  // 实验B  用户的展示逻辑
}else if(info === 'C') {
  // 实验C 用户的展示逻辑
}


其实看上去还好对吧, 不就是多写几个 if else  , 但是你 随着产品的实验 越来越多, 你这样的代码会越来越多。 会带来下面这 几个问题


  1. 当实验全部应用一个 数据比较好的 情况下, 你的那些脏代码,是不是要全部删除。这个需要我们前端 还要 花时间 去定时清理


  1. 因为虽然你可能只是删除了代码,在上线的时候其实也需要测试  进行回归, 万一你误删了,可能你和测试都不知道,造成线上事故


  1. 这两者 其实都 占用了 开发 和测试的一些时间  ,怎么做到提高代码的可维护性和稳定性呢

cocos


这里我介绍下cocos 方面我是怎么处理的, 用cocos 做的游戏, 页面每一个元素都叫做一个node ,每个节点上都有一些基础的属性,比如设置节点的 大小, 缩放, 锚点,还包括绑定脚本,绑定各种各样的组件 等等。如图所示:


image.png

其实我们可以开发一个自定义AB组件, 然后在脚本设置可以在编辑器中使用, 这样每个节点就可以添加到我们自定义的脚本组件。

// 编辑器特性
    editor: {
        // 允许当前组件在编辑器模式下运行
        executeInEditMode: false,
        // 当本组件添加到节点上后,禁止同类型(含子类)的组件再添加到同一个节点,防止逻辑发生冲突
        disallowMultiple: false,
        // menu 用来将当前组件添加到组件菜单中,方便用户查找
        menu: 'NX/FLEX/AB',
    },

然后内部我们通过全局的视图绑定, 绑定到AB请求的返回值,去做页面的渲染, 对于我们而言就不需要判断, 页面渲染哪个组件了。内部逻辑都封装好了,我们只需要关系当前实验组的表现是怎么样的就好了。 如图:

image.png

image-20220528164215375


我介绍下这几个节点的意思


  1. container 节点只负责绑定自定义脚本AB组件,


  1. 然后container 下面的子节点 对应的其实就是不同的实验分组, 展示的不同node, 比如 命中了实验组1  那么我页面展示其实就是 展示 headerA 其他节点都隐藏

我们看下container 节点的绑定


点击下方的添加组件,然后找到我们对应的脚本组件AB如图:

image.png


然后我们根据提示信息,填写对应的配置就完成了AB 实验的搭建了, 页面 就可以渲染我们想要的结果了


image.png


这里的key 和value 都是由产品提供的,我们填写就好了, 然后实验应用了, 我们只需要把对应的节点删除了就好了, 代码层面不需要做任何改动。


react


我们在看看react 层面 我是如何去做的,这里是由组合组件的方式去实现的 一个


<ABTestComponent config={{ keyName: 'xx' }} fallbackComponent={renderDefault()}>
      <Variant name={'new1'}>
        <New1 />
      </Variant>
      <Variant name={'old'} />
    </ABTestComponent>


一个组件 ABTestComponent 和一个 变量 组件 Variant,这里为什么设置两个组件, 当时是这么考虑的 由于产品设置的实验组 可能有多个, 无法确定一个实验key 对应多少个value 。 所以干脆利用 react 的  props.children 去match 对应的子组件, 然后渲染就好了。


ABTestComponent 这个实验 你只需要传入 当前的实验key 就可以了,然后传一个兜底组件,这是边界情况考虑, 内部 做了兜底处理,防止页面崩溃。


然后  Variant 这个组件下面封装各种情况的组件, 你就不需要 大量的if else 了, 这个场景 比较单一可能还看出优势,我们在看下一个稍微复杂的场景如下:


<ABTestComponent config={{ keyName: 'xx' }} fallbackComponent={renderDefault()}>
  <Variant name={'new1'}>
    <ABTestComponent config={{ keyName: 'yy' }} >
      <Variant name={'new3'}>
        <New3 />
      </Variant>
      <Variant name={'new4'}>
        <New4 />
      </Variant>
    </ABTestComponent>
  </Variant>
  <Variant name={'old'} />
</ABTestComponent>


我这个用户 命中 实验xx 的new1 并且 在new 1的情况下 又分为 new3 和 new4 做一进步实验, 然后要做各种逻辑处理。用这种方式去处理的话,逻辑都已经分开了, 你只需写对应的展示 就好了, 如果应用了那一组, 你只需要在 组件 这块做删除就好了, 不用在各种方法删除, 提升代码的可稳定性 或者维护性。

相关文章
|
缓存 前端开发 小程序
数据驱动UI迭代,如何设计简单高效的前端AB实验方案?
以前,我们没有一条简洁而高效的AB实验接入方案,过去大多数前端在接到AB需求,唯一的选择就是调用客户端提供的库函数来实现,我们从中发现了一些痛点。
数据驱动UI迭代,如何设计简单高效的前端AB实验方案?
|
2月前
|
Web App开发 缓存 前端开发
前端性能优化的整理笔记(一)
前端性能优化的整理笔记(一)
114 0
|
7天前
|
前端开发 JavaScript 数据库
如何实现前后端分离-----前端笔记
如何实现前后端分离-----前端笔记
|
7天前
|
前端开发 安全 NoSQL
技术笔记:Security前端页面配置
技术笔记:Security前端页面配置
|
1月前
|
JSON 前端开发 JavaScript
前端Ajax、Axios和Fetch的用法和区别笔记
前端Ajax、Axios和Fetch的用法和区别笔记
30 2
|
2月前
|
存储 前端开发 JavaScript
前端笔记_OAuth规则机制下实现个人站点接入qq三方登录
前端笔记_OAuth规则机制下实现个人站点接入qq三方登录
53 1
|
2月前
|
移动开发 前端开发 JavaScript
10款精美的web前端源码的特效,2024年最新面试题+笔记+项目实战
10款精美的web前端源码的特效,2024年最新面试题+笔记+项目实战
|
2月前
|
前端开发 容器
CSS3属性详解(一)文本 盒模型中的 box-ssize 属性 处理兼容性问题:私有前缀 边框 背景属性 渐变 前端开发入门笔记(七)
CSS3属性详解(一)文本 盒模型中的 box-ssize 属性 处理兼容性问题:私有前缀 边框 背景属性 渐变 前端开发入门笔记(七)
42 2
|
2月前
|
移动开发 前端开发 JavaScript
CSS选择器 前端开发入门笔记(十)
CSS选择器 前端开发入门笔记(十)
32 1
|
2月前
|
编解码 前端开发 iOS开发
前端开发入门笔记(八)CSS3属性详解:动画详解+Flex布局图文详解+Web字体
前端开发入门笔记(八)CSS3属性详解:动画详解+Flex布局图文详解+Web字体
72 1