docs: 客户行为采集平台设计文档(M1/M2/M3 需求基线)

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-09-15 09:51:36 +08:00
commit 3d013fd0b7
2 changed files with 296 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
_extract_*.txt
__pycache__/
*.pyc
node_modules/
.env
@@ -0,0 +1,291 @@
# 客户行为采集平台 · 设计文档
- 日期:2026-09-15
- 状态:待评审
- 关联文档:`docs/客户行为数据采集平台完整项目实施方案.docx`、`docs/客户行为数据采集平台方案实施报告.docx`(需求基线,本设计在其基础上按实际约束裁剪落地)
## 1. 项目目标
构建一个**第一方客户行为数据采集平台**:网站引入自研 JS SDK,采集访客行为轨迹与环境信息,写入独立后台数据库;后台基于 Art Design Pro 构建管理控制台,提供访客/客户的跨天行为时间线、来源归因、有效停留统计和客户档案管理。
核心业务问题:**"这个客户从哪来、看过什么、哪天来过、每次停多久、在哪儿流失、什么时候变成了线索"**。
## 2. 已确认的决策
| 维度 | 决策 |
|---|---|
| 形态 | 通用 JS SDK(网站引入)+ 独立后台 |
| 后端 | Python · Django + DRF |
| 数据库 | MySQL 8(复用 1Panel 现有容器),事件表按月分区 |
| 前端 | Art Design Pro(Vue3 + TypeScript + Element Plus + Pinia + ECharts) |
| 部署 | 阿里云 ECS · 1Panel · Docker Compose(Nginx 静态 + 反代 Django) |
| 规模策略 | 先小后大;单组织多站点,表结构带 `site_id` 留多站点扩展位 |
| 实时性 | 准实时(事件分钟内可见,最近 5 分钟活跃作为"在线"口径) |
| 客户识别 | 表单提交(询盘/留言)为主;邮件专属链接识别(M2);登录绑定(P2) |
| 缓存 | M1 不引入 Redis;M2 起可选(限流/缓存加固) |
### 2.1 与原方案文档的差异
| 原文档建议 | 本设计 | 理由 |
|---|---|---|
| Node.js 后端 | Django + DRF | 团队技术选型 |
| PostgreSQL | MySQL 8 | 现有 1Panel 环境;JSON 类型 + 按月分区满足当前量级 |
| React/Next.js 后台 | Art Design Pro | 指定模板,自带权限/菜单/主题体系 |
| 多租户 SaaS 就绪 | 单组织多站点 | 先自用,不为 SaaS 付复杂度 |
| Redis 起步必备 | M2 可选 | 先小后大 |
**明确砍掉/推迟**(首期不做):多租户组织管理、ClickHouse、同意管理平台(CMP)、Webhook、会话回放、浏览器指纹身份追踪、营销自动化、机器学习评分。
**保留的治理底线**(不可裁剪):敏感字段黑名单双重拦截、确定性合并原则、数据保留期限与清理、客户删除流程、隐私告知。
## 3. 系统架构
```
┌─────────────────────────────────────────────┐
│ 网站浏览器 │
│ JS SDK(自研 ~10KB,异步加载,绝不阻塞页面) │
└──────────────────┬──────────────────────────┘
│ HTTPS 批量 JSON 上报
▼
┌─────────────────────────────────────────────┐
│ 阿里云 ECS · 1Panel · Docker │
│ Nginx │
│ ├─ 静态:Art Design Pro 打包产物 │
│ └─ /api/* ──► Django + DRF │
│ ├─ 采集接口(公开、域名白名单、限流)│
│ ├─ 管理接口(JWT 登录) │
│ └─ 后台任务(会话化/聚合/清理) │
│ │ │
│ ▼ │
│ MySQL 8(events 按月分区) │
└─────────────────────────────────────────────┘
```
- 开发期:Vite 代理解决跨域;部署期同域无跨域问题。
- 响应格式适配 Art Design Pro 的 `{code, data, message}` 约定。
- 升级路径:事件量到瓶颈时把采集接口拆为独立 FastAPI 服务,SDK 协议不变。
## 4. JS SDK 设计
### 4.1 接入方式(两行)
```html
<script>
window.ctk = window.ctk || function(){(ctk.q = ctk.q || []).push(arguments)};
ctk('init', { siteId: 'site_xxx', endpoint: 'https://track.example.com' });
</script>
<script async src="https://track.example.com/sdk/v1.js"></script>
```
### 4.2 身份模型
- `visitor_id`:加密安全随机数,存 localStorage(第一方存储,不用 Cookie+localStorage 双恢复对抗用户清除)。
- `session_id`:30 分钟无活动切新会话;跨天访问 = 新会话、同一 visitor。
- 首次落地时保存**首触来源**(referrer + UTM + 落地页)到访客档案;每次会话各自记录来源。
### 4.3 事件清单
| 事件 | 优先级 | 字段要点 |
|---|---|---|
| `page_view` | P0 | path、title、referrer、UTM;SPA 路由变化触发(P1) |
| `page_stay` | P0 | `active_ms` 有效停留:页面可见 + 有鼠标/键盘/滚动活动才累计;`visibilitychange` 停止;`sendBeacon` 兜底上报 |
| `scroll_depth` | P1 | 25/50/75/100% 四档 |
| `click` | P1 | 可配置范围(按钮/导航/外链/下载),`data-track-id` 优先标识 |
| `form_start` / `form_submit` | P1 | 表单标识、字段名清单、成功/失败;字段值**白名单制** |
| `copy` / `download` / `print` | P1 | 意图事件:复制了邮箱/电话、下载报价单 PDF、打印页面 |
| `rage_click` / `dead_click` | P2 | 反复点无反应区域 |
| `first_interaction` | P1 | 进页面后首次互动耗时 |
| `form_field_drop` | P1 | 表单在哪个字段放弃、是否粘贴、是否自动填充 |
| `identify_hit` | P1 | 邮件专属链接 token 命中(见 5.3) |
| `sdk_loaded` | P0 | 诊断事件:SDK 版本、初始化耗时 |
### 4.4 环境信息(首次访问携带)
设备类型、OS + 版本、浏览器 + 版本、屏幕分辨率、语言、时区、触屏、CPU 核心数、设备内存(可选开)、Client Hints(设备型号)、网络类型/下行/RTT(`navigator.connection`)、页面性能(Navigation Timing)。
### 4.5 传输可靠性
- 内存队列 → 批量发送(10 条或 15 秒触发);页面隐藏 `sendBeacon`,需自定义头时 `fetch keepalive`。
- 每事件 UUID `event_id`,服务端按 `site_id + event_id` 幂等去重。
- 失败指数退避重试(上限 3 次);4xx 不重试;离线队列超限按最旧丢弃并记本地丢弃计数。
- 客户端时间仅作排序参考,服务端另存 `received_at` 并标记时钟偏差。
- SDK 全部逻辑 try/catch 包裹,任何异常不影响宿主网站。
### 4.6 隐私与安全红线(SDK 端)
- 不采集:password/hidden/file/autocomplete 敏感字段值、验证码、银行卡、身份证。
- URL 清洗:含邮箱/手机号/令牌类查询参数在入库前删除或哈希。
- 不做:键盘逐键记录、剪贴板读取、摄像头/麦克风、浏览器指纹身份追踪(弱指纹仅用于爬虫识别,不参与身份关联)。
- 免费文本默认不采集,需逐项白名单。
## 5. 身份识别与客户合并
### 5.1 身份层级
```
visitor_id(匿名浏览器)
└─ session_id(每次访问)
└─ events
contact(客户档案)── identity 关联表 ── visitor_id / 邮箱哈希 / 手机号哈希
```
### 5.2 表单识别(M2 主路径)
```
匿名访客逛了 3 天 → 第 4 天提交询盘表单
→ 白名单字段值(姓名/邮箱/电话)创建客户档案
→ 同邮箱/手机号已存在则归并,不建重复档案
→ 该 visitor_id 全部历史轨迹自动归入客户名下
→ 后续访问持续追加到同一档案
```
- 表单字段值浏览器端采集(询盘线索场景够用 + 垃圾过滤:粘贴检测/Honeypot/频率)。
- **订单、支付、注册成功等业务事实必须走服务端签名 API(P2)**,浏览器事件不作事实依据。
### 5.3 邮件专属链接识别(M2)
开发信/WhatsApp/社媒发 `https://site/?ctk_token=<专属token>` 链接;对方点开即触发 `identify_hit`,立即把匿名轨迹归到对应客户档案——比等表单提交更早识别。
### 5.4 合并规则
- **只做确定性合并**:邮箱/手机号/token/user_id。IP、城市、设备相似**绝不自动合并**,仅作线索提示。
- 手动认领:后台把匿名访客轨迹认领给客户,支持解除;操作记审计。
- 多个 visitor_id 绑定同一邮箱 → 汇入同一 contact(跨设备视图)。
- 每次 merge/认领/解除记录操作者、时间、规则版本。
## 6. 来源归因(四层)
1. **自动 referrer**:提取来路域名(google.com / 合作伙伴站 / 微信内置浏览器 / 直接访问)。
2. **UTM 参数**:utm_source / medium / campaign / term / content,外投链接统一带参。
3. **首触 + 会话来源**:访客/客户档案永久记录首触来源;每次会话各自记录(时间线可见"第 N 次访问来自 X")。
4. **渠道规则映射 + 手动标记**:后台配置 `域名 → 渠道名` 规则表(google.com → 自然搜索等);支持手动改/手动标(线下展会、referrer 丢失场景)。
已知边界:referrer 被剥(部分隐私工具/HTTPS→HTTP/微信)记为"直接访问";要 100% 可靠归因用 UTM 链接。
## 7. 匿名访客可采集信息全景
| 类别 | 内容 |
|---|---|
| 身份标识 | visitor_id、session_id、新/回访、访问次数、首末次访问、活跃天数 |
| 行为轨迹 | 页面浏览及路径、每页有效停留、滚动深度、点击、表单行为(开始/放弃字段/提交)、意图事件(复制/下载/打印) |
| 来源 | referrer 域名、UTM、落地页、部分搜索词 |
| 设备环境 | 设备类型、OS/浏览器及版本、分辨率、语言、时区、触屏、硬件(可选)、Client Hints、网络质量、页面性能 |
| 网络地理(服务端) | IP(保留期限见 9.2)、国家/省/市(ip2region 离线库)、运营商、爬虫识别 |
| 跨站关联 | 同一访客在自有多个域名间串联(首方合法做法) |
拿不到(诚实边界):匿名阶段真实身份(姓名/邮箱/电话);跨设备同一人(直到提交表单/登录/token 命中);清存储/无痕后重新开始(不对抗)。
## 8. 管理控制台(Art Design Pro 页面)
| # | 页面 | 优先级 | 内容 |
|---|---|---|---|
| C1 | 登录/权限 | P0 | JWT;管理员/普通成员两角色起步(复用模板权限体系) |
| C2 | 总览 Dashboard | P0 | 今日/7日/30日 PV、UV、会话数、新访客比;最近 5 分钟活跃(准实时在线);趋势图 |
| C3 | 访客列表(匿名) | P0 | 访客 ID、首末次访问、会话数、来源、位置、设备 |
| C4 | 访客/会话详情 | P0 | 单访客跨天时间线 + 单会话页面路径(**M1 验收核心**) |
| C5 | 站点管理 | P0 | 站点 CRUD、site_id 签发、域名白名单 |
| C6 | 客户列表 | P1 | 姓名/邮箱/手机号脱敏、首末次访问、访问次数、总停留、最近来源、标签筛选、搜索 |
| C7 | 客户详情 | P1 | 跨天时间线(日期分组)+ 会话列表 + 设备/地理位置 + 首触来源 + 标签备注 |
| C8 | 事件调试流 | P1 | 原始事件流(含拒绝原因、时延),开发调试用 |
| C9 | 标签/备注 | P1 | 客户打标签、跟进备注 |
| C10 | 渠道规则 | P1 | 域名→渠道映射配置 |
| C11 | 专属链接生成 | P1 | 给客户/活动生成带 token 的识别链接 |
| C12 | 数据导出 | P2 | 客户列表/时间线 CSV |
| C13 | 事件字典 | P2 | 事件 schema 登记 |
客户时间线样式(原样采用文档 8.2):
```
09-01 10:20 首次访问产品 A 页面 来源 Google Ads
09-01 10:24 查看价格页 有效停留 2 分 18 秒
09-02 16:10 再次访问案例页面
09-02 16:15 询盘提交成功 身份识别为 customer@example.com
```
## 9. 数据治理
### 9.1 敏感字段黑名单
SDK 端 + 服务端**双重拦截**:password/验证码/银行卡/身份证等永不入库;服务端对 properties 做体积/数量/长度/深度校验,未知字段拒绝或隔离并记原因。
### 9.2 数据保留(默认值,站点可配)
| 数据 | 保留期 |
|---|---|
| 原始事件(events 分区) | 180 天,分区清理 |
| 原始 IP | 180 天,到期后台任务截断为 /24 前缀;地理/运营商解析结果长期保留 |
| 客户档案、标签、备注 | 长期(直至客户删除) |
| 审计日志 | 1 年 |
### 9.3 客户删除
删除客户档案 + 关联事件(标记删除 + 异步物理清理),记录审计;导出留档。
### 9.4 隐私告知
提供隐私政策/Cookie 告知文案模板;SDK 预留 `consent` 开关接口(同意管理模式 P2 完善化);第三方脚本不可绕过同意状态。
## 10. 数据库核心表(MySQL 8)
| 表 | 要点 |
|---|---|
| `site` | 站点、site_id、域名白名单、采样配置 |
| `visitor` | visitor_id、首触来源、首次/最近访问、环境摘要 |
| `session` | session_id、visitor、开始/结束、来源、落地页、会话时长 |
| `events`(按月分区) | event_id(site 内唯一幂等键)、visitor、session、contact(可空)、event_type、occurred_at、received_at、path、properties JSON |
| `contact` | 客户档案:姓名、邮箱(规范化+加盐哈希列)、电话(同)、公司(可由邮箱域名推导)、标签、备注、负责人 |
| `identity_map` | visitor_id / 邮箱哈希 / 电话哈希 / token ↔ contact 关联 + 合并审计字段 |
| `track_token` | 专属链接 token ↔ contact |
| `daily_stats` / `session_rollup` | 聚合派生表(日指标、会话摘要),避免报表扫 events |
| `admin_user` / `audit_log` | 后台账号、审计 |
索引原则:时间线 `(site_id, visitor_id/contact_id, occurred_at DESC)`;会话 `(site_id, visitor_id, started_at DESC)`;高频筛选字段独立列,长尾属性进 JSON。
## 11. API 概览
| 接口 | 说明 |
|---|---|
| `POST /api/collect/batch` | 浏览器批量上报:校验站点状态/域名白名单/体积/限流/幂等去重/黑名单 → 入库 |
| `POST /api/collect/identify` | token 命中识别(M2) |
| 管理接口 `/api/admin/*` | JWT;站点、访客、客户、事件调试、标签、渠道规则、导出、Dashboard 聚合 |
采集接口返回最小响应(成功/失败 + 稳定错误码),不向匿名调用方泄露配置或客户数据。site_id 是公开标识,只用于归属,不赋予任何读取权限。
## 12. 非功能需求
- SDK 体积 ≤ 15KB(gzip),初始化不阻塞首屏;加载失败对网站零影响。
- 采集接口:日均 10 万事件内单 Django 实例 + MySQL 从容承载;监控接受率、去重率、拒绝原因分布。
- 准实时:事件从发生到后台可见 ≤ 60 秒(列表刷新即得,无长连接)。
- 部署:1Panel Docker Compose(Nginx + Django/uwsgi 或 gunicorn + 复用 MySQL 容器);.env 管理密钥;数据库迁移向前兼容。
- 备份:MySQL 自动备份 + 恢复演练(复用 1Panel 能力)。
## 13. 里程碑
### M1 · 最小闭环(端到端技术验证)
- SDK:接入两行代码、visitor/session 身份、page_view、page_stay、批量传输、幂等去重、UTM/referrer 首触记录、环境信息。
- 后端:采集 API(域名白名单/限流/黑名单校验)、核心表、会话化与日聚合任务。
- 后台:C1 登录权限、C2 总览、C3 访客列表、C4 访客/会话详情、C5 站点管理。
- **验收**:一个真实网站接入,后台能看到"某访客今天看了 3 页、每页停多久、昨天来过、首触来源是 Google"。
### M2 · 完整产品(客户识别 + 完整后台)
- SDK:click、scroll、SPA 路由、表单事件(含字段放弃/粘贴/自动填充)、意图事件(复制/下载/打印)、first_interaction、URL 清洗、track/identify/reset API。
- 身份:表单→客户档案创建与归并、邮箱/手机号去重、邮件专属链接识别、手动认领/解除、合并审计。
- 后台:C6 客户列表、C7 客户详情、C8 事件调试流、C9 标签备注、C10 渠道规则、C11 专属链接生成。
- 治理:IP 保留期任务、客户删除流程、隐私告知模板。
- **验收**:询盘表单提交后客户档案自动生成并归并全部历史轨迹;专属链接点开即识别。
### M3 · 增强与扩展
- rage/dead click、远程配置(采样/开关,ETag)、npm 包发布。
- 服务端签名事件 API(订单/注册事实)、WordPress 连接器插件(注入 SDK + CF7/WPForms 钩子)。
- IP 企业反查(Leadfeeder 式 B2B 线索提示,可选付费库,只提示不自动合并)、邮箱后缀→公司名补全。
- 数据导出、事件字典、Redis 限流加固、(独立评估)会话回放。
## 14. 风险与开放项
| 项 | 状态 |
|---|---|
| 表单字段值浏览器端先行、签名机制 P2 | 已决策 |
| 原始 IP 默认保留 180 天后截断(站点可配) | 已决策(默认值) |
| 微信内置浏览器 referrer 常缺失 | 已知边界,用 UTM 专属链接兜底 |
| 主要访客区域与跨境合规 | 上线前按原方案文档第十章做一次专项确认 |
| 事件量超预期 | 升级路径已定:FastAPI 采集拆分 → 分区细化 → 聚合下沉 |