博客SEO

Odoo 博客为什么“封面好看”还不够:cover、SEO 元数据与 canonical 链路讲透

Odoo blog post 不是正文加封面图这么简单。cover_properties、Open Graph、seo_name、canonical URL 和语言本地化会一起决定文章在搜索引擎、社交分享和多语言页面中的真实表现。

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

先说结论

Odoo 博客的“发布完成”,绝不是正文写好、封面上传、点一下 published 就结束。

website_blog/models/website_blog.pywebsite/models/website.py 看,博客发布实际至少同时受四层内容机制影响:

  1. cover_properties 决定页面首屏与社交图像来源;
  2. website.seo.metadata 负责 title、description、Open Graph、Twitter 卡片等元数据;
  3. seo_name 和 slug 共同影响 URL 长相;
  4. 站点级 canonical URL 与语言本地化逻辑,决定搜索引擎最终应把哪条地址视为规范版本。

所以正确理解应该是:

一篇 blog post 在 Odoo 里是“内容对象 + 展示封面 + SEO 元数据 + 规范地址”的组合体。

只要把它当成单纯 CMS 正文页,SEO、分享卡片和多语言规范地址迟早会出问题。

一、为什么博客模型一上来就继承 cover 和 SEO mixin

blog.post 继承的 mixin 很说明问题:

  • website.seo.metadata
  • website.published.multi.mixin
  • website.page_visibility_options.mixin
  • website.cover_properties.mixin
  • website.searchable.mixin

这不是为了“功能多一些”好看,而是在定义博客对象的本质:

  • 它不仅有正文;
  • 它还必须可被网站搜索;
  • 必须能控制发布可见性;
  • 必须携带封面展示属性;
  • 必须能产出适合搜索引擎和社交平台的元信息。

所以博客封面从一开始就不是装饰,而是内容分发链路的一部分。

二、为什么 cover_properties 不只是页面背景,而是分享图来源

_default_website_meta() 里有个特别关键的细节:

  • og:imagetwitter:image 直接从 cover_propertiesbackground-image 里提取。

也就是说,很多人以为“封面只影响文章头图显示”,但源码实际上告诉我们:

  • 这张图还会被拿去当社交分享图;
  • 它会影响链接预览;
  • 甚至会影响内容在聊天工具、社交网络里的第一印象。

这会带来两个很现实的运营后果:

1. 封面不是只给站内看的

如果封面裁切差、尺寸怪或引用异常,问题不只在页面首屏,也会体现在分享卡片上。

2. 封面字段和 SEO 图像字段并不是两条完全独立的线

在默认逻辑下,它们天然相连。

所以“页面好看但分享卡片不好看”,很多时候不是社交平台抽风,而是封面资产本身就没按分享场景设计。

三、为什么 subtitle 比很多人想的更像 SEO 核心字段

同一个 _default_website_meta() 里:

  • og:description 用的是 subtitle
  • twitter:description 用的是 subtitle
  • 默认 meta description 也是 subtitle

这说明在 Odoo 博客语义里,subtitle 不是可有可无的副标题,而更像:

给搜索引擎和分享渠道准备的一段简明内容说明。

如果团队只认真写正文,不认真写 subtitle,就会出现一种常见错觉:

  • 页面内容明明不错;
  • 但 Google 摘要、社交分享描述、预览文案都很平。

原因往往不是抓取失败,而是默认元描述压根就没有被运营化处理。

四、为什么 seo_name 和 blog/post slug 一起决定 URL 观感

_compute_website_url() 会把博客文章路径拼成:

  • /blog/<blog_slug>/<post_slug>

website/models/ir_http.py 又说明:

  • 如果对象带 seo_name,slug 生成会优先利用它。

这意味着 Odoo 博客 URL 不是单一文章字段在起作用,而是:

  • 博客容器 slug;
  • 文章对象 slug;
  • 以及可翻译、可编辑的 seo_name

这就解释了为什么有些站点会碰到:

  • 同一篇文章换语言后 URL 观感不同;
  • 标题改了但旧链接还存在重定向需求;
  • blog 本身的命名也会影响文章路径。

所以 URL 设计不是正文编辑完成后再临时想一下,而应该在栏目层和文章层一起规划。

五、为什么 canonical 是博客 SEO 最容易被忽略的一环

website._get_canonical_url() 会基于当前请求语言和站点 base URL,生成规范地址。

_is_canonical_url() 则用它来判断当前请求是不是规范版本。

这意味着 canonical 在 Odoo 网站里不是插件式附加功能,而是站点级路由语义的一部分。

它尤其影响两类问题:

1. 多语言地址

同一篇内容在不同语言、不同路径前缀下,搜索引擎应该把哪条当主版本。

2. 编码与地址标准化

源码还特别提到含可引用字符的路径,当前 URL 与 canonical URL 的比较会更谨慎。

这说明 canonical 问题不是只跟“有没有 <link rel=canonical>”有关,还跟:

  • 当前请求 URL 是否标准;
  • 多语言本地化路径是否一致;
  • 域名和 base URL 是否统一。

六、为什么“已发布”仍然可能不是一个稳定的 SEO 成品页

即使 website_published = True,一篇博客也不必然已经具备理想的搜索和分享表现。

你还得同时确认:

  • subtitle 是否适合作为默认 description;
  • cover_properties 是否能产出合格分享图;
  • seo_name 是否稳定、可读、适合长期保留;
  • canonical 是否落在预期语言和域名上;
  • 站点是否用统一 base URL 输出规范链接。

也就是说,发布状态解决的是“能不能看见”,SEO / canonical 解决的是“应该怎样被看见”。

最后给内容站运营者的 4 个提醒

1. 把 subtitle 当成 SEO 资产来写

别把它当副标题填空题。

2. 封面图要按社交分享场景设计

否则首屏能看,不代表卡片能看。

3. URL 规划要同时考虑 blog 与 post 两层 slug

别只盯单篇文章。

4. 多语言博客上线前一定检查 canonical

否则很容易把搜索权重分散到多个地址上。

参考源码

  • addons/website_blog/models/website_blog.py
  • addons/website/models/website.py
  • addons/website/models/ir_http.py

DISCUSSION

评论区

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