# WePlay 活动埋点文档生成指南

本 guide 把「运营文档 + 数据需求文档 + 活动配置中心」转换为标准格式的活动埋点文档。
**本文件是规则的唯一权威源**。

参考文件：
- [活动常用埋点.md](./活动常用埋点.md)：标准组件键值模板库；开头有「上报端与时区处理说明」
- [activitytotal_fields.md](./activitytotal_fields.md)：临时事件字段的唯一允许清单；表中不存在的字段一律不得新增

---

## 1. 生成流程（必须按顺序执行）

### 步骤 1：获取并理解输入材料

两份输入文档**都必须**提供。飞书链接使用 `lark-cli docs +fetch --doc "<文档URL或token>" --doc-format markdown --scope full --as user` 读取为 Markdown；执行前按 `lark-doc` skill 读取 `lark-shared` 与 `lark-doc-fetch.md` 的最新说明。禁止使用已废弃的 `/feishu2md`。

| 材料 | 作用 |
|------|------|
| 运营活动文档 | 活动玩法、数值设计、道具/礼包 ID、价格 |
| 埋点数据需求文档 | 需要跟踪的业务模块和指标方向 |

阅读后需理解：活动各页面/模块的玩法规则、数据需求方向、礼物/道具 ID 与价格。

### 步骤 2：查询活动配置中心（必须！）

