访客追踪

Odoo 网站访客为什么不是“匿名 Cookie”:身份 token、浏览轨迹与登录合并主链路讲透

很多人把 Odoo 网站访客理解成一条轻量统计记录,但 website.visitor 实际同时处理匿名身份 token、页面轨迹、8 小时 visit 计数、登录后 partner 归并与过期清理,是一套前台身份聚合机制。

网站
进阶 开发者 2 分钟阅读
0 评论 0 点赞 0 收藏 5 阅读

先说结论

在 Odoo 里,网站访客不是一个“记一条 pageview 就完事”的统计对象。

/home/ubuntu/odoo-temp/addons/website/models/website_visitor.pytests/test_website_visitor.py 看,website.visitor 实际承担的是:

  • 给匿名或已登录访问者生成稳定身份;
  • 记录页面访问轨迹;
  • 把短时间连续浏览和跨 8 小时再访问区分开;
  • 登录后把匿名轨迹归并到 partner 身份;
  • 对长期无价值的匿名访客做定期清理。

所以它更像:

一个网站前台身份聚合层,而不是单纯流量报表表。

这也是为什么它既跟 request、session、partner 有关系,又跟 page tracking、清理 cron 和消息联系能力绑在一起。


一、访客身份为什么不是随机 UUID,而是跟登录状态强绑定

_get_access_token() 是整条链路的起点。

它有两种模式:

1. 已登录用户

如果当前用户不是 public user,access token 直接用:

  • request.env.user.partner_id.id

这说明登录态访客的目标非常明确:

  • 不是再造一层匿名身份;
  • 而是直接把网站行为和真实业务联系人对齐。

2. 匿名用户

如果还是 public user,token 会根据:

  • IP
  • User-Agent
  • session id

拼接后做 hash,截成固定长度。

也就是说匿名访客也不是完全一次性的,它在“同一会话 + 同类访问环境”下尽量保持稳定。

这套设计透露出一个很实际的目标:

网站先尽量聚合同一个人,再考虑后续是否能把他认成业务联系人。


二、为什么 visit_count 不是每次点开页面都 +1

源码里 visit_count 的定义很有意思:

  • 如果上次连接时间距离现在超过 8 小时,才算一次新 visit;
  • 否则只是当前 visit 内的继续活动。

这比“每个 pageview 都算一次访问”更接近运营语义。

因为真实世界里:

  • 用户连续看 10 个页面,不代表 10 次访问;
  • 早上看一次、晚上再回来一次,才更像两次独立 visit。

对应地,website_track 仍会继续记 page-level 轨迹,二者职责分开:

  • visit_count 看会话级访问次数;
  • website_track_ids 看页面级轨迹。

三、为什么 tracked page 与 untracked page 会被区别对待

测试文件里很清楚地构造了:

  • track = False 的 view;
  • track = True 的 view。

只有 tracked 页面会进入 _handle_webpage_dispatch(),继而触发:

  • 获取或创建 visitor;
  • 新增 website.track 记录。

这说明 Odoo 的设计并不是“所有页面一律统计”,而是:

哪些页面值得作为行为证据追踪,要由页面层显式决定。

这很合理。

因为有些页面只是技术跳板、空白容器或不重要的中间视图,没有必要每次都计进访客行为证据里。


四、为什么 visitor 里同时存 country、lang、timezone 和 partner 映射

website.visitor 不是只记轨迹,它还记:

  • country_id
  • lang_id
  • timezone
  • partner_id
  • email
  • mobile

但这些字段背后来源并不一样:

1. 国家与语言

创建 visitor 时会从当前 request 环境里取:

  • geoip country code
  • request.lang

2. 时区

优先从 cookie tz 里拿; - 如果没有,再看已登录用户自己的时区。

3. 联系方式

不是直接存一份独立真值,而是从 partner_id 关联读取。

这意味着 Odoo 想要的是:

  • 前台行为身份有自己的访问上下文;
  • 一旦能和业务联系人对上,就尽量复用正式联系人数据,而不是再维护一套平行资料。

五、为什么登录后会发生访客归并,而不是简单新建一条登录访客

_merge_visitor() 很能体现这套模型的目标。

当匿名访客后来登录后,系统不会简单保留匿名 visitor 再新开一个已登录 visitor,然后任由数据分裂。

