# H5 任务页埋点与结果回传规范
> 文档版本：v1.0
> 最后更新：2026-04-05 12:36:25

本文档用于定义当前项目中，**原生内容卡、H5 详情页、H5 互动任务页、增强结果页** 的最小埋点口径与结果回传结构，避免后续出现“曝光、点击、任务完成、业务落库”混为一谈的情况。

核心结论：

**展示埋点、交互埋点、任务结果回传必须分层定义；H5 可以上报行为与任务结果，但不能直接决定打点成功或比赛状态。**

---

## 1. 目标

本文档重点解决以下问题：

- 如何统一原生内容卡与 H5 页的埋点事件口径
- 如何区分“浏览行为”与“任务完成结果”
- 如何通过 `submitResult` 回传 H5 任务页结果
- 如何让内容面 API 稳定承接任务结果落库
- 如何保证埋点失败或回传失败时不阻断主流程

适用范围：

- 打点后原生内容卡
- 原生内容卡 CTA 进入的 H5 详情页
- H5 互动任务页
- H5 增强结果页

不适用范围：

- 打点判定本身
- 地图主链状态流转
- 高频 telemetry 主链
- 实时网关事件流替代方案

---

## 2. 边界原则

### 2.1 任务结果不等于比赛结果

H5 回传的任务结果只表示：

- 某个互动任务是否完成
- 某个表单是否提交
- 某个作品是否生成
- 某个增强页是否完成关键动作

它不直接表示：

- 打点是否成功
- 本局是否完赛
- 成绩是否生效

### 2.2 埋点事件不等于业务落库

埋点事件主要用于：

- 行为分析
- 页面漏斗观察
- 体验优化
- 运营数据统计

业务落库主要用于：

- 记录任务完成事实
- 记录作品或表单提交结果
- 记录奖励发放依据

这两者可以共用部分字段，但不能视为同一条链路。

### 2.3 埋点失败不阻断体验

若埋点上报失败：

- 页面仍可继续浏览
- 任务仍可继续操作
- 比赛主流程不应被中断

### 2.4 结果回传失败不反向控制主流程

若 `submitResult` 或内容面 API 落库失败：

- 不应改写打点成功状态
- 不应强制比赛中断
- 允许重试、缓存或降级提示

---

## 3. 推荐分层模型

建议将相关事件分为三层：

### 3.1 展示层事件

用于记录页面或卡片是否被看到。

例如：

- 内容卡进入
- H5 页面曝光
- 结果页进入

### 3.2 交互层事件

用于记录用户在页面中的关键操作。

例如：

- CTA 点击
- 页面关闭
- 按钮点击
- 表单提交点击
- 分享点击

### 3.3 结果层事件

用于记录任务是否完成，以及完成后产出的结果对象。

例如：

- 拍照任务完成
- 留言任务完成
- 答题任务完成
- 作品提交成功

---

## 4. 统一标识字段

无论是原生内容卡还是 H5 页面，建议统一携带以下字段：

- `eventId`
  活动标识
- `sessionId`
  对局标识
- `controlId`
  点位标识；非点位页面可为空
- `taskId`
  任务标识；非任务页面可为空
- `pageCode`
  H5 页面编码
- `pageType`
  页面类型
- `bridgeVersion`
  Bridge 协议版本
- `contentSource`
  内容来源
- `triggerSource`
  触发来源
- `timestamp`
  事件时间

建议补充字段：

- `userId`
- `tenantId`
- `variantId`
- `resultId`
- `deviceType`
- `networkType`

字段说明：

- `contentSource`
  建议取值：`native-card` `h5-content` `h5-task` `h5-result`
- `triggerSource`
  建议取值：`auto-popup` `card-cta` `map-click` `result-action`

---

## 5. 页面类型建议

建议统一定义以下 `pageType`：

- `native-content-card`
- `h5-content-page`
- `h5-task-page`
- `native-result-page`
- `h5-result-page`

这样可以保证：

- 原生与 H5 事件可以统一分析
- 同一任务可横跨内容卡和任务页追踪
- 结果页增强链不会混进地图主链事件

---

## 6. 原生内容卡最小事件集

结合当前待办中的口径，建议先正式收口以下事件：

### 6.1 `content_card_enter`

