前端视角下的 A/B Test:埋点、分流与验证
目录
「做个 A/B 实验看看」这句话听起来很轻松,真正落地时会发现:
- 指标怎么算?
- 实验人群怎么分?
- 前端要怎么接入实验配置?
- 实验结束之后,代码怎么收口?
这篇文章从前端的角度,讲一次相对完整的 A/B 实验闭环。
1. 先确定:为什么要做这个实验?
我们当时的实验目标是:提高某投资流程的转化率。
假设是:
把原本一个超长的单页表单拆成多步引导,是否能提高「填写完成率」。
因此:
- 实验对象:访问该流程的真实用户;
- 对照组:看到旧版「单页表单」;
- 实验组:看到新版「多步引导」;
- 观测指标:完成率、平均耗时、中途流失位置等。
只有先把这些定义清楚,后续埋点和分流才有方向。
2. 埋点设计:先有指标,再谈实现
这次我们重点关心几个指标:
flow_enter:进入流程的人数;flow_complete:完成流程的人数;step_view:在多步表单中,每一步的曝光;step_error:每一步表单提交失败次数。
在前端埋点上做了几件事:
- 所有埋点带上
experiment_id和variant(A / B); - 关键事件使用统一的
event_name+event_params格式; - 尽量避免把业务逻辑硬编码到埋点名里。
示例:
track('flow_enter', {
experimentId: 'exp_split_form_v1',
variant: currentVariant, // 'A' 或 'B'
});
track('step_view', {
experimentId: 'exp_split_form_v1',
variant: currentVariant,
step: 1,
});
track('flow_complete', {
experimentId: 'exp_split_form_v1',
variant: currentVariant,
});
3. 分流:让实验「公平」且可控
3.1 基本原则
-
同一用户体验稳定
- 被分到 A 组,就一直看 A;
- 避免一次访问是 A,刷新变 B。
-
分配近似均匀
- 比如 50% / 50%,可配置。
-
可按维度分层(可选)
- 某些实验只针对特定渠道/地区/设备;
- 可以把这些条件交给实验平台控制。
3.2 简单的前端分流逻辑(示意)
真实环境建议统一由实验平台服务端下发
这里用一个简化版说明思路:
function assignVariant(userId: string) {
// 简单哈希,保证同一用户稳定
const hash = hashString(userId);
return hash % 100 < 50 ? 'A' : 'B';
}
实际项目中:
- 更推荐由 实验平台在服务端完成分流,前端只负责读取「当前用户在哪个 variant」;
- 或者前端从配置接口拿到
variant,不自己算。
前端只要:
const { variant, experimentId } = await fetchExperimentConfig('exp_split_form_v1');
renderByVariant(variant);
4. 前端实现:一套代码里兼容 A/B 两种体验
实验时间有限,没必要搞两个完全独立项目,我们选择:同一代码库内分支渲染。
示意:
<template>
<div>
<OldSingleForm v-if="variant === 'A'" />
<StepForm v-else />
</div>
</template>
注意两点:
- 埋点要分别在两个版本里打好;
- 实验结束后,记得删掉失败版本的代码,而不是永远留个
if。
为了减少「代码污染」,我们一般会:
- 把新旧版本封装成两个独立组件;
- 把实验 if 判断集中放在一层。
5. 实验过程中的监控与灰度
上线时我们采用的是:
- 先把实验比例设得很小(比如 5% 的 B 组);
- 观察 1–2 天,确认没有严重 bug;
- 再逐步放大到目标比例(例如 50%)。
期间前端要关注:
- 是否出现某个版本异常 JS 错误;
- 是否出现某个版本性能指标明显变差;
- 是否有用户反馈「流程异常」。
这些都要在实验看效果之前先保证「能用」。
6. 结果验证:从数据到决策
实验跑了几周之后,数据团队给出的结果大概是:
- B 组(多步表单)完成率相比 A 组提升了 7–10%(统计显著);
- 平均填写耗时略有上升,但仍在可接受范围;
- 流失主要集中在第 2 步(补充信息),为后续优化提供了方向。
从前端视角看,更关心的是:
- 是否存在异常埋点(比如某些事件 A/B 数据差异异常大);
- 页面报错/性能是否在两组之间差异显著。
最终结论是:
- 该实验可以「放量上线」,即 B 组变成新默认;
- 旧版单页表单支撑一段时间后下线。
7. 实验结束:代码与配置的「收口」
很多团队会忽略一个步骤——清理实验遗留。
我们做了三件事:
- 删除旧版本组件和相关样式;
- 删除实验 ID / 分流逻辑,只保留新的实现;
- 保留埋点,但去掉
variant区分,改为新方案作为常规指标。
这样可以避免代码里残留一堆:
if (experimentId === 'xxx' && variant === 'B') {
// ...
}
长期下来会变成「实验墓地」。
8. 小结:前端在 A/B 实验中的角色
从这次实践来看,前端在 A/B 流程里的角色大概是:
- 在实验设计阶段,一起讨论可观测指标和埋点方案;
- 实现支持多版本渲染的前端逻辑;
- 接入实验平台,正确获取用户实验分组;
- 在实验过程中配合观察错误/性能;
- 实验结束后,做好代码和配置的收口。
A/B Test 的核心不在于「用了哪个实验平台」,而在于:
是否有一条「从假设 → 实验 → 数据 → 决策 → 收口」的闭环。
从前端把每一步做好,是让实验真正落地的关键。