A/B 测试设计方案 — /guide/getting-started
状态:Phase 0 脚手架已落地(本分支
feat/ab-getting-started)。四位开发者照docs/ab-author-guide.md写各自页面即可。
1. 目标
把 4 位开发各做一版新落地页「整体体验包」(页面 + 安装脚本,各人端到端),分别对照未改动的现状基线,看哪一版最能把搜索 CC 进来的用户导向 lucky。共 5 组:1 个 control + 4 个开发变体。
- A · control(现状基线) —
/guide/getting-started.html(沿用现有页面,不改;canonical 目标) - B —
/guide/getting-started-b.html— 开发者 1(主题自定) - C —
/guide/getting-started-c.html— 开发者 2 - D —
/guide/getting-started-d.html— 开发者 3 - E —
/guide/getting-started-e.html— 开发者 4
实验定位:整体体验包。赢家是「这一整套页面+脚本」赢的,不做页面 vs 脚本的拆分归因(这是团队共识)。
2. 关键约束(来自仓库现状)
- 站点是 VitePress SPA,不能用边缘响应重写(触发 hydration 闪回)。
- 已有 Analytics Engine 埋点生态(
web_traffic+czh_vid+ bot 分类 + DNT + exporter)→ 复用,不引入 D1。 - 下游事件(install/wrapper/cc_auth/payment)全部以
install_id为键 → 安装时打变体标记即可归因整条漏斗。
3. 投递层:预绘制粘性重定向到独立页
五个真实 VitePress 页面。control(A)= 现有页面,canonical 承接搜索流量;B/C/D/E 是 4 个独立变体页。
分桶 + 重定向(.vitepress/config.mts 全局 head 内联脚本,body 绘制前同步执行):
- 读 / 铸造
localStorage.czh_vid(复用流量埋点的访客 ID)。 - 若无
localStorage.czh_ab,用cyrb53(czh_vid) % 100按权重分到 a/b/c/d/e,写盘锁定(改权重不翻老用户的桶)。- GO-LIVE 开关:
config.mts里var W={a:100,b:0,c:0,d:0,e:0}。脚手架先以 100% A 上线(B/C/D/E 还是占位也不会有真实用户落进去),四个变体都就绪后用一个小 PR 翻成{a:20,b:20,c:20,d:20,e:20}(等分,或给 control 更大权重)正式开跑。
- GO-LIVE 开关:
- 给
<html data-ab>打标(调试/分析用)。 - 若当前在某个实验页、但其变体 ≠ 分配桶 →
location.replace到正确变体页。
要点:
- control(A)零闪零跳:命中 A 的用户落在 canonical 上不动。
- B/C/D/E 用户在 body 绘制前
location.replace,几乎无闪;地址栏出现-b/-c/-d/-e(实验可接受)。 - 粘性:桶由
czh_vid决定且写盘锁定,跨会话稳定。 - 爬虫 / 无 JS:不执行脚本,永远看 control(A)→ 单一 canonical,GEO 干净、无 cloaking。
- SPA 导航:
.vitepress/theme/ab.ts在路由切换时做同样的检查(用 VitePress router 客户端跳转)。
B/C/D/E 页面通过 frontmatter 设置 <link rel="canonical" href="https://claude-zh.cn/guide/getting-started.html">,把权重归并到 control。
4. 埋点(复用 AE)
4.1 新 dataset ab_events(binding AB_ANALYTICS)
接收端 functions/api/ab-event/[[path]].js(照搬 pageview-event 模式:客户端只传少量字段,服务端派生 device/country/ref):
| blob | 字段 | 说明 |
|---|---|---|
| blob1 | event | exposure / cta_copy / cta_click / section_view |
| blob2 | variant | a/b/c/d/e |
| blob3 | path | 页面路径 |
| blob4 | cta | lucky_curl / lucky_ps / official_curl / 自定义(转化事件才有) |
| blob5 | visitor_id | czh_vid,UV/转化去重键 |
| blob6 | session_id | czh_sid |
| blob7 | device | 服务端从 UA 派生(bot 单列) |
| blob8 | browser | 同上 |
| blob9 | os | 同上 |
| blob10 | country | cf-ipcountry |
| blob11 | ref_kind | search/social/direct/internal/external |
| indexes | [event] | 采样键 |
4.2 事件来源(ab.ts,全部 sendBeacon,尊重 DNT)
- exposure:落在正确变体页时发一次。
- cta_copy:点击 lucky 安装代码块的复制按钮(脚本按代码内容自动识别 lucky vs official,作者无需配合)。
- cta_click:点击任何带
data-ab-cta="xxx"的元素(作者给「安装 lucky」大按钮加这个属性即可)。 - section_view:
data-ab-section="lucky"元素首次进入视口(作者给 lucky 段加这个属性)。
另外:pageview beacon 也带上
ab参数(web_traffic.blob13),让现有流量看板能直接按变体拆。exposure 计数以ab_events为准。
4.3 口径
主转化率(variant) = distinct(vid where event in (cta_copy,cta_click)) / distinct(vid where event = exposure)人类过滤(每条 query 必带):device != 'bot' AND vid NOT LIKE 'probe-test-%' AND vid != ''。
5. 下游真值归因(Phase 2,跨仓)
整体体验包模式下,每个变体页指向自己的安装脚本,每个脚本硬编码自己的 ab_variant 上报 install_events:
claude-zh.cn:functions/api/install-event/[[path]].js加 blob8 = ab_variant(positional 追加,向后兼容)。- 各变体的安装脚本在上报 install 事件时带上自己的变体标记。
一旦 install_events 有 (install_id, ab_variant),因为 wrapper/cc_auth/payment 都以 install_id 为键,就能把页面变体 → 安装 → 首启 → 登录 → 充值整条漏斗按变体拆开。
落地前 verify:确认各变体安装脚本的托管/分发方式,以及 install-event Function 加 blob 后的 schema 版本同步到 AE 查询备忘。
6. 统计与防误判
- 检验:双比例 z 检验(pooled SE,与团队已有 stats 实现一致)。
- 多重比较:B、C、D、E 各自 vs control(A)共 4 个对比,做 Bonferroni(α=0.05 → 每对用 0.0125)。
- 样本量先估:每组
n ≈ 16·p(1−p)/(p·δ)²(80% 功效 / 5% 显著)。- 例:基线复制率
p=8%、想测出相对提升δ=15%→ 每组约 2.5 万次曝光。 - 跑测周期 / 目标样本量待团队拍板填入此处:______
- 例:基线复制率
- 严禁 peeking:跑够预估样本量再下结论。
- AE 采样:早期小样本数字会抖,靠样本量 + 显著性 + DISTINCT 去重把关。
7. 看板
- 轻:
functions/api/ab-stats(token 保护,跑 AE SQL 算 A/B/C/D/E 的曝光/转化/率/z/p,返回 JSON)。Phase 1 够用。 - 重:接 luckyapi 看板 exporter 加「🧪 A/B 落地页」tab,Phase 2 全漏斗归因走这条。
8. 分阶段交付
| Phase | 内容 | 跨仓 | 状态 |
|---|---|---|---|
| 0 脚手架 | 分桶+重定向脚本;ab_events binding;ab-event Function;ab.ts 转化埋点;B/C/D/E 页 stub;pageview 加 ab | 仅本仓 | ✅ 本分支 |
| 1 实验上线 | 四人各写完整变体页(+各自脚本);ab-stats Function;锁定样本量/周期 | 仅本仓 | 待作者 |
| 2 真值归因 | 各脚本自带变体标记;install-event 加 blob8;看板全漏斗 tab | + 脚本仓 | 待排期 |
作者怎么开工
每位作者的逐步操作指南见 docs/ab-author-guide.md(分支、文件、埋点约定、本地预览、PR 流程)。本文件是设计/架构说明,作者照 author-guide 走即可。