第02章:第一方数据体系 — 访客、会话与身份识别的核心概念
第02章:第一方数据体系 — 访客、会话与身份识别的核心概念
“数据不会说谎,但如果你连同一个人的两次访问都无法识别为同一个人,那你的数据说的是一门没人能懂的外语。”
为什么身份识别是一切的基础
想象这样一个场景:一个用户周一看到你的 Facebook 广告,点进来看了一眼,没有提交表单,离开了。周三,他直接在 Google 搜索你的产品名,又进来了,这次提交了报价请求。
如果你的系统无法识别这两次访问来自同一个人,你会得出什么结论?
- Facebook 广告带来了 1 次访问,0 次转化,ROI 为零
- 直接搜索带来了 1 次转化
- 结论:Facebook 广告没用,砍掉预算
但真相是:Facebook 广告是这次转化的触点之一,用户是在看过广告之后,主动去搜索的。如果你砍掉 Facebook,可能连"直接搜索"这个转化也会减少。
这就是为什么身份识别是整个归因体系的基础。没有准确的访客识别,归因分析就是建立在流沙之上。
三个核心概念:访客、会话、事件
在构建追踪系统之前,我们需要建立精确的概念框架。这个框架由三个层级构成:
身份识别层级体系
─────────────────────────────────────────────
访客(Visitor)
│ 持久化身份,跨时间、跨会话保持不变
│ 标识符:visitor_id(存储在 Cookie 中)
│
├─ 会话 / 访问(Session / Visit)
│ │ 单次访问行为的容器
│ │ 标识符:visit_id(每次访问生成新的)
│ │
│ ├─ 事件(Event)
│ │ │ 会话内的具体行为
│ │ │ 例:页面浏览、按钮点击、表单提交
│ │
│ ├─ 事件
│ └─ 事件
│
├─ 会话(另一次访问)
│ └─ 事件...
│
└─ 会话(又一次访问)
└─ 事件...
─────────────────────────────────────────────
访客(Visitor):代表一个真实的人或设备。即使他们多次访问你的网站,visitor_id 保持不变。这让你能够追踪一个用户从第一次接触到最终转化的完整旅程。
会话/访问(Session/Visit):代表一次连续的访问行为。在我们的系统里,我们用 visit_id 来标识每一次访问,并记录这次访问的来源信息(UTM 参数、referrer 等)。一个 visitor_id 对应多个 visit_id。
事件(Event):会话内发生的具体行为。提交表单是一个事件,点击按钮是一个事件,浏览一个页面也是一个事件。在我们的 MVP 系统里,最关键的事件是"表单提交",对应到 wb_leads 表的一条记录。
visitor_id:跨会话的持久化身份
visitor_id 的核心设计需求是:同一个浏览器/设备的所有访问,应该使用相同的 visitor_id。
实现方式通常是第一方 Cookie:
访客第一次访问
─────────────────────────────────────
1. 浏览器发出请求,没有 visitor_id Cookie
2. 落地页脚本检测到没有 visitor_id
3. 生成一个新的 UUID:visitor_id = "a3f2-..."
4. 将这个 UUID 写入第一方 Cookie:
Set-Cookie: wb_vid=a3f2-...; max-age=63072000; SameSite=Lax
(max-age = 2 年,以秒为单位)
5. 在 localStorage 里也备份一份(应对某些浏览器限制)
访客第二次访问(相同浏览器)
─────────────────────────────────────
1. 浏览器发出请求,带有 visitor_id Cookie
2. 落地页脚本读取 Cookie:visitor_id = "a3f2-..."
3. 继续使用这个 visitor_id,不生成新的
4. 这次访问会有新的 visit_id,但 visitor_id 相同
为什么用第一方 Cookie 而不是第三方 Cookie?
| 对比维度 | 第一方 Cookie | 第三方 Cookie |
|---|---|---|
| 设置域名 | 你自己的域名 | 第三方域名 |
| 浏览器限制 | 几乎不受限 | 正在被全面限制 |
| Safari ITP 影响 | 最长 7 天(JS 设置)或更长(HTTP 设置) | 已被完全阻止 |
| 跨网站追踪 | 仅限你的域名 | 可跨网站(但已失效) |
| 隐私政策要求 | 需要用户同意 | 同样需要用户同意 |
关键细节:visitor_id Cookie 必须通过 HTTP 响应头设置,而不是 JavaScript,原因是:
Safari 的 ITP 对 JavaScript 写入的 Cookie 有 7 天有效期限制,但对 HTTP 响应头设置的 Cookie 可以延长到 1-2 年。这意味着如果你在前端 JS 里写 Cookie,iOS Safari 用户每 7 天就会生成一个新的 visitor_id,身份识别完全失效。
正确的方式是:前端把 visitor_id 传给你的 API,API 在响应里用 Set-Cookie 头设置。
visit_id:单次访问的唯一标识
每次用户访问你的落地页,都应该生成一个新的 visit_id。这个 ID 的作用是:
-
关联这次访问的所有数据:UTM 参数、referrer、fbclid、gclid 等,都记录在以 visit_id 为主键的 wb_visits 表里
-
连接访问和转化:当用户提交表单时,visit_id 会被写入 wb_leads 表,把这次转化和对应的广告来源关联起来
-
支持多触点归因:同一个 visitor_id 可以有多个 visit_id,这为"首次点击归因"、“末次点击归因”、"线性归因"等不同归因模型提供了数据基础
visit_id 的生成和存储逻辑:
页面加载时
─────────────────────────────────────
1. 生成 visit_id = UUID()
2. 存储在会话级别(sessionStorage 或内存变量中)
(不写入持久化 Cookie,因为每次访问应该独立)
3. 发送 POST /api/visit,记录本次访问信息
4. visit_id 也存入一个 session-level Cookie,
方便表单提交时自动携带
用户提交表单时
─────────────────────────────────────
1. 读取 visitor_id(来自持久化 Cookie)
2. 读取 visit_id(来自 session Cookie 或 JS 变量)
3. 读取 qualifier(来自 session Storage,本次 A/B 版本)
4. 一起提交到 POST /api/lead
身份识别的完整数据流
让我们把整个身份识别流程串联起来,看清楚数据是如何流动的:
用户点击广告 (带有 utm_source=facebook&fbclid=xxx)
│
▼
浏览器加载落地页 URL
(https://yourdomain.com/landing?utm_source=facebook&fbclid=xxx)
│
▼
前端 JavaScript 运行
│
├─ 1. 读取 URL 参数
│ utm_source=facebook
│ utm_medium=cpc
│ utm_campaign=insurance_q1
│ fbclid=AQHxxxxxxxx
│
├─ 2. 读取/生成 visitor_id
│ 检查 Cookie "wb_vid"
│ → 存在:使用现有值
│ → 不存在:生成新 UUID,临时存储
│
├─ 3. 分配 qualifier (A/B 版本)
│ 检查 Cookie "wb_qual"
│ → 存在:使用现有值(保证同访客看同版本)
│ → 不存在:按权重随机分配 A/B/Control
│
├─ 4. 生成 visit_id(每次访问新建)
│ visit_id = UUID()
│
└─ 5. POST /api/visit
{
visitor_id,
visit_id,
qualifier,
utm_source,
utm_medium,
utm_campaign,
fbclid,
landing_url,
referrer
}
│
▼
服务端处理
│
├─ 写入 wb_visits 表
└─ 响应头设置持久化 Cookie
Set-Cookie: wb_vid=xxx; HttpOnly; max-age=63072000
Set-Cookie: wb_qual=A; max-age=2592000
多设备场景:身份识别的边界
一个现实问题:同一个用户在手机上看到广告,在电脑上提交表单,这两个 visitor_id 是不同的。
这是设备级别身份识别的固有局限性。要解决跨设备识别,需要引入"已知标识符":
设备级别识别(Cookie)
─────────────────────────────────────────────
手机浏览器:visitor_id = "aaa-111"
电脑浏览器:visitor_id = "bbb-222"
→ 无法关联,是两个独立访客
基于已知标识符的关联
─────────────────────────────────────────────
当用户在手机上用邮箱注册:
email: "user@example.com" ←→ visitor_id = "aaa-111"
当用户在电脑上用同一邮箱登录/提交表单:
email: "user@example.com" ←→ visitor_id = "bbb-222"
通过 email 可以把两个 visitor_id 关联起来
对于大多数 MVP 阶段的追踪系统,设备级别的识别已经够用了。跨设备追踪是进阶功能,等基础体系建立后再考虑。
会话超时:什么时候应该创建新的 visit_id
一个常见的问题:用户打开落地页后去做了别的事,30 分钟后回来继续填表,算一次访问还是两次访问?
这里有两种设计哲学:
Google Analytics 的方式:会话超时(默认 30 分钟无活动算会话结束)。超时后回来算新会话。
我们的推荐方式:每次落地页加载都是新的 visit_id,不考虑超时。
理由:
- 我们主要关心的是"广告点击 → 落地页加载 → 表单提交"这条链路。落地页加载就是流量入口,每次加载都对应一次广告曝光或搜索行为。
- 如果用户 30 分钟后回来,浏览器可能已经有新的 URL(直接访问而不是通过广告),这是一次新的"意向表达"。
- 简单性原则:每次加载 = 新的 visit_id,逻辑最清晰,最不容易出 bug。
第一方数据体系的四个核心属性
一个健康的第一方数据体系应该具备以下属性:
1. 完整性(Completeness) 每一次有效访问都应该被记录,不能有遗漏。这要求:前端脚本要足够轻量和可靠,不能因为广告拦截或网络问题导致大量记录失败。
2. 准确性(Accuracy) 记录下来的数据要准确。visitor_id 的生成和持久化机制要可靠,不能因为 Cookie 设置错误导致同一个用户生成了多个 visitor_id。
3. 关联性(Linkability) 访问记录(wb_visits)和转化记录(wb_leads)之间要能关联。这通过 visit_id 和 visitor_id 两个外键来实现。
4. 可操作性(Actionability) 数据收集的目的是支持决策。数据结构的设计要能直接回答以下问题:
- 这个 lead 是哪个广告带来的?
- A 版本和 B 版本哪个转化率更高?
- 这个月花在 Facebook 上的预算产生了多少个 lead?
真实案例:一条数据记录的完整生命周期
让我们用一个真实的数据案例,把本章所有概念串联起来:
场景:用户 Lisa 点击了一个 Facebook 广告
1. 访问记录(wb_visits)
─────────────────────────────────────────────────────────────
visit_id: "v-8f3a-92bc" ← 本次访问唯一标识
visitor_id: "vis-a1b2-c3d4" ← Lisa 的持久化身份
qualifier: "B" ← 被分配到 B 版本落地页
landing_url: "https://site.com/insurance?utm_source=facebook"
referrer: "https://www.facebook.com/"
utm_source: "facebook"
utm_medium: "cpc"
utm_campaign: "q1_homeowner_2024"
fbclid: "AQH8f3a92bcXXXXXX"
created_at: "2024-03-15 14:23:11"
2. Lisa 填写表单并提交(wb_leads)
─────────────────────────────────────────────────────────────
lead_id: "lead-001"
name: "Lisa Chen"
email: "lisa@example.com"
phone: "555-1234"
...其他业务字段...
visit_id: "v-8f3a-92bc" ← 关联到上面的访问记录
visitor_id: "vis-a1b2-c3d4" ← 同一个访客 ID
qualifier: "B" ← 她看的是 B 版本
wct_click_id: null ← 这次不是 WCT 平台来的
3. 现在可以回答的问题
─────────────────────────────────────────────────────────────
Q: Lisa 从哪里来的?
A: Facebook 付费广告(utm_source=facebook, utm_medium=cpc)
Q: Lisa 看的是哪个版本的落地页?
A: B 版本(qualifier=B)
Q: Lisa 的 fbclid 是什么?(用于 Conversion 回传)
A: AQH8f3a92bcXXXXXX
Q: 这次转化归属于哪个广告系列?
A: q1_homeowner_2024
这就是第一方数据体系的价值:每一条 lead 记录背后,都有完整的来源信息,支持精准的归因和分析。
本章小结
-
身份识别是归因体系的基础:准确识别"同一个访客",才能追踪完整的转化旅程。
-
访客(Visitor)、会话(Visit)、事件(Event)是三个不同层级的概念,对应 visitor_id、visit_id 和具体的行为记录。
-
visitor_id 需要通过 HTTP 响应头设置 Cookie,才能避免 Safari ITP 的 7 天有效期限制。
-
visit_id 每次访问重新生成,是连接"广告来源"和"转化行为"的桥梁。
-
第一方数据体系需要具备完整性、准确性、关联性、可操作性四个属性。
核心行动建议:在设计你的追踪系统之前,先明确定义"访客"和"会话"的边界,这两个定义会影响后续所有的数据结构和业务分析。
→ 继续阅读:第03章 — UTM 参数工程,深入讲解流量来源标记的规范与最佳实践。