用户对象
ABetterChoice 的每一次分组都基于一个用户对象。它包含两类信息:
- 决定调用落在哪个分组的
unit_id; - 决定调用满足哪些受众规则的可选属性。
本页描述如何在 SDK 与 HTTP API 间正确构造用户对象。
下文 Go 与 HTTP 部分代表今天已正式可用的接入方式。iOS、Android、JavaScript、C++ 部分是 形态预览,这些 SDK 在
Settings → SDK&Key下都是Coming soon。
unit_id
unit_id 是用来确定实验随机化粒度的稳定字符串。平台保证同一 unit_id 在同一实验生命周期里 始终落在同一个分组。
| 选哪种 ID | 何时用 |
|---|---|
| 用户 ID | 实验对比的是登录用户,且你有稳定的内部 ID。 |
| 会话 ID | 登录前的链路,还没有用户 ID。 |
| 设备 / 安装 ID | 移动端 App,希望分组跟着安装走。 |
在服务端或首次启动时构造一次并复用。不要把 PII 拼进 unit_id(如 user@example.com:1), 它会泄漏到曝光日志里。
ctx := abc.NewUserContext("user_id_1") // GoexpOptions.unitId = @"user_id_1"; // iOSabc.init({ projectId, unitId: "user_id_1", ... }) // JavaScript切换 unit_id
当一次会话内 unit_id 会变(用户登录、切账号),客户端 SDK 提供 switchUnitId。SDK 会为新 unit_id 重新拉取分组:
mAbcExpSDK.switchUnitId("otherUnitID", listener); // Androidabc.switchUnitId("other_unit_id"); // JavaScript服务端 SDK 不需要 switch —— 每次请求都可以构造自己的用户上下文,unit_id 本就随请求变。
属性(profiles)
属性让实验或开关只命中部分 unit_id(例如 country == "US" AND app_version >= 1.3.0)。 在调用处组装属性集,SDK 或 HTTP 会把它带上:
ctx := abc.NewUserContextWithAttrs("user_id_1", map[string]string{
"country": "US",
"app_version": "1.3.0",
})abc.init({
projectId, unitId, secretKey,
attributes: { country: "US", app_version: "1.3.0" },
});HTTP API 把属性放进请求体的 profiles map:
{
"project_id": "6666",
"unit_id": "user_id_1",
"profiles": { "country": { "user_attrs": ["US"] }, "age": { "user_attrs": ["18"] } }
}今天的内置属性包括 country、app_version、media_source、os_platform、ram_total、 first_install_version、time_since_join、user_type。自定义属性在控制台 Audiences → Attributes 中创建,详见 受众。
属性类型
| 类型 | 控制台标签 | 比较 |
|---|---|---|
| String | String | 等值、IN、NOT IN、正则。 |
| Number | Number | 等值、范围、IN、NOT IN。 |
| Version | Version | 语义化版本比较(>=、<、=)。 |
HTTP API 只接受字符串属性值 —— 数字与布尔在发送前先转字符串("18"、"true")。
粘性分组
平台对 (unit_id, layer_or_experiment_seed) 做哈希决定分组。哈希是确定性的,所以:
- 只要实验流量分配与盐值不变,同一
unit_id始终在同一组; - 在同一项目里增减其他实验,不会让该
unit_id在本实验的分组发生迁移; - 修改层的
% of global traffic会让单元跨过命中 / 未命中边界,详见 层域说明。