Files
fangke/docs/superpowers/specs/2026-09-15-customer-behavior-platform-design.md
T

301 lines
18 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.
# 客户行为采集平台 · 设计文档
- 日期:2026-09-15
- 状态:已确认
- 关联文档:`docs/客户行为数据采集平台完整项目实施方案.docx`、`docs/客户行为数据采集平台方案实施报告.docx`(需求基线,本设计在其基础上按实际约束裁剪落地);`docs/客户画像与销售转化实施方案.md`(**M4+ 路线图**,本平台即其"跨天轨迹底座")
## 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(自研 ≤15KB gzip,异步加载,不阻塞页面) │
└──────────────────┬──────────────────────────┘
│ 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。会话权威在 SDK;服务端按同一 30 分钟规则做兜底校验(超长/跨天异常时切分修正),不产生第二套会话口径。
- 首次落地时保存**首触来源**(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 | 表单标识、字段名清单、成功/失败;字段值**白名单制**(白名单在后台按站点配置,SDK init 可覆盖) |
| `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 串联(M3,首方合法做法);或经客户识别后归并到同一档案 |
拿不到(诚实边界):匿名阶段真实身份(姓名/邮箱/电话);跨设备同一人(直到提交表单/登录/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 天,到期后台任务截断(IPv4 → /24,IPv6 → /64 前缀);地理/运营商解析结果长期保留 |
| 客户档案、标签、备注 | 长期(直至客户删除) |
| 审计日志 | 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` | 客户档案:姓名、邮箱(规范化+加盐哈希列)、电话(同)、公司(可由邮箱域名推导,预留 account 关联,M4+ 客户画像阶段扩展 Account/Person 体系)、标签、备注、负责人 |
| `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 + gunicorn + 复用 MySQL 容器);.env 管理密钥;数据库迁移向前兼容。
- 备份:MySQL 自动备份 + 恢复演练(复用 1Panel 能力)。
## 13. 里程碑
### M1 · 最小闭环(端到端技术验证)
- SDK:接入两行代码、visitor/session 身份、page_view、page_stay、批量传输、幂等去重、UTM/referrer 首触记录、环境信息、sdk_loaded 诊断事件。
- 后端:采集 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 包发布。
- 登录绑定 `identify(user_id)`(含服务端签名令牌机制)、同意管理模式完善(consent 分目的开关)。
- 服务端签名事件 API(订单/注册事实)、WordPress 连接器插件(注入 SDK + CF7/WPForms 钩子)。
- IP 企业反查(Leadfeeder 式 B2B 线索提示,可选付费库,只提示不自动合并)、邮箱后缀→公司名补全。
- 跨自有域名访客串联(站间跳转传 token)。
- 数据导出、事件字典、Redis 限流加固、(独立评估)会话回放。
- 上线门禁:跨境/隐私合规专项确认(按原方案文档第十二章执行)。
### M4+ · 客户画像与销售转化(独立立项,见 `docs/客户画像与销售转化实施方案.md`)
不在本设计范围内。本平台为其提供的数据基础保障:
- 原始事件全量保存 path/title/properties——画像评分规则可基于历史数据回放重算;
- contact 模型对齐其 Person 概念,预留 account 关联;
- 站内搜索词、下载/复制/打印等意图事件、表单字段级数据从 M2 起持续积累,正是其 Intent/Engagement 评分的原料。
## 14. 风险与开放项
| 项 | 状态 |
|---|---|
| 表单字段值浏览器端先行、签名机制 P2 | 已决策 |
| 原始 IP 默认保留 180 天后截断(站点可配) | 已决策(默认值) |
| 微信内置浏览器 referrer 常缺失 | 已知边界,用 UTM 专属链接兜底 |
| 主要访客区域与跨境合规 | 上线前按原方案文档第十章做一次专项确认 |
| 事件量超预期 | 升级路径已定:FastAPI 采集拆分 → 分区细化 → 聚合下沉 |