其他深度

Odoo 营销卡为什么不只是“生成一张图”:UTM、跳转链接与落地页转化闭环讲透

很多人看到 marketing_card,第一反应是“可以批量做社媒海报”。但源码真正有价值的地方,是 campaign 在创建时就绑定 link.tracker、自动挂 UTM 来源、每张 card 都有独立 preview/redirect 路径,还能把 shared 与 visited 汇总回 campaign。它做的是一条从素材到落地页的可追踪链路。

其他
进阶 开发者 2 分钟阅读
0 评论 0 点赞 0 收藏 6 阅读

先说结论

marketing_card 不是一个“自动出图小工具”,而是一套把动态素材、分享入口、UTM 跟踪、点击跳转和结果回写连起来的传播闭环。

/home/ubuntu/odoo-temp/addons/marketing_card/models/card_campaign.pycard_card.pycard_template.py 看,Odoo 这里真正做的事情是:

  1. 给一个 campaign 绑定目标模型和目标链接
  2. 为 campaign 自动创建 link.tracker
  3. 给每一条目标记录生成唯一 card
  4. 让每张 card 自带 preview / image / redirect 路径
  5. sharedvisited 回写执行状态
  6. 用聚合计数把转化反馈回 campaign

这说明它的重点不是“图做出来没有”,而是:

一张图从被生成、被分享、被访问,到把人送进目标落地页,整个过程能不能追得回来。


第一层:为什么 campaign 创建时就先建 link.tracker

card.campaign.create() 非常关键。

它会在 campaign 建立的同时,先创建一个 link.tracker,并且把:

  • url
  • title
  • source_id
  • label

都一起准备好。

其中最重要的是两件事:

1. 没有 target_url 也会给默认 base_url

这表示 campaign 从诞生那一刻起,就被视作一个有明确跳转目标的传播动作,而不是纯设计稿。

2. 会尝试挂上 utm_source_marketing_card

也就是说,Odoo 不是等点击来了再想“要不要做归因”,而是在 campaign 一创建时就默认:

  • 这是一种有来源标记的营销流量

这套设计非常像成熟营销系统的思路:

归因不是事后补表,而是事前埋点。


第二层:为什么 campaign 允许的模型被刻意限制

_get_model_selection() 并不是对所有模型开放,而是硬编码白名单:

  • res.partner
  • event.track
  • event.booth
  • event.registration

很多人看到这里会觉得“为什么不更通用”。

但这恰恰说明 Odoo 在刻意控制场景边界。

因为 marketing card 不是万能图片工厂,而是用于几类高度明确的传播场景:

  • 邀请联系人转发
  • 宣传活动议程和讲师内容
  • 让展商传播自己参展
  • 让报名人或参与对象帮忙扩散

场景越明确,动态字段、落地页、归因路径就越容易做稳定。

如果一开始就开放所有模型,模板和路径的复杂度会快速膨胀,最终变成谁也不敢维护的系统。


第三层:为什么 preview card 会被单独缓存和归档

_fetch_or_create_preview_card() 的行为很有意思:

  • 找已有预览卡就更新图片并 archive
  • 没有就创建一张 preview card
  • image_preview 作为它的图像内容

这说明 preview 并不是一张临时截图,而是系统里一个明确对象。

它的价值在于:

1. 预览路径稳定

你可以有一个稳定的 preview URL 给内部审样或测试邮件用。

2. 预览与正式发放分离

preview card 可以 archive,避免它和正式分发对象混在一起。

3. 设计变更后可以重新渲染

不是只存模板文本,而是把预览结果作为资产对象对待。

这让营销卡的“发前确认”动作更可靠。


第四层:为什么卡片要对每条记录唯一,而不是一张图大家共用

card.card 上有唯一约束:

  • unique(campaign_id, res_id)

这意味着在同一个 campaign 里,每个目标对象只有一张唯一 card。

这背后的业务收益非常大。

因为一旦 card 和对象一一对应,你就可以稳定地拥有:

  • 每个对象自己的分享地址
  • 每个对象自己的 redirect 路径
  • 每个对象自己的状态回写

举个活动场景:

  • 一个 booth 一张 card
  • 一个演讲 track 一张 card
  • 一个 registration 一张 card

这样你就不只是“生成了一批海报”,而是在给每个传播对象分配可追踪的独立传播入口

这和一张 JPEG 群发全员,完全不是一个层级。


第五层:为什么 redirect 路径比直接放 target_url 更重要

card.card 里有:

  • _get_card_url()
  • _get_redirect_url()
  • _get_path()

也就是说,一张卡片不只是有图片地址,还有自己的 redirect 地址。

这点非常关键。

如果所有人都直接跳原始 target_url,你很难回答:

  • 用户到底是从哪张 card 点进去的
  • 是哪个 booth、哪个报名对象、哪个传播对象带来的访问
  • 哪个 campaign 下的哪类资产更有效

而有了中间 redirect 层后,系统就能在“用户到达目标页之前”留下一次可归因的路径。

这其实就是营销链路里最重要的一件事:

别只关心内容有没有被看到,更要关心它把人送到了哪里。


第六层:为什么 shared 和 visited 都值得统计

share_status 只有两个值:

  • shared
  • visited

而 campaign 的统计逻辑会认为:

  • shared 隐含也发生过访问
  • visited 代表至少有人点开或到达过

很多人会觉得这两个状态太粗。 但它其实抓住了传播闭环里最重要的两个门槛:

第一门槛:有没有人愿意拿去转发

这是 shared

第二门槛:转发出去后有没有带来访问

这是 visited / click。

这比一堆花哨但解释困难的指标更实用。 因为大多数运营复盘最后真正要回答的,往往就是:

  • 卡片有没有被人采用
  • 采用之后有没有带访问

第七层:为什么设计变更会把 card 标记为 requires_sync

当 render 字段变化时,系统会把相关卡片打成 requires_sync = True,之后 _update_cards() 再批量重渲染。

这说明 Odoo 很清楚营销素材的一个现实问题:

  • 模板会改
  • 文案会改
  • 目标记录的数据会变
  • 旧图会过时

如果没有同步标记机制,系统很快就会出现:

  • 页面里展示的是新文案
  • 外发图却还是旧版本

requires_sync 的存在,让 card 不只是一次性导出的静态文件,而是可重新对齐 campaign 当前状态的派生资产


第八层:为什么还要自动清理旧 card 图像

_gc_card() 会按配置清理 오래未更新的 card 图像。

这个设计说明 Odoo 默认认为:

  • 社交平台会缓存图片
  • 旧 card 不应该无限期占资源

它不是简单“删缓存省空间”,而是在假设传播资产具有生命周期。

这也提醒实施方一个现实问题:

营销卡不是永久主数据,它更像一批可再生成的短中期传播资产。


最后一句

marketing_card 最值得学的地方,不是它能批量做图,而是它把传播对象、UTM 来源、redirect 路径、状态回写和聚合统计都绑在了一起。

所以如果你把它只当海报工具,就会错过它真正的价值; 如果把它当成一条从卡片到落地页的可归因转化链,这套设计就会突然非常合理。

DISCUSSION

评论区

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