UTM 入链路

Odoo 的 utm.mixin 为什么不只是“记个来源”:从 URL 参数、Cookie 到业务记录字段的链路讲透

很多人知道 Odoo 会把 utm_source、utm_medium、utm_campaign 带进线索或表单,但经常只把它理解成前端埋点。本文结合官方源码讲清 utm.mixin 如何从 URL 参数写 Cookie,再在 default_get 时落到业务记录字段上。

Odoo 开发
进阶 开发者 1 分钟阅读
0 评论 0 点赞 0 收藏 7 阅读

先说结论

很多人以为 Odoo 里的 UTM 只是:

  • 页面 URL 上多几个参数
  • CRM 线索里多几个来源字段

但如果只这么理解,就会低估它的设计。

从官方源码看,utm.mixin 真正在做的是:

把一次匿名访问里的营销来源信号,沿着请求链路保存下来,并在后续建业务记录时自动注入对应字段。

也就是说,它不是孤立字段,而是一条完整链路:

  • URL 参数
  • HTTP 响应写 Cookie
  • default_get() 读取 Cookie
  • many2one 值按名字查找或创建
  • 最终落到业务记录的 campaign_id / source_id / medium_id

utm.mixin 本身提供了什么字段

/home/ubuntu/odoo-temp/addons/utm/models/utm_mixin.py 里,定义很直接:

  • campaign_id
  • source_id
  • medium_id

都是 many2one。

这已经说明一个关键点:

Odoo 不把 UTM 只是当字符串保存,而是倾向于把它结构化成可复用的主数据。

所以来源不是随手贴在记录上的文本标签,而是能在系统里继续聚合、统计、归类的对象。


很多人只看 utm.mixin 模型文件,会漏掉 HTTP 那一半。

/home/ubuntu/odoo-temp/addons/utm/models/ir_http.py 中,Odoo 重写了 _post_dispatch(),并在里面调用 _set_utm()

_set_utm() 做的事情很明确:

  • 检查请求参数里有没有 utm_campaign / utm_source / utm_medium
  • 如果有,而且当前 Cookie 值不同
  • 就往响应里写入:
  • odoo_utm_campaign
  • odoo_utm_source
  • odoo_utm_medium

而且默认保存 31 天。

这意味着:

UTM 信号并不是只在“这一跳请求”里存在,而是被延续到了后续访问。

这正是“访问来源能影响后来建单”背后的关键。


业务记录是怎么自动拿到这些值的

答案在 utm.mixin.default_get()

源码逻辑大致是:

  • 先走父类 default_get()
  • 然后逐个检查 tracking_fields() 里定义的来源映射
  • 如果当前要创建的字段里包含这些 UTM 字段
  • 且当前 request 存在
  • 就从 Cookie 里取对应值
  • 如果字段是 many2one 且 Cookie 里是字符串,就 _find_or_create_record()
  • 最后把结果塞进默认值

这说明 utm.mixin 的思路不是“等你提交表单时手写映射”,而是:

在 ORM 默认值阶段,就把来源字段自动补进去。

这设计很漂亮,因为它让:

  • 网站表单
  • 线索创建
  • 其他继承 utm.mixin 的对象

都能复用同一条默认值注入链。


为什么源码里还特地处理 many2one 的查找/创建

因为 Cookie 里拿到的通常是字符串,比如:

  • Google
  • Email
  • Spring Campaign

但模型字段是:

  • utm.source
  • utm.medium
  • utm.campaign

这些主数据表的 many2one。

所以 _find_or_create_record() 会:

  • 先按名字模糊找
  • 找不到再创建
  • 某些模型还会补 is_auto_campaign

这一步很重要,因为它把“前端来源文本”转成了“后端结构化对象”。

也因此,utm.mixin 不是简单埋点,而是埋点到业务主数据的桥接层


为什么有个“销售员默认忽略 UTM”的判断

源码里还有个很容易忽略的逻辑:

  • 如果当前用户不是 superuser
  • 且属于销售员组
  • default_get() 就直接返回,不去吃这些 UTM 值

这说明 Odoo 也在防止某些内部人工操作把匿名来源信号不当地继承进去。

换句话说:

UTM 更偏向“外部访问来源带进来的默认语义”,而不是所有后台人工建单都机械套用。

这能减少来源污染。


最常见的误解

误解 1:UTM 只是前端统计参数

不对。

在 Odoo 里,它还会进入 ORM 默认值链路,最终影响业务记录字段。

误解 2:来源字段一定要前端表单自己传

不一定。

很多时候,Cookie + default_get() 已经替你串好了。

误解 3:来源值只是字符串,不值得结构化

官方正相反:它尽量把来源结构化成 many2one 主数据。


对自定义开发最有价值的启发

如果你要让自定义对象也带来源归因,思路往往不是:

  • 自己在控制器里东拼西凑
  • 提交表单时手工塞三个字段

而是优先考虑:

  • 让对象继承 utm.mixin
  • 明确你是否需要扩展 tracking_fields()
  • 想清楚哪些对象该自动继承来源,哪些不该

这样你接的是 Odoo 现成的链路,而不是另起一套半自动规则。


一句话收尾

utm.mixin 的价值不只是“记录来源”,而是把 URL 参数、Cookie、默认值注入和主数据结构化串成了一条完整归因链。

DISCUSSION

评论区

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