1. **向用户确认活动 ID 和区服代号**（如 act_id=`6193`，region=`C`）。区服代号对照见 [第 5.3 节](#53-区服代号对照)。
2. **调用 `get_key_api.py` 查询配置中心**，获取活动完整配置（奖池、任务、碎片、榜单、兑换等）：
   ```python
   from get_key_api import get_key
   get_key(key="6193", region="C")   # region 取用户确认的区服代号
   ```
   详见 [get_key_api.py](../../scripts/get_key_api.py)。

   查询后**必须提取以下字段**：

   **基础字段（所有活动必取）：**

   | 配置字段 | 对应埋点属性 | 说明 |
   |---------|------------|------|
   | `name` | `activity` | 活动对外展示名；**不得标 ❓，直接从配置取值** |
   | `activity_name` | `activity_name` | 活动内部标识名，同一活动所有埋点保持一致 |

   **礼包字段（配置含 `gift_pkg` 时额外执行）：**

   若 `get_key` 返回的配置中存在 `gift_pkg.list`，调用 `get_gift_pkgs(act_id, region)` 补充查询礼包信息：

   ```python
   from get_key_api import get_gift_pkgs
   get_gift_pkgs(act_id="6897", region="A")
   ```

   | 返回字段 | 对应埋点属性 | 说明 |
   |---------|------------|------|
   | `pkg_id` | `pkg_id` | 连锁礼包 ID，填入 ActivityTotal 埋点；逐礼包列出，**禁止留 ❓** |
   | `goods_id` | `goods_id` | 宣发礼包弹窗曝光/点击及 `Pay` 事件的 `goods_id`；**直接取此处，禁止等运营文档** |
   | `description` | `gift_package_name`（Pay 事件）/ 注释 | 礼包名称；`Pay` 事件字段为 `gift_package_name`，同时填入「活动核心资源 ID」表 |
   | `price` | 注释 | 礼包价格，填入「活动核心资源 ID」表 |

3. **识别配置里每个玩法用的组件**：逐一看配置中各玩法分别对应哪类组件——任务（task）、抽奖（lottery）、碎片（chip）、兑换（collect_exchange）、榜单（rank）、礼盒（gift_box）、盲盒（blind_box）等。**配置中存在的玩法，一律按其配置实际使用的组件来埋点。**
4. ⚠️ **配置中心优先级高于通用组件匹配经验**：同一玩法在不同活动可能用不同组件实现，**必须以配置为准，不要凭惯性套组件**。
5. ⚠️ **写集合页「礼物」埋点前，先逐个礼物确认玩法类型，再对组件**：先判断每个礼物属于小礼物爆大礼物 / 礼盒 / 盲盒 / 星级礼盒 / 恋恋魔方 / 礼物转转机 / 大礼物等哪一类（**禁止凭价位或名字套组件**），确认后去 [活动常用埋点.md](./活动常用埋点.md) 取该玩法专属组件字段。
6. **可选保底按实际功能裁剪**：组件库中的保底模板不是必写清单。只有运营文档或活动配置明确存在对应保底功能时，才生成礼盒保底 `gift_box / guarantee` 或抽奖保底 `lottery / guarantee`；玩法没有该功能时不得生成对应保底埋点。材料无法确认时标记待确认，不得仅因组件库存在模板而补写。

### 步骤 3：按数据需求书写埋点（需求不遗漏）

1. **以数据需求文档为纲逐条覆盖**：把数据需求文档里的每个跟踪点 / 指标方向，逐一落成对应埋点，**做到需求项无遗漏**。
2. 匹配标准组件、设计临时事件，标注标签（见 [第 3.4 节](#34-标签规则)）。
3. 从配置中提取具体值（task_id、chip_id、奖池名称等）填入属性，**禁止泛化占位描述**；暂不确定的用 ❓ 标注"待确认"。
4. **核心区分字段值用红色字体标识**：对「用于区分/定位其它埋点或子玩法」的核心字段值，在飞书文档中用红色字体高亮，方便开发/测试一眼锁定必须校验的关键值。Lark Markdown 写法：`<text color="red">值</text>`（只给**值**上色，字段名和注释不上色）。**必须标红的核心值**包括（但不限于）：
   - 临时事件的 `activity_type`（temporary_event）与 **`action` 值**
   - 抽奖组件的 **`lottery_name`**、`box_type` 值
   - 任务组件的 **`task_id`**、**`stage`** 值
   - 碎片组件的 `chip_id` 值
   - 礼物 / 道具 / 礼包等 **id 值**（gift_id、reward_id、goods_id 等）
   - 充值优惠等组件的 `action` 值（use_coupon / incr_coupon 等）

   示例：`action = <text color="red">send_blessing_gift</text>，STRING`、`**task_id** = <text color="red">2</text>，NUMBER`、`lottery_name = <text color="red">春日奖池</text>，STRING`。
5. **按页面拆分结构**：页面作飞书一级标题（`#`），模块作二级标题（`## 1.1`/`## 2.1`…），单条埋点作三级标题（`### 1、`/`### 2、`…），逐级体现「页面 → 模块 → 埋点」层级（见 [第 3.1 节](#31-文档结构模板)）。
6. **每条埋点追加「开发/测试进度」表**（**活动宣发章节除外**）：紧跟该埋点的事件属性之后，用 [第 3.1 节模板](#31-文档结构模板)里的 `<lark-table>` 进度表；表头按开发方选——服务端埋点（ActivityTotal 等）用 `服务器`，前端埋点（ViewActivity / ClickActivity / AppClick / ta_pageview / AppViewScreen 等客户端/H5 事件）用 `前端`。

### 步骤 4：检查审核后输出

书写完成后**必须自检审核**，三条主线缺一不可，通过后再输出。

**审核必须细到「每一个埋点、每一个字段」逐条过，不允许整体扫一眼放过。**

1. **逐埋点 × 逐字段规范核验**（对照 [第 3.5 节格式强制规范](#35-格式强制规范每条必须符合) 与 [第 4 节编写规则](#4-编写规则)）。对每条埋点：
   - **事件名称**正确（ActivityTotal / ViewActivity / AppClick / Pay 等）
   - **事件用户**明确且正确（送礼人/收礼人/购买者等，见 [第 2.2 节](#22-常见模块--组件--事件用户对应表)）
   - **标签**（【组件】/【新增】/无）标注正确
   - ActivityTotal 含 `act_id` / `activity` / `activity_name`（例外：`use_coupon` **不带任何活动信息**——无 act_id/activity/activity_name）

   逐字段再核：
   - **字段名**与 `活动常用埋点.md` 完全一致，无错名、无自创、无往组件塞自定义字段
   - **【新增】临时事件字段必须逐一对照 [activitytotal_fields.md](./activitytotal_fields.md)**：每个字段都必须存在于速查表并直接复用原字段名，禁止重命名或新造；速查表不存在的字段不得写入正式埋点，只能列入「字段注册阻塞清单」，待完成注册后再补。**并核对每个临时事件下方是否已追加「字段查表」留痕行**，缺失则补
   - **字段值**：核心区分值填的是**配置实际值**（非占位描述），不确定项已 ❓ 标注；该标红的核心值已用 `<text color="red">值</text>` 标红
   - **可选保底**：礼盒保底与抽奖保底均有运营文档或配置依据；没有对应功能时未生成 `gift_box / guarantee`、`lottery / guarantee`
   - **`,TYPE` 类型**与值匹配（字符串值不能标 NUMBER，反之亦然）
   - **注释含义**与配置/玩法一致，无张冠李戴
   - 字段是否**有遗漏**：组件该带的关键字段是否齐（如抽奖必带 `use_lottery_coins`、`lottery_name`；任务必带 `task_id`/`stage`）
   - **进度表已加且表头开发方正确**：每条埋点（活动宣发章节除外）事件属性后已追加 `<lark-table>` 进度表，服务端用 `服务器`、前端用 `前端`；宣发章节未加
   - 格式：字段间空行、不用 `-`/表格
2. **玩法语义是否准确**：每条埋点的 `action`、事件用户、触发时机是否真实反映配置玩法，不靠惯性想当然。
3. **数据需求是否有遗漏**：逐条回扫数据需求文档，确认每个需求点都有对应埋点且字段够算；配置中存在、但需求文档未提及的玩法，也要确认是否需要补埋点。
4. 审核通过后先将正文保存为 Markdown 文件，再按 `lark-doc` skill 读取 `lark-shared`、`lark-doc-md.md`、`lark-doc-style.md`、`lark-doc-create-workflow.md` 与 `lark-doc-create.md`，然后执行 `lark-cli docs +create --as user --doc-format markdown --parent-token SplTfSaLelLVXtdh1FfcrCgnn6c --title "活动名称—数据需求埋点文档" --content @/absolute/path/to/document.md` 创建飞书文档。禁止使用已废弃的 `/lark-doc` 或 `--folder-token`。

---

## 2. 事件类型与组件匹配

查询配置中心后，按以下**优先级顺序**为每个玩法定埋点：

1. **配置中心已用的组件优先**：先确定配置中心实际用了哪些组件——这些玩法直接套用配置所用的组件，标【组件】。**配置优先级最高，不凭惯性套组件**。
2. **剩余玩法用组件匹配**：配置未直接体现的玩法，按 `activity_type + action` 匹配标准组件（见 [第 2.2 节](#22-常见模块--组件--事件用户对应表)），匹配到的标【组件】。
3. **匹配不到再写临时事件**：标准组件覆盖不了的玩法，设计临时事件（`temporary_event`），标【新增】（见 [第 2.3 节](#23-临时事件埋点规范)）。

### 2.1 宣发入口事件清单（非 ActivityTotal）

宣发入口事件不打 ActivityTotal，按下表的客户端/H5 事件编写，标题不加标签：

| 场景 | 事件名称 | 关键属性 |
|------|---------|---------|
| 弹窗曝光 | ViewActivity | activity_id, coupon_id, is_auto=1 |
| 弹窗点击 | ClickActivity | activity_id, coupon_id, scene |
| 语音房入口曝光 | ViewActivity | activity_id, is_auto=0 |
| 语音房入口点击 | AppClick | screen_name="语音房公屏", btn_name="运营资源位" |
| 首页 icon 点击 | AppClick | $screen_name="首页", btn_name="活动" |
| H5 页面曝光 | ta_pageview | #url, #url_path |
| 法官消息曝光 | SendFaguanMsg | message_type, message_id, act_id |
| 法官消息点击 | AppClick | screen_name="法官聊天页", btn_name="法官消息" |
| 礼包弹窗曝光 | AppViewScreen | screen_name="礼包弹窗", goods_id（取 `get_gift_pkgs()` 返回的 `goods_id`） |
| 礼包购买点击 | AppClick | btn_name="购买礼包", goods_id（取 `get_gift_pkgs()` 返回的 `goods_id`） |

> ⚠️ 客户端/H5 事件（ViewActivity、ClickActivity、AppClick、ta_pageview 等）上报时区与服务端不同，分析需做时区转换；详见 `活动常用埋点.md` 开头「上报端与时区处理说明」。

### 2.2 常见模块 → 组件 → 事件用户对应表

匹配组件时除了 `activity_type + action`，还要确定**事件用户**。

> **组件字段名必须与 [活动常用埋点.md](./活动常用埋点.md)（标准组件键值模板库）完全一致，禁止自创**；

**礼物面板（ActivityTotal）**

| 玩法 | activity_type | action | 事件用户 |
|------|--------------|--------|---------|
| 小礼物触发大礼物（汇总上报） | gift | send_gift | **送礼人** |
| 小礼物随机触发大礼物 | gift | random | **送礼人** |
| 小礼物保底触发大礼物 | gift | guarantee | **送礼人** |
| 小礼物触发红包雨 | gift | red_packet | **送礼人** |
| 开礼盒 | gift_box | gift_box_get_reward | 收礼人 |
| 礼盒保底 | gift_box | guarantee | 收礼人 |
| 开盲盒 | blind_box | blind_box_get_reward | 收礼人 |

> ⚠️ **三类礼物玩法的组件严格对应各自场景，不可混用：**
> - `gift`（send_gift / random / guarantee）**仅用于「小礼物爆大礼物」玩法**，事件用户为送礼人；**不可**写到礼盒、盲盒、大礼物等其他场景。
>
>   这三个 action **必须成套埋全**，三者关系：**`send_gift` = 触发爆出大礼物的汇总上报（随机爆出 + 保底爆出都上报），即 `send_gift` 次数 = `random` 次数 + `guarantee` 次数**；`random` = 随机爆出大礼物，`guarantee` = 保底爆出大礼物。三条结构一致，`gift_id` 均为爆出的**大礼物**ID，`origin_gift_id` 为原始**小礼物**ID。
>
>   ⚠️ **易错点：`send_gift` 不是"每次送小礼物上报"，它只在爆出大礼物时上报；不要因为它名字像"送礼"就误解。**
>
>   ⚠️ **「累计送礼满阈值必触发」本身就是保底（guarantee），是正常触发的主上报口径，不是"预期不触发"。** 典型如「送小礼物累积满100个必爆大礼物」——满阈值触发即保底，核心走 `guarantee`（condition=阈值，如100）；`random` 对应「单次直接随机爆出」。运营文档里「在此不设保底」常指「无额外固定次数兜底」，**不代表玩法无保底**；累计值满阈值触发仍是保底，需用 guarantee 上报。
>
> - `gift_box`（gift_box_get_reward / guarantee）**仅用于「礼盒」**，事件用户为收礼人。`gift_box / guarantee` 仅在礼盒实际配置了保底功能时生成；没有礼盒保底则只写开礼盒主事件，不写保底事件。
>
> - `blind_box`（blind_box_get_reward）**仅用于「盲盒」**，事件用户为收礼人。
>
> - 大礼物等其余礼物若无独立爆奖玩法，走基础 `CoinChange`/`SendGift` 等事件，不套用上述活动组件。
>
> - 星级礼盒、恋恋魔方、礼物转转机等特殊玩法有各自独立组件，详见 [活动常用埋点.md](./活动常用埋点.md) 对应节（§15 星级礼盒、§16 恋恋魔方、§17 礼物转转机）。

**抽奖页（ActivityTotal）**

| 玩法 | activity_type | action | 事件用户 |
|------|--------------|--------|---------|
| 购买抽奖币 | chip | buy_collect_chip | 购买用户 |
| 抽奖 | lottery | do_wheel_lottery | 抽奖用户 |
| 抽奖保底 | lottery | guarantee | 抽奖用户 |
| 获得/消耗碎片 | chip | add_collect_chip | 用户 |
| 碎片兑换 | chip | collect_exchange | 用户 |

`lottery / guarantee` 仅在抽奖玩法实际配置了保底功能时生成；没有抽奖保底则只写抽奖主事件，不写保底事件。不得因为组件库中存在保底模板而默认补齐。

**充值优惠（ActivityTotal）**

| 玩法 | activity_type | action | 备注 |
|------|--------------|--------|------|
| 使用充值优惠 | charge_coupon | use_coupon | **不带任何活动信息**：无 act_id / activity / activity_name（账号级充值优惠事件，仅 times/accu_times/original_coins/coins/rebate_rate） |
| 获得额外固定优惠 | charge_coupon | incr_coupon | 带完整活动信息（act_id / activity / activity_name / incr_times） |
| 获得额外动态/随机优惠 | charge_coupon | incr_random_coupon | 带完整活动信息（act_id / activity / activity_name / incr_times） |

**任务 & 榜单（ActivityTotal）**

| 玩法 | activity_type | action | 事件用户 |
|------|--------------|--------|---------|
| 完成任务 | task | complete_task | 用户 |
| 领取任务奖励 | task | recv_reward | 用户 |
| 榜单结算 | rank | rank_checkout | 上榜用户 |
| 总榜每日上报 | rank | total_rank_daily | 上榜用户 |

**其他（ActivityTotal）**

| 玩法 | activity_type | action | 事件用户 |
|------|--------------|--------|---------|
| 签到 | sign_in | do_sign_in | 用户 |
| 金币直购 | subscribe | subscribe_pay | 购买用户 |

**WePlay 扩展组件**（详见 [活动常用埋点.md](./活动常用埋点.md) 对应节）：

| 组件 | 活动常用埋点.md 节号 |
|------|-----------------|
| 组队 | §4 |
| 拉新召回 | §6 |
| Bingo 玩法 | §14 |
| 星级礼盒 | §15 |
| 恋恋魔方 | §16 |
| 礼物转转机 | §17 |
| 道具红包雨 | §18 |
| 常规红包雨 & buff 红包雨 | §19 |
| 金币瓜分 | §22 |
| 农场组件 | §23 |
| 东南亚 Bingo | §24 |
| 投票组件 | §25 |
| 道具工坊 | §26 |
| 抽奖自选奖励 | §27 |
| 连锁礼包 | §28 |
| 挖矿组件 | §29 |

### 2.3 临时事件埋点规范

配置中不存在的玩法（特殊累消规则、自定义奖励行为等），**以及组件模板装不下的额外字段需求**，都用临时事件承载：

- `activity_type` = `temporary_event`
- `action` = 自定义，需清晰表达业务含义（如 `wealth_withdraw`、`custom_reward`）
- **字段白名单**：临时事件的每个字段都必须存在于 [activitytotal_fields.md](./activitytotal_fields.md)，语义相同的字段直接复用；速查表不存在的字段一律不得新增、不得写入正式埋点文档
- **缺字段处理**：数据需求确实依赖未注册字段时，将其列入「字段注册阻塞清单」，说明业务语义与预期类型；待字段完成注册并进入速查表后再补入埋点，不得先写占位字段
- **查表结论必须留痕（强制）**：每个临时事件下方追加一行查表说明，列出本事件全部字段并统一写「复用 `字段名`」；同时明确「无新增字段」。

  示例：`> 字段查表：复用 act_id / activity / activity_name / action / gift_id / coin / source；无新增字段。`

> ⚠️ **组件字段不够用时的正确做法**：标准组件（gift / lottery / chip / task / gift_box 等）的字段集是固定的，**严禁直接往组件事件里加自定义字段**（如给 `gift / random` 加 `is_buff`）。需要额外信息时可另起 `temporary_event`，但仍只能使用速查表中的已有字段；无法用已有字段表达时按缺字段阻塞处理。

---

## 3. 输出格式

### 3.1 文档结构模板

**以页面为顶层分节，页面内按模块展开**。章节用 `#` 一级标题，模块用 `## 1.1` 二级标题，单条埋点用 `### 1、` 三级标题：

```markdown
# [活动名称] — 数据需求埋点文档

## 活动基础信息
| 项目 | 内容 |
|------|------|
| 活动名称 | xxx |
| 活动时间 | xxx |
| 集合页活动 ID | xxx |
| 玩法页活动 ID | xxx |（若无玩法页则省略）
| activity 标识 | xxx |

### 活动核心资源 ID
（道具ID等从运营文档提取；连锁礼包从 `get_gift_pkgs()` 返回结果填写）

**连锁礼包（有礼包玩法时填写）：**

| pkg_id | 礼包名称 | 商品ID (goods_id) | 价格 |
|--------|---------|-----------------|------|
| 783 | S1第一赛段1号礼包 | 80 | 12元 |
| 784 | S1第一赛段2号礼包 | 82 | 30元 |
| ... | ... | ... | ... |

---

# 一、活动宣发

<!-- 活动宣发章节的埋点不加进度表 -->

## 1.1 活动入口

### 1、活动入口曝光（ViewActivity）

事件名称：ViewActivity

埋点场景：活动入口曝光时上报

事件用户：曝光用户

上报端：客户端

事件属性：

activity_id = 对应活动id，NUMBER

coupon_id = 对应优惠码id（实际为后台首页弹窗id），STRING

is_auto = 是否自动弹出（1：是，0：否），NUMBER

---

# 二、集合页

## 2.1 充值

### 1、【组件】获得额外充值优惠（charge_coupon / incr_coupon）

事件名称：ActivityTotal

埋点场景：xxx 时上报

事件用户：xxx

事件属性：

activity_type = charge_coupon，STRING

action = incr_coupon，STRING

act_id = 活动id，NUMBER

activity = 活动标识，STRING

activity_name = 活动名称，STRING

incr_times = 额外充值优惠次数，NUMBER

<lark-table column-widths="240" header-row="true">
<lark-tr>
<lark-td>

服务器

</lark-td>
</lark-tr>
<lark-tr>
<lark-td>

- [ ] 是否完成

</lark-td>
</lark-tr>
<lark-tr>
<lark-td>

- [ ] 是否自测

</lark-td>
</lark-tr>
<lark-tr>
<lark-td>

- [ ] 是否测试

</lark-td>
</lark-tr>
</lark-table>

# 三、玩法页

## 3.1 抽奖币购买
## 3.2 每日任务
## 3.3 抽奖
## 3.4 阶段奖励
## 3.5 榜单
...
```

进度表说明：每条埋点（活动宣发章节除外）的事件属性之后必须追加「开发/测试进度」表。必须用 `<lark-table>`（普通 Markdown 表格在飞书里 checkbox 不渲染）；服务端埋点（ActivityTotal 等）表头用 `服务器`，前端埋点（ViewActivity / ClickActivity / AppClick / ta_pageview / AppViewScreen 等客户端/H5 事件）把表头 `服务器` 换成 `前端`，其余三行 checkbox 不变；宣发章节不加。

### 3.2 页面拆分原则

- 活动宣发（入口曝光/点击、页面浏览、法官消息、资源位、礼包弹窗）→ `# 一、活动宣发`，放在最前；按活动实际接入渠道取舍，未接入的渠道可省略
- 集合页（充值、礼包、累消、各礼物玩法）→ `# 二、集合页`
- 玩法页（抽奖、任务、榜单、阶段奖励等）→ `# 三、玩法页`
- 跨页面的独立玩法 → 归入最相关页面，或作独立章节 `# 四、xxx`
- 活动只有单一页面时，按实际页面数量拆分，不强行凑两章

### 3.3 单条埋点格式与属性书写示例

每条埋点 4 个必填项（一行一个）：

| 字段 | 说明 |
|------|------|
| 事件名称 | 事件名，如 `ActivityTotal`、`ViewActivity`、`AppClick`、`Pay` 等 |
| 埋点场景 | 何时触发上报，需描述清楚触发条件 |
| 事件用户 | 事件打在谁身上（送礼人/收礼人/房主/中奖用户等） |
| 事件属性 | `key = value //注释，TYPE` 格式，一行一个属性 |

属性书写格式：`key = value //注释说明，TYPE`。完整示例（抽奖组件）：

```
事件名称：ActivityTotal
埋点场景：用户在春日奖池抽奖时上报
事件用户：抽奖用户
事件属性：
activity_type = lottery，STRING
action = do_wheel_lottery，STRING
act_id = 活动id，NUMBER
activity = 春日樱花节 //活动标识，STRING
activity_name = 春日樱花节(A) //活动名称，STRING
lottery_name = <text color="red">春日奖池</text> //奖池名称，STRING
box_type = <text color="red">normal</text> //奖池类型，STRING
use_lottery_coins = 6 //消耗抽奖币数量，NUMBER
reward_id = 奖励id，NUMBER
reward_name = 奖励名称，STRING
activity_version = 活动测试版本，NUMBER
```

### 3.4 标签规则

| 标签 | 含义 |
|------|------|
| 【组件】 | `activity_type + action` 匹配标准组件 |
| 【新增】 | 需开发新增上报的全新临时事件（历史从未有过埋点） |
| 无标签 | Pay / CoinChange 等基础事件，不属于活动组件，标题前不加任何标签 |

### 3.5 格式强制规范（每条必须符合）

1. **事件属性字段格式**：每行 `field = value，TYPE`，**不加 `-` 列表符号**，不用表格；**每个字段之间必须有一个空行**（否则飞书渲染时所有行会合并为一段）。
2. **文档必须有大标题**：`# [活动名称] — 数据需求埋点文档`。
3. **注释行 `> 内容`**：只写开发需要知道的简短规则，不写分析口径。**两条强制**：
   - ① **多条注释之间必须加空行**（每条 `> ...` 独立成块，块与块之间空一行）。飞书会把**连续无空行的多行 `>` 合并渲染成一整段**，挤成一坨、可读性极差。
   - ② **多阶段/多档位/奖励明细等结构化信息一律用表格**（见 [第 4.2 节](#42-属性补充写法)），**禁止用 `>` 逐行堆砌**。
4. **核心区分字段值标红**：用于区分/定位其它埋点或子玩法的核心值（临时事件 action、lottery_name、task_id、stage、chip_id、gift_id/reward_id/goods_id 等 id），在飞书文档中用 `<text color="red">值</text>` 给**值**上色（字段名、注释、`,TYPE` 不上色）。详见 [步骤 3 第 4 点](#步骤-3按数据需求书写埋点需求不遗漏)。
5. **每条埋点追加「开发/测试进度」表**：紧跟事件属性之后用 `<lark-table>` 进度表（模板见 [第 3.1 节](#31-文档结构模板)），表头按开发方选 `服务器`/`前端`；**活动宣发章节的埋点不加**。详见 [步骤 3 第 6 点](#步骤-3按数据需求书写埋点需求不遗漏)。

---

## 4. 编写规则

### 4.1 核心规则速查

1. **每个 ActivityTotal 必须含 `act_id`、`activity`、`activity_name`**（例外：`use_coupon` 不带任何活动信息——无 act_id/activity/activity_name；`incr_coupon`/`incr_random_coupon` 带完整活动信息）。
2. **按 `activity_type + action` 匹配标准组件**（组件键值模板见 [活动常用埋点.md](./活动常用埋点.md)）；临时事件标【新增】；Pay/CoinChange 等基础事件不加标签。
3. **填入具体值，禁止泛化描述**：`task_id`、`chip_id`、`lottery_name`、`box_type`、`condition`（保底次数）等关键字段必须写配置中心查到的实际值，不能写"任务ID""奖池名称"等占位。
4. **不确定字段用 ❓ 标注"待确认"**。
5. **不写指标口径、SQL 模板**等分析内容，只写埋点规范。
6. **区分事件用户**（送礼人/收礼人、购买者/使用者等，见 [第 2.2 节](#22-常见模块--组件--事件用户对应表)）。
7. **组件埋点字段必须与 `活动常用埋点.md` 完全一致：既不得改字段名，也不得在组件事件里新增/自造字段。** 若业务需要组件模板之外的额外字段，**必须单独新开一个 `temporary_event`** 来承载（见 [第 2.3 节](#23-临时事件埋点规范)）。
8. **临时事件字段只允许使用 [activitytotal_fields.md](./activitytotal_fields.md) 中的已注册字段；不存在的字段一律不得新增。**
9. **能合并的埋点不拆写**（见 [第 4.3 节](#43-合并规则减少冗余条目)），尤其同玩法碎片/代币获得与消耗优先合并为 1 个 `chip/add_collect_chip` 埋点。
10. **【新增】临时事件只保留数据需求明确要求的属性**，避免把可推算、测试调试、纯关联字段写进埋点（见 [第 4.4 节](#44-临时事件属性精简避免冗余)）。
11. **礼盒保底与抽奖保底按实际功能生成**：没有对应保底功能时，不写 `gift_box / guarantee` 或 `lottery / guarantee`；组件库存在模板不等于活动具备该功能。

### 4.2 属性补充写法

**关键字段加粗。** 标准组件埋点中，**区分业务场景的关键字段**用 `**field**` 加粗，便于开发/测试识别必须验证的字段：

| 组件 (activity_type) | 需加粗的字段 |
|---------------------|------------|
| chip（碎片） | **chip_id**、**source** |
| task（任务） | **task_id**、**stage** |

```
**chip_id** = 碎片id，NUMBER
**source** = 礼盒开出，STRING
**task_id** = 任务id，NUMBER（活动内自增 1~4）
**stage** = 1 //任务阶段，NUMBER
```

**多阶段/多档位对应关系一律用表格。** 对有多阶段、多档位的玩法，在埋点属性之后**用 Markdown 表格**补充对应关系，**禁止用 `>` 引用块逐行堆砌**（飞书里会挤成一段）：

```markdown
**累消阶段对应**（task_id=1）：

| stage | 累消门槛 | 奖励 | 奖励 ID |
|---|---|---|---|
| 1 | 10,000 金币 | 礼物卡 ×2 | 1711487 |
| 2 | 50,000 金币 | 戒指礼物卡 ×1 | 1721241 |
| ... | ... | ... | ... |
```

### 4.3 合并规则（减少冗余条目）

**规则一：complete_task + recv_reward 合并写。** 同一任务的"完成"和"领取"结构相同，合并为一条，`/` 分隔 action：

```
事件名称：ActivityTotal
埋点场景：完成任务时上报 complete_task；领取奖励时上报 recv_reward
事件属性：
activity_type = task，STRING
action = complete_task / recv_reward，STRING
act_id = 6193，NUMBER
activity = 春日樱花节，STRING
activity_name = 春日樱花节(A)，STRING
**task_id** = <text color="red">2</text>，NUMBER（每日送礼任务）
**stage** = <text color="red">[1~5]</text>，NUMBER（1=1000个 ... 5=5000个）
period_type = 1 //每日累计，NUMBER
```

**规则二：多个同结构礼物合并写。** 多个礼物共享同一事件结构（如 CoinChange 送礼），合并为一条，`|` 枚举 gift_id：

```
事件名称：CoinChange
事件属性：
gift_id = [1211847 | 1211850 | 1211858]，NUMBER
          （春日礼物 A | 春日礼物 B | 春日礼物 C）
```

**规则三：同玩法碎片/代币获得与消耗合并写。** 同一玩法内的碎片/代币获得与消耗，应合并为 1 个 `chip/add_collect_chip` 埋点承载，避免拆成多条增加埋点冗余：

- `source` 字段区分获得/消耗的具体场景（如 `charge_accu` 累充获得 / `refresh_lottery` 刷新消耗）
- `chip_value` 用正负区分：`> 0` 表示获得，`< 0` 表示消耗

```
事件名称：ActivityTotal
埋点场景：累充门槛获得碎片 / 消耗碎片刷新晶石时上报
事件属性：
activity_type = chip，STRING
action = add_collect_chip，STRING
act_id = 6193，NUMBER
activity = 星图寻宝，STRING
activity_name = star_treasure，STRING
**source** = <text color="red">charge_accu</text> / <text color="red">refresh_lottery</text>，STRING（累充获得 / 刷新消耗）
**chip_id** = <text color="red">1001</text>，NUMBER（星轨碎片）
chip_name = 星轨碎片，STRING
chip_value = 数量，NUMBER（>0 获得，<0 消耗）
num = 70 //碎片单价（金币价值），NUMBER
```

典型合并场景：
- 累充碎片：获得（累充门槛）+ 消耗（刷新晶石）
- 点球大战球票：获得（NPC 开奖）+ 消耗（兑换商店）
- 礼盒星光币：获得（点亮道具）+ 消耗（开扭蛋机）
- 盲盒星尘碎片：获得（爆 2000+ 礼物）+ 消耗（开星核宝函）

**不可合并的情况：**
- 事件用户不同（如送礼人 vs 收礼人）
- 有意义的字段差异（如不同保底次数、不同奖池奖励）
- 需要单独分析的场景（如区分首次/非首次）
- 不同玩法的不同碎片类型（`chip_id` 不同）必须独立埋点
- `collect_exchange` 是兑换商店专用标准组件，与 `add_collect_chip` 是不同 action，不合并

### 4.4 临时事件属性精简（避免冗余）

对于 `活动常用埋点.md` 中没有对应组件的【新增】临时事件，只保留数据需求文档中明确要求统计的属性。不要把 `lottery_id`、`is_private`、`combo_num`、`refresh_times` 等非核心字段默认塞进临时事件。

判断标准：
- 属性能从数据需求中找到对应指标：保留
- 属性可由其他事件推算：不新增（如盲盒进度可由 `blind_box_get_reward` 的 `guarantee` / `lottery_stage` 推算）
- 属性是测试/调试用：不新增
- 属性是非业务关联字段：不新增（如仅用于关联抽奖流水的 `lottery_id`）

冗余写法：

```
事件名称：ActivityTotal
事件属性：
activity_type = temporary_event，STRING
action = grand_slam，STRING
act_id = 6193，NUMBER
activity = 星图寻宝，STRING
activity_name = star_treasure，STRING
box_type = common / limited，STRING
lucky_point = 2000，NUMBER
player_num = 4，NUMBER
layer = 1 / 2 / 3，NUMBER
lottery_id = uid_xxx_时间戳，STRING
```

精简写法（数据需求仅要求统计小奖池、大奖池分别触发大满贯玩法的人数、次数）：

```
事件名称：ActivityTotal
事件属性：
activity_type = temporary_event，STRING
action = <text color="red">grand_slam</text>，STRING
act_id = 6193，NUMBER
activity = 星图寻宝，STRING
activity_name = star_treasure，STRING
box_type = <text color="red">common</text> / <text color="red">limited</text>，STRING（小奖池 / 大奖池）

> 字段查表：复用 act_id / activity / activity_name / action / box_type。
```

删除【新增】埋点的判断：
- 数据需求未要求：直接不新增（如奖池升级可由其他事件 `lottery_stage` 推算）
- 数据需求未要求且无业务影响：不新增（如纯表现层自选、扭蛋机奖池重置）

### 4.5 组件字段名速查表（禁止自造）

书写组件埋点属性时，**必须**对照 [活动常用埋点.md](./活动常用埋点.md) 核查字段名，常见错误：

**task（complete_task / recv_reward）**

| 正确字段名 | ❌ 错误写法 | 说明 |
|-----------|-----------|------|
| `stage` | ~~`stage_id`~~ | 任务阶段，NUMBER |
| `period_type` | ~~`period`~~ | 累计方式（0=活动累计，1=每日），NUMBER |

**chip（add_collect_chip）**

| 正确字段名 | ❌ 错误写法 | 说明 |
|-----------|-----------|------|
| `chip_value` | ~~`chip_num`~~ | 碎片数量，正数=获得，负数=消耗 |

---

## 5. WePlay 特有注意事项

### 5.1 货币与购买事件区分（重要！）

| 场景 | 正确事件 | 说明 |
|------|---------|------|
| 用真实货币（人民币/美元等）购买礼包 | `Pay` | `goods_id` + `gift_package_name` 区分商品，无 act_id；两个字段均从 `get_gift_pkgs()` 返回值取（`goods_id` → `goods_id`，`description` → `gift_package_name`） |
| 金币直购道具/礼物卡 | `ActivityTotal subscribe_pay` | 走活动购买组件 |
| 送礼/道具消耗货币流水 | `CoinChange` | 活动归因通过 sub_type=活动id（仅充值返金场景）或时间范围 |

### 5.2 activity / activity_name 字段规则

所有 ActivityTotal 事件必须包含 `act_id`、`activity`、`activity_name`；例外：充值优惠 `use_coupon` **不带任何活动信息**（无 act_id/activity/activity_name，为账号级充值优惠事件，仅 times/accu_times/original_coins/coins/rebate_rate）。

| 字段 | 来源 | 说明 |
|------|------|------|
| `activity` | 配置中心 `name` 字段 | 活动对外展示名，**查完配置必须填入，禁止标 ❓** |
| `activity_name` | 配置中心 `activity_name` 字段 | 活动内部标识名，同一活动所有埋点保持一致 |

同一活动不同页面的 `activity` 值可能不同（如集合页和玩法页各有独立 `name`），需分别从各页面的配置中取值。

### 5.3 区服代号对照

查询配置中心时，`region` 参数取以下代号（非中文区服名）：

| 代号 | 区服 | 主要国家 | 时区 |
|------|------|----------|------|
| A | 阿语服 | 伊拉克 | +3 |
| B | 葡语服 | 巴西 | -3 |
| C | 华语服 | 中国 | +8 |
| F | 法语服 | 法国 | +1 |
| G | 德语服 | 德国 | +1 |
| I | 印度服 | 印度 | +5.5 |
| J | 日服 | 日本 | +9 |
| K | 韩服 | 韩国 | +9 |
| M | 马尼服 | 印度尼西亚 | +8 |
| N | 巴基斯坦服 | 巴基斯坦 | +5 |
| O | JK服 | 沙特阿拉伯 | +3 |
| P | 菲律宾服 | 菲律宾 | +8 |
| Q | 土语服 | 土耳其 | +3 |
| R | 俄语服 | 俄罗斯 | +3 |
| S | 西语服 | 墨西哥 | -6 |
| T | 泰服 | 泰国 | +7 |
| U | 美服 | 美国 | -7 |
| V | 越南服 | 越南 | +7 |
| Y | 意语服 | 意大利 | +1 |

如活动覆盖多区服，需分别查询各区服配置（activity 值可能不同）。

### 5.4 CoinChange 基础事件归因口径（重要！易错点）

送礼消耗、道具消耗等用 `CoinChange` 记录货币流水时：

| 字段 | 含义 | 送礼消耗场景正确写法 |
|------|------|----------------|
| `act_id` | CoinChange 原生字段，**活动归因唯一正确字段** | 填活动 id（如 6193） |
| `gift_id` | 锁定具体活动礼物 | 填礼物 id |
| `change_type` | 金币变更类型 ID（分析时 INNER JOIN `ta_dim.dim_2_0_2395`，限 `change_type_from_app='消耗'`，详见 `weplay-coin-change-analytics` skill） | 送礼消耗对应场景 |


---

## 依赖关系

- `weplay-dictionary`：WePlay 基础事件定义（Pay、CoinChange、SendGift 等字段参考）
- `weplay-shushu-sql`：SQL 查询规范（活动分析取数）

---

**最后更新**: 2026-08-21 ｜ **维护者**: 数据分析团队

**更新日志:**
- 2026-08-21: 更新飞书读取/创建为 `lark-cli docs`；修正 `use_coupon` 与 `add_collect_chip` 错误示例；按 WePlay 字段速查表统一 ActivityTotal 组件字段类型；速查表升级为字段白名单，禁止新增未注册字段；礼盒/抽奖保底改为按实际功能生成。
- 2026-06-30: 合并本地规则 12/13——补回同玩法碎片/代币获得与消耗合并为 `chip/add_collect_chip` 的明确约束；补回【新增】临时事件属性精简规则，避免冗余字段污染埋点。
- 2026-06-09（基于 JK 完整重构）: 参照 `jk-activity-tracking-doc` SKILL.md 进行全面重构——新增步骤 2「强制查询配置中心」、临时事件字段查表留痕要求、核心值标红规则（`<text color="red">`）、合并规则（complete_task+recv_reward、多礼物合并）、逐字段自检审核四维度；补充 `send_gift` 三件套规则说明（含易错点警示）；补充 WePlay 特有 `incr_random_coupon`、`red_packet` 组件；删除实战案例中的本地绝对路径引用；格式统一为 `key = value //注释，TYPE`；整体重组为「流程→组件判断→输出格式→编写规则→WePlay特有」五节结构