表示内容卡实际展示给用户。

建议时机：

- 卡片完成入场动画后
- 卡片真实可见时

### 6.2 `content_card_close`

表示内容卡被关闭。

建议补充原因字段：

- `closeReason = auto-dismiss`
- `closeReason = user-close`
- `closeReason = replaced`
- `closeReason = open-h5`

### 6.3 `content_card_cta_click`

表示用户点击内容卡主 CTA。

建议补充字段：

- `ctaKey`
- `targetType`
- `targetPageCode`

### 6.4 `result_page_enter`

表示原生结果页进入。

该事件用于与 H5 增强结果页做漏斗对比。

---

## 7. H5 页面最小事件集

### 7.1 `h5_page_enter`

表示 H5 页面真实进入。

建议在：

- 页面初始化完成
- 基础上下文已拿到
- 主视图可见

之后触发，而不是在 `web-view` 打开瞬间就记。

### 7.2 `h5_page_exit`

表示 H5 页面退出。

建议补充：

- `exitReason = close`
- `exitReason = back`
- `exitReason = bridge-close`
- `exitReason = replaced`
- `exitReason = error`

### 7.3 `h5_cta_click`

表示 H5 页内关键 CTA 被点击。

建议至少带：

- `ctaKey`
- `ctaLabel`
- `taskId`

### 7.4 `h5_interaction`

表示任务页关键互动动作。

建议只用于关键动作，不记录所有噪声操作。

推荐 `actionKey`：

- `start-task`
- `take-photo`
- `record-audio`
- `submit-form`
- `share`
- `retry`

---

## 8. 任务生命周期事件

若页面属于互动任务页，建议增加一组任务态事件：

### 8.1 `task_viewed`

表示用户已看到任务主体。

### 8.2 `task_started`

表示用户开始任务，不再只是浏览。

### 8.3 `task_progressed`

表示阶段性推进。

适用场景：

- 多步表单
- 连续拍照
- 多题答题
- 分阶段收集

建议带：

- `stepId`
- `stepIndex`
- `stepStatus`

### 8.4 `task_completed`

表示任务完成，但不代表业务一定已成功落库。

### 8.5 `task_failed`

表示任务失败。

建议补充：

- `errorCode`
- `errorStage`

### 8.6 `task_cancelled`

表示用户主动放弃任务。

---

## 9. `submitResult` 推荐结构

建议将 `submitResult` 视为“结果层回传”，而不是普通点击埋点。

推荐最小结构：

```json
{
  "id": "req-002",
  "channel": "request",
  "type": "submitResult",
  "payload": {
    "taskId": "task-photo-control-3",
    "taskType": "photo-checkin",
    "attemptId": "attempt-001",
    "status": "completed",
    "pageCode": "task-control-3-photo",
    "controlId": "control-3",
    "result": {
      "assetId": "img-001"
    }
  }
}
```

字段建议：

- `taskId`
  任务标识
- `taskType`
  任务类型
- `attemptId`
  一次任务尝试标识
- `status`
  任务结果状态
- `pageCode`
  页面编码
- `controlId`
  关联点位
- `result`
  结构化结果对象

---

## 10. `submitResult.status` 建议口径

建议第一阶段只正式支持：

- `completed`
- `failed`
- `cancelled`
- `skipped`

建议解释：

- `completed`
  用户已完成任务目标
- `failed`
  本次任务尝试失败
- `cancelled`
  用户主动退出或放弃
- `skipped`
  允许跳过的任务被明确跳过

当前不建议第一阶段就把过多中间状态做成业务落库状态。

例如：

- `viewed`
- `started`
- `progressed`

这些更适合作为埋点事件，而不是最终任务结果状态。

---

## 11. `result` 结果对象建议

不同任务类型建议分别约定 `result`：

### 11.1 拍照任务

```json
{
  "assetId": "img-001",
  "assetType": "image",
  "count": 1
}
```

### 11.2 录音任务

```json
{
  "assetId": "audio-001",
  "assetType": "audio",
  "durationMs": 12000
}
```

### 11.3 表单任务

```json
{
  "formId": "form-001",
  "submissionId": "sub-001"
}
```

### 11.4 问答任务

```json
{
  "questionSetId": "quiz-001",
  "score": 3,
  "total": 5
}
```

