Files
adcloud-server/docs/events.md
T
codex-bot b43043255c
Docker test deployment / test-build-deploy (push) Successful in 4m44s
Add versioned event registry and transactional feature rules
2026-09-16 04:46:17 +08:00

123 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 事件注册表与标准特征
## 身份与凭据
本版沿用现有部署 TENANT_ID:一个部署上下文对应一个租户,该租户内按 app_id 隔离注册表和接入凭据。尚未实现客户账号登录、多租户请求路由或客户角色权限;不能把不同客户的应用都放进 default 租户并声称彼此身份图谱隔离。
平台受控后端使用 SERVICE_TOKEN 调用 POST /v1/registry/apps 创建应用,返回 collection_key、server_key、management_key(仅此时返回原值);数据库只保存带租户密钥的 HMAC。
collection_key 是 SDK 使用的受限写入凭据,不是用户认证或广告反作弊凭据。server_key 只在客户可信后端保存,用于上报服务端专属事件。management_key 用于本版控制台注册管理,页面内存保存,刷新清空;不使用 SERVICE_TOKEN,不存 localStorage。正式管理操作需 HTTPS,并最终接入客户登录。
事件请求头 X-Adcloud-Key 必须匹配 app_id;管理请求头 X-Adcloud-Management-Key 必须属于同一应用。
匿名 token 与 Master ID 沿用身份图谱;事件本身不验证邮箱、不执行登录态身份缝合。
## 公共请求字段
必选:app_id、name、event_version、event_id(UUID)、occurred_at(带时区,不能为未来或超过 90 天的历史事件)、properties。
可选:session_id、context、anonymous_token。浏览器可使用 Cookie,SDK 也可显式发送此前签发的匿名 token。
context 为有 32 KiB 上限的可选 JSON 上下文;properties 为有 32 KiB 上限的注册参数对象。业务身份/密码/设备推送 token 不应作为埋点字段;query、URL 等可能包含隐私数据,应由客户在上报前清理。
匿名签发 POST /v1/identity/anonymous 也接受可选 anonymous_token,用于 SDK 在 Cookie 不可用时恢复此前签发的匿名身份。
## 标准事件目录
下表参数都位于 properties。默认拒绝未注册参数、空字符串、类型不符和超出范围的值。quantity 为正整数;金额为最小货币单位非负整数,并要求三位大写 currency。
items 为 1–100 个商品对象,每项必选 product_id / quantity,可选 category_id / unit_price。
content.engage.action: like / save / share / comment;不采集评论正文。
content.progress 是累计进度信号,本版没有将其自动累加成时长特征。
ad.response.result: filled / no_fill / error;filled 需 delivery_id。ad.error 需 request_id 或 delivery_id。
ad.impression / ad.click 是客户端信号,本版不实现广告归属验证、有效曝光认定、反作弊或计费。
delivery_id 是单次广告投递 ID;message_id 必须是单个接收方的一次消息投递 ID,群发活动使用 campaign_id。push.open 按 message_id 统计首次打开,非每次重复打开。
push.delivery.result.status: accepted / delivered / failed,只有供应商确实提供的状态才上报。
| 标准事件 | 分类 / 含义 | 必选参数 | 可选参数 | 来源 | 业务去重键 |
|---|---|---|---|---|---|
| `page.view` | 访问与内容 / 页面访问 | page_id | referrer, title, url | SDK / 服务端 | event_id |
| `content.view` | 访问与内容 / 内容查看 | content_id, content_type | author_id, category_id | SDK / 服务端 | event_id |
| `content.engage` | 访问与内容 / 内容互动 | content_id, action | category_id, content_type | SDK / 服务端 | event_id |
| `content.progress` | 访问与内容 / 内容消费进度 | content_id, consumed_ms | duration_ms, progress_percent | SDK / 服务端 | event_id |
| `search.submit` | 访问与内容 / 发起搜索 | query | category_id, result_count | SDK / 服务端 | event_id |
| `navigation.click` | 访问与内容 / 导航点击 | target_id | destination, placement_id | SDK / 服务端 | event_id |
| `commerce.product.view` | 电商与交易 / 商品查看 | product_id | category_id, currency, price | SDK / 服务端 | event_id |
| `commerce.cart.add` | 电商与交易 / 加入购物车 | product_id, quantity | cart_id, category_id, currency, price | SDK / 服务端 | event_id |
| `commerce.cart.remove` | 电商与交易 / 移出购物车 | product_id, quantity | cart_id, category_id | SDK / 服务端 | event_id |
| `commerce.checkout.start` | 电商与交易 / 开始结算 | checkout_id, items | amount, coupon_id, currency | SDK / 服务端 | event_id |
| `commerce.order.create` | 电商与交易 / 创建订单 | order_id, items, amount, currency | checkout_id, coupon_id | 服务端 | order_id |
| `commerce.payment.success` | 电商与交易 / 支付成功 | order_id, payment_id, amount, currency | items, payment_method | 服务端 | payment_id |
| `commerce.order.cancel` | 电商与交易 / 订单取消 | order_id | reason_code | 服务端 | order_id |
| `commerce.refund.success` | 电商与交易 / 退款成功 | order_id, refund_id, amount, currency | items, reason_code | 服务端 | refund_id |
| `account.signup.success` | 注册与线索 / 注册成功 | registration_id, method | campaign_id | 服务端 | registration_id |
| `account.login.success` | 注册与线索 / 登录成功 | method | login_id | 服务端 | event_id |
| `lead.form.start` | 注册与线索 / 开始填写表单 | form_id | campaign_id, placement_id | SDK / 服务端 | event_id |
| `lead.submit.success` | 注册与线索 / 留资成功 | lead_id, form_id | campaign_id, lead_type | 服务端 | lead_id |
| `conversion.complete` | 注册与线索 / 业务转化完成 | conversion_id, conversion_type | currency, related_object_id, value | 服务端 | conversion_id |
| `ad.request` | 广告 / 请求广告 | request_id, placement_id | format, page_id | SDK / 服务端 | request_id |
| `ad.response` | 广告 / 广告返回 | request_id, result | delivery_id, latency_ms, reason_code | 服务端 | request_id |
| `ad.render` | 广告 / 广告渲染 | delivery_id | render_ms | SDK / 服务端 | delivery_id |
| `ad.impression` | 广告 / 广告展示信号 | delivery_id, impression_id | visible_ms, visible_ratio | SDK / 服务端 | impression_id |
| `ad.click` | 广告 / 广告点击信号 | delivery_id, click_id | destination_id, impression_id | SDK / 服务端 | click_id |
| `ad.video.progress` | 广告 / 广告视频进度 | delivery_id, milestone | played_ms | SDK / 服务端 | delivery_id, milestone |
| `ad.dismiss` | 广告 / 关闭广告 | delivery_id, action | reason_code | SDK / 服务端 | event_id |
| `ad.error` | 广告 / 广告错误 | stage, error_code | delivery_id, request_id | SDK / 服务端 | event_id |
| `push.permission.result` | 推送 / 推送权限结果 | status, channel | prompt_id | SDK / 服务端 | event_id |
| `push.send` | 推送 / 发送推送 | message_id, channel | campaign_id | 服务端 | message_id |
| `push.delivery.result` | 推送 / 推送投递结果 | message_id, status | failure_reason, provider_code | 服务端 | message_id, status |
| `push.open` | 推送 / 打开推送 | message_id | campaign_id | SDK / 服务端 | message_id |
| `push.click` | 推送 / 点击推送入口 | message_id, action_id | destination_id | SDK / 服务端 | message_id, action_id |
| `push.unsubscribe` | 推送 / 取消推送订阅 | channel | reason_code, subscription_id | SDK / 服务端 | event_id |
## 注册、发布、试算
公共 GET /v1/registry/catalog 返回事件字段类型、必选字段、枚举、范围,以及标准特征字典。
应用管理接口路径前缀 /v1/registry/apps/{app_id}:
- GET /events:查看应用所有事件参数版本和草稿。
- PUT /events/{name}/versions/{version}:新增或保存草稿。
- POST 同一路径 /preview:传入 properties,显示命中规则和特征增量,无事件或特征写入。
- POST /publish:产生不可变 rule_revision 并激活。
- POST /disable:拒绝新事件;已经接受的任务继续执行,原 event_id 的幂等重试仍返回原回执。
- GET /publications:列出不可变历史发布配置。
- POST /rollback:传入 revision,激活该历史规则;不重算此前接受的事件。
配置示例:
```json
{
"standard_event": "commerce.cart.add",
"description": "用户将数码商品加入购物车",
"extra_fields": {},
"required_extra": [],
"rules": [{
"conditions": [{"field": "properties.category_id", "operator": "eq", "value": "digital"}],
"effects": [{"feature": "intent.purchase.digital", "operation": "increment", "value": 1}]
}]
}
```
name 可以是客户自己的 add_cart;参数仍使用标准字段名。本版不做参数字段重命名或商品目录补全。
规则条件引用可选字段时,该字段会成为该事件定义的必选字段;上例因此必须提供 category_id。
扩展字段支持 string / integer / number / boolean;不能覆盖标准字段。发布过的参数结构不可变,改结构需要新 event_version;只改规则增量或描述可发布新 rule_revision。
规则内条件全部满足才执行;多条规则独立匹配。支持 eq / in / contains / gt / gte / lt / lte,contains 只支持字符串。
仅支持正数 increment,增量精度最多 6 位小数,单个增量 ≤100。规则只能引用平台已有特征;不运行任意代码、脚本或正则表达式。
最多 20 条规则、每条 20 个条件和 20 个增量、30 个扩展字段,配置正文最大 64 KiB。
## 持久化与计算
PostgreSQL 新增 event_apps、event_definitions、event_rule_publications、event_receipts、event_feature_contributions。元数据与冻结的请求/规则快照使用 JSONB,本地使用 SQLite JSON;已有表不改列,初始化时增加新表。
POST /v1/events 在同一事务中保存原始事件和规则任务;adcloud-events worker 在同一事务中写特征贡献、更新画像并入画像 outbox、标记任务完成。失败回滚,任务仍可重试。
同一租户下 event_id 不能用于不同事件;有业务去重键的事件还会按应用和标准事件业务键去重,避免同一支付、广告点击或推送投递重复计算。
贡献绑定原始身份节点。读取时按 Master ID 对应的所有图谱成员汇总;缝合前后不复制贡献,不重复加分。GET /v1/users/{master_id} 提供 features;GET /v1/users/{master_id}/features 提供最近 100 个贡献及其 rule_revision,使用现有可信服务鉴权。
标准特征值按事件发生时间计算窗口和上限,而非简单覆盖 attributes;不能通过画像 PATCH 修改标准特征。
adcloud-profiles 将含特征快照的画像同步 Cassandra。画像读取的 features 按关系库贡献实时计算,避免过期分数被 Cassandra 缓存延长;Cassandra 画像仍保持其版本回退机制。
没有自动打标签、历史事件重放、商品类目查询、通用累积观看时长或客户自建标准特征功能。购买次数等特征按客户映射的业务事件计数,映射时应明确最终成交的业务含义。
| 标准特征 | 展示名称 | 窗口 | 上限 |
|---|---|---|---|
| `intent.purchase.digital` | 数码购买意向 | 7 天 | 100 |
| `interest.category.digital` | 数码兴趣 | 30 天 | 100 |
| `engagement.ad.click` | 广告点击活跃度 | 7 天 | 1000 |
| `engagement.push.open` | 推送打开活跃度 | 30 天 | 1000 |
| `commerce.purchase.count` | 购买次数 | 30 天 | 10000 |
| `conversion.lead.count` | 留资次数 | 30 天 | 10000 |
## 兼容与部署
EVENT_REGISTRY_REQUIRED 默认 true。旧版未带应用字段的埋点将返回 422,应先创建应用、注册并发布事件、更新 SDK。仅本地旧代码联调可设置 false;一旦带 app_id 仍必须通过注册表校验。平台专属结果事件不会因为兼容开关而允许 collection_key 上报。
Compose 已增加常驻 event-worker;部署 smoke 创建合成应用、注册加购、发送与重试事件,并验证 +1、身份缝合及 Cassandra 当前版本。临时 CI 对 SQLite 与真实 PostgreSQL 都测试注册、参数、去重、规则版本、worker 回滚和窗口。