它更倾向于:

  • 把匿名 visitor 的 tracking 数据迁到目标 partner visitor;
  • 再删除匿名 visitor。

官方测试也专门验证了:

  • 登录前访问过的 tracked page;
  • 登录后继续访问;
  • 最后应该仍尽量归在同一个更有业务价值的身份上。

这背后的想法非常清楚:

访客系统要尽量回答“这个人后来是谁”,而不是永远停留在匿名碎片。

这对后续 CRM、营销自动化、客服联系都更有价值。


六、为什么 _upsert_visitor() 要用原生 SQL UPSERT,而不是普通 ORM create/write

这段实现很值得看。

_upsert_visitor() 直接写 SQL:

  • INSERT ... ON CONFLICT (access_token) DO UPDATE

而不是先 search,再 create 或 write。

原因至少有三个:

1. 并发更稳

高并发访问下,同一 token 的 visitor 很容易被同时命中。

2. 可以把“更新访客 + 记录 track”尽量收敛到一条更紧凑的数据库操作里

源码甚至支持在同一个 SQL 里顺手插入 website_track

3. visit_count 的 8 小时逻辑更容易在数据库层原子化处理

这类“根据旧值判断是否递增”的逻辑,放 SQL 更不容易出竞态问题。

这不是为了炫技,而是网站访问模型天然就比很多后台业务更高频、更并发。


七、为什么 _add_tracking() 不会每次刷新都无限加新轨迹

源码里还有个 30 分钟边界:

  • 如果同一个 visitor 的最近一次匹配页面访问还在 30 分钟内,
  • _add_tracking() 不会无脑再建一条同类 track。

这说明 Odoo 不是要把每次页面刷新都堆成原始日志海洋,而是想在行为可用性与数据膨胀之间找平衡。

对实施来说,这个思路很重要:

  • 如果你期待 visitor track 是完美无损的点击流日志,它不是;
  • 它更偏“足够支撑网站运营与业务判断”的行为摘要层。

八、为什么旧匿名访客会被 cron 清理,而且默认只清没绑 partner 的人

_cron_unlink_old_visitors()_inactive_visitors_domain() 定义了清理策略:

  • 默认保留最近 website.visitor.live.days(默认 60 天)内活跃的访客;
  • 主要清理的是没绑定 partner 且长期不活跃的匿名 visitor。

这特别说明了 Odoo 对 visitor 数据价值的判断:

  • 已经能对上业务联系人的,价值更高,应尽量保留;
  • 长期无人认领、也没新活动的匿名轨迹,保留价值有限,反而会膨胀数据库。

所以它没有继续走“archive 一堆无意义历史访客”的路线,而是直接删除。


九、最容易误解的,是把 visitor 当分析工具而不是身份桥梁

误解一:visitor 就是 GA 风格流量记录

不完全是。

它更强调“这个访问者后面是否能和 Odoo 业务对象接起来”。

误解二:登录后新建一条更干净

这会让匿名行为和真实业务联系人割裂。

误解三:轨迹越细越好

未必。网站业务系统关注的是“够不够支撑运营动作”,不是一定要成为全量日志仓。

误解四:匿名访客都应该永久保留

长期看往往只会把噪音和存储成本一起堆高。


十、实战里怎么利用这套 visitor 机制

1. 把 visitor 看成前台身份缓冲层

它是匿名世界和业务联系人世界之间的桥。

2. 认真区分哪些页面值得 track

不要默认所有页面都追。

3. 如果要做 CRM 或营销联动,优先利用登录后归并能力

别自己再造一套“匿名线索池”。

4. 清理策略不要随便关掉

匿名 visitor 的价值会快速衰减。

5. 对 page-level 统计要理解其“摘要化”属性

它不是原始日志系统。


结语

website.visitor 真正有意思的地方,在于它把网站前台访问行为做成了一条可逐步升格的身份链路:

  • 先是匿名 token;
  • 再是带轨迹的访客;
  • 后来可能和 partner 对齐;
  • 最终成为 CRM、客服或营销动作可利用的证据。

所以它不是一条轻量统计记录,而是:

Odoo 网站把“这个浏览器访问过什么”慢慢转成“这个业务联系人做过什么”的过渡层。

DISCUSSION

评论区

想参与讨论?先 登录 再发表评论。
还没有评论,你可以成为第一个留言的人。