- 浏览器优先,不依赖任何 UI 框架(React / Vue / 原生页面均可)
- 原生 TypeScript 支持,类型完整
通过 CDN 加载
可通过 CDN 引入 SDK。 CDN 模式调用语法:abSubotiz(方法名, ...参数)
上报事件
业务事件通过track(eventName, properties?) 上报,常用于实验转化分析(注册完成、按钮点击、自有收入 / LTV 等平台无法自动采集的指标):
- 永远上报、永不丢弃——SDK 不在客户端做白名单拦截,任意
eventName都会发往后端。是否计入某个实验由后端归因,无需前端关心 - 永远成功返回,不抛出异常
- 网络失败 / 5xx → 入
localStorage离线队列,回到在线状态时自动重发 - 4xx → 静默丢弃(事件本身不合法)
init未完成时调用 → 静默跳过
数值指标:properties.value
需要求和 / 平均值类聚合的指标(如收入、LTV、停留时长),把数值放在 properties.value 上:
value必须是有限数字(typeof === 'number'且非NaN/Infinity)才会被后端纳入数值聚合。- 非法的
value(字符串'99.9'、NaN、null等)不会污染数值统计,会作为普通标签原样透传,由后端按”非数值”降级处理。 - 计数 / 去重类指标(如
signup_complete)无需传value,直接track('signup_complete')即可。 properties中除value外的其他字段都作为附加标签随事件上报,字段名自定。
调试:指标白名单提示
后台为实验声明的指标 key 会随分桶结果下发,SDK 在debug: true 时据此做拼写提示:当 track 的 eventName 不在任何运行中实验声明的指标里,控制台会 warn(提示可能拼写错误 / 大小写不符,并打印当前白名单)。
这只是调试提示——事件依然正常上报。生产模式(debug: false)下完全无此开销,不影响上报行为。
曝光事件
实验首次命中时 SDK 会自动上报曝光事件,不需要手动调用。粘性缓存中已存在的实验不重复上报。Pricing 链接自动注入
实验对象类型为price_list 时,SDK 会在返回的价格表链接中,追加以下 query 参数。业务方拿到的链接已经是注入完毕的:
来源渠道定向 (sourceChannel)
init 时可传入 sourceChannel,用于让后端按流量来源做实验定向分流(例如”仅对来自 facebook 的流量开启某实验”)。其余定向维度(设备、语言、国家、IP)由后端从 HTTP 请求头自动解析,SDK 不采集任何浏览器指纹 / UA / 地理位置信息。
- 分桶请求:写入
POST /sdk/v1/ab/assign请求体的attributes.source_channel,供后端定向规则匹配。 - Pricing 链接:对
price_list类型实验的链接追加ab_sbt_schquery 参数(与上面的值同源)。
取值与归一化规则
SDK 不做枚举校验、不做大小写转换,取值口径(如facebook / google / tiktok)由您与产品侧自行约定。携带前仅做如下处理:
稳定性:
sourceChannel 在单次会话内被视为稳定值,仅 init 时确定一次。后续不监听变化、不会因渠道变化重新拉取分桶。未携带优于截断:超长 / 非法值一律不携带,避免后端拿到被静默改写的值后与您的埋点配置产生偏差。API 参考
init(config)
初始化 SDK。在每个 SDK 实例上只能调用一次,重复调用会被忽略。立即返回,不阻塞主线程。
- 参数
config: SubotizSDKConfig - 返回
void
配置项
init(config) 接受一个 SubotizSDKConfig 对象:
onReady(onSuccess, onError?)
注册就绪回调。SDK 已就绪时同步触发,未就绪时异步触发。可重复注册多个。
- 参数
onSuccess: (experiments: SubotizExperimentMap) => voidonError?: (error: ABTestError) => void
- 返回
void
waitReady()
onReady 的 Promise 版本。
- 返回
Promise<SubotizExperimentMap> - 失败时:抛出
ABTestError(与onReady的onError等价)
isReady()
同步检查 SDK 是否已就绪。
- 返回
boolean
getExperiments()
同步获取当前所有命中实验。
- 返回
SubotizExperimentMap | nullnull—— 未初始化、未就绪、或当前没有任何命中实验Record<string, SubotizExperiment>—— 实验映射表,键为experimentId
track(eventName, properties?)
上报自定义业务事件。任意事件都会上报,是否计入实验由后端归因。
- 参数
eventName: string—— 事件名properties?: Record<string, unknown>—— 事件附加属性。其中value(有限数字)用于求和 / 均值类指标;其余字段作为附加标签透传
- 返回
void(永不抛错) - 行为
- 永远上报,不在客户端做白名单丢弃
debug: true且eventName不在后台声明的指标白名单中 → 控制台warn拼写提示(仅提示,不影响上报)init未完成时调用 → 静默跳过
forceVariant(experimentId, variantKey)
仅 debug: true 时生效。本地强制覆盖某实验的变体,便于开发期验证不同变体的 UI。
- 参数
experimentId: string、variantKey: string - 返回
void
错误处理
onReady(_, onError) 与 waitReady() 失败时返回 ABTestError:
降级策略
SDK 内置降级策略,业务方只需关心三件事:- 首次渲染走对照组 ——
await waitReady()在网络异常时最长会等timeout秒,不要用它阻塞首屏 onReady/waitReady中切换变体 —— 用户视觉冲击最小onError时保持对照组 —— 不展示空白或异常 UI
调试
打开debug: true 后,SDK 会在控制台输出请求与队列状态:
重置 SDK 状态
本地存储键
SDK 在localStorage 中使用以下键:
常见问题
SDK 加载之前业务代码已经渲染了,会拿不到实验数据?
会。让业务代码先渲染对照组,再在onReady / waitReady 中切换到变体。粘性缓存保证用户刷新后稳定看到自己的变体(首次访问会有”对照组 → 变体”的瞬时切换)。
track 调用了,后端没收到怎么排查?
按顺序检查:
abSubotiz.isReady()是否为true?未就绪时track静默跳过。- 打开
debug: true,看控制台是否有track: sending日志。 - 看浏览器网络面板有没有
POST /sdk/v1/ab/events请求。 - 响应是 4xx 还是 5xx?4xx 会被丢弃,5xx 会入队等待重发。
- 看
localStorage.ab_event_queue_*_track是否积压事件。
我传了 sourceChannel,但实验定向没生效
按顺序检查:
- 打开
debug: true,看分桶请求体attributes.source_channel是否带上了您的值。 - 确认值合法:trim 后非空、长度 < 50。超长会被忽略(控制台有
warn)。 - 确认值与后台定向规则完全一致——SDK 不做大小写转换,
Facebook≠facebook。 - 定向规则匹配在后端完成;命中与否可用
getExperiments()看是否拿到该实验。
track 的 value 没有进入求和 / 均值统计
value 必须是有限数字(typeof === 'number' 且非 NaN / Infinity)才会被纳入数值聚合。常见错误是传入字符串:track('ltv', { value: '99.9' })(字符串)会被当成普通标签,不参与 sum / average,应改为 { value: 99.9 }。
同一个实验,刷新前后变体不一致
SDK 粘性缓存保证 60 天内变体稳定。出现不一致通常是:localStorage被清除(隐私模式 / 用户主动清空)- 后台开启了用户强制分配,会覆盖粘性缓存
实验在生产没生效,怎么排查
按顺序检查:storeId是否正确(错误的 storeId 不报错,只是拿不到任何实验)- 后台实验是否处于”运行中”状态(暂停 / 草稿状态不会下发)
- 用户是否命中实验定向规则(设备 / 国家由后端从 HTTP 请求头解析)
- 用
getExperiments()看返回结果,确认是不是变体决策本身就是对照组
我想让某个用户完全不参与实验
SDK 不提供”退出实验”接口。变通方案:业务代码自行判断(如登录态 / 角色),命中条件时不读experiments 直接走默认渲染。
getExperiments() 为什么返回 null 而不是空对象
null 表示”未就绪”或”无任何命中实验”,便于做存在性判断:
Object.keys(all).length === 0。
React 服务端组件 / Edge Runtime 能用吗
不能。SDK 依赖localStorage / document.cookie / window 等浏览器接口。
浏览器兼容性
依赖原生fetch / Promise / localStorage。支持:
- Chrome / Edge ≥ 最近 2 个大版本
- Safari ≥ 最近 2 个大版本
- Firefox ≥ 最近 2 个大版本