原则：

- `result` 保持结构化
- 不直接塞整页原始页面状态
- 不把分析事件数组混进 `result`

---

## 12. 内容面 API 落库建议

建议内容面 API 承接：

- H5 页面入口鉴权
- H5 上下文初始化
- `submitResult` 后的业务落库
- 上传结果对象登记

建议最小落库对象至少包含：

- `eventId`
- `sessionId`
- `controlId`
- `taskId`
- `attemptId`
- `pageCode`
- `status`
- `resultJson`
- `submittedAt`

建议能力边界：

- 内容面 API 记录任务完成事实
- 主系统继续负责比赛核心状态
- 不通过内容面 API 直接判定打点成功或比赛结束

---

## 13. 去重与幂等建议

为避免重复点击、网络重试或页面重进导致重复落库，建议：

### 13.1 任务尝试幂等

建议以：

- `sessionId`
- `taskId`
- `attemptId`

作为一次任务尝试的幂等键。

### 13.2 埋点去重

建议以下事件在单次页面进入内只记一次：

- `h5_page_enter`
- `task_viewed`
- `task_started`
- `task_completed`

### 13.3 可重复事件

以下事件允许多次：

- `h5_cta_click`
- `h5_interaction`
- `task_progressed`

但建议带：

- `sequence`
- `stepId`
- `timestamp`

---

## 14. 推荐上报时机

建议的最小时机如下：

### 14.1 原生内容卡

- 卡片入场完成后：`content_card_enter`
- 用户关闭时：`content_card_close`
- CTA 点击时：`content_card_cta_click`

### 14.2 H5 内容页 / 任务页

- 页面首屏稳定后：`h5_page_enter`
- 任务主体真正可见后：`task_viewed`
- 用户开始实际互动后：`task_started`
- 关键阶段完成后：`task_progressed`
- 调用 `submitResult(completed)` 前：`task_completed`

### 14.3 结果页

- 原生结果页进入：`result_page_enter`
- H5 增强结果页进入：`h5_page_enter`

---

## 15. fallback 规则

### 15.1 H5 打不开

- 记一条 `h5_open_failed`
- 回退到原生内容卡或原生结果页

### 15.2 埋点接口失败

- 允许静默失败或批量补报
- 不阻断用户当前操作

### 15.3 `submitResult` 失败

- 页面应拿到明确失败回执
- 允许用户重试
- 原生可决定是否保留最小完成提示

### 15.4 Bridge 未就绪

- 禁用依赖原生能力的操作
- 仅保留静态浏览能力

---

## 16. 第一阶段建议收口的正式事件

建议第一阶段只先正式收口以下事件，不一开始扩太大：

- `content_card_enter`
- `content_card_close`
- `content_card_cta_click`
- `result_page_enter`
- `h5_page_enter`
- `h5_page_exit`
- `h5_cta_click`
- `task_viewed`
- `task_started`
- `task_completed`
- `task_failed`
- `task_cancelled`

以及一个正式回传动作：

- `submitResult`

这样已经足够支撑：

- 内容卡漏斗
- H5 页面进入漏斗
- 任务页完成率
- 原生页与 H5 页联动链路

---

## 17. 当前阶段不建议做的事

- 不建议把所有按钮点击都做成正式公共事件
- 不建议把页面内局部滚动、每次切 tab 都纳入统一业务口径
- 不建议让 `submitResult` 兼做曝光埋点
- 不建议让 H5 页面自己定义完全不同的一套事件命名
- 不建议直接把原始页面表单全文落到统一分析事件里

---

## 18. 与现有文档的关系

本规范补充收口以下文档中的未定项：

- `原生与 H5 Bridge 规范`
- `H5 增强与内容扩展层方案`
- `混合体验架构方案`
- `API 与发布物边界约定`
- `MyToDo` 中已出现的内容卡与结果页事件线索

定位上：

- `Bridge 规范` 负责通信动作
- 本文负责埋点口径与任务结果口径
- 内容面 API 文档后续再细化具体落库接口

---

## 19. 一句话结论

最适合当前项目的做法不是让 H5 自己发明一套任务体系，而是：

**由主系统定义统一上下文、统一事件口径、统一结果回传结构，让 H5 只负责增强体验与任务执行。**
