canonical 失效的五种冲突,以及 Google 的取舍
Google 自己的用词是「提示,而非规则」。这是站内信号互相打架的五个位置,以及 Google 会听谁的。
canonical 标记是提示,不是规则。Google 关于规范化的文档就是这么写的,规范网址由 Google 自己决定,依据包括重定向、是否出现在站点地图里、对 HTTPS 的偏好和 hreflang 集群,而不只是你的标记。这些信号互相矛盾时,你的标记就可能落败。下面是造成这种局面的五种冲突。
canonical 标记是指令还是提示?
是提示。Google 的 What is canonicalization 页面明确写道,指明规范网址偏好是一个提示,而不是规则。Google 会把它判定为重复的页面聚成一个集群,再在其中挑出它认为最完整、对搜索用户最有用的那一个。你的标记只是这个判断的输入之一,而且它在一份公开的强度排序里有固定位置。
| 信号 | 强度 | Google 的说法 |
|---|---|---|
| 重定向 | 强,排在第一位 | 表示重定向目标应成为规范网址的强信号 |
| rel=canonical 注解 | 强,排在第二位 | 表示所指定网址应成为规范网址的强信号 |
| 收录进站点地图 | 弱 | 有助于站点地图中的网址成为规范网址,但哪些是重复页仍由 Google 判断 |
| HTTPS 优先于 HTTP | 来自站点配置的信号 | 除非存在冲突信号,否则 Google 更倾向以 HTTPS 页面作为规范网址 |
| 属于某个 hreflang 集群 | 来自站点配置的信号 | Google 更倾向选择属于 hreflang 集群的网址 |
进入具体冲突之前,先记住两条最佳实践。不要用 robots.txt 做规范化,因为被屏蔽的网址 Google 仍可能收录,只是没有内容。也不要用不同手段给同一个页面指定不同的规范网址。
canonical 可以指向被 noindex、被屏蔽或会重定向的页面吗?
可以这么写,但每一种都会削弱这个标记。Google 不建议在同一网站内用 noindex 来挑选规范页面,因为那会让页面彻底从搜索中消失,它明确把 rel=canonical 列为首选方案。指向被 robots.txt 屏蔽的网址更糟:noindex 文档写得很清楚,抓取工具取不到页面,就永远看不到页面上的任何规则。
重定向是微妙的那一类,因为在 Google 自己的排序里,重定向排在 canonical 标记之前。文档只展开了一个场景:HTTPS 页面把用户重定向到 HTTP 或经由 HTTP,或者带有指向 HTTP 版本的 canonical,都被列为冲突信号,而 HTTPS 到 HTTP 的重定向会让 Google 非常强烈地偏向 HTTP。除此之外,canonical 指向一个会重定向的网址会发生什么,文档并没有写。所以请自己追一遍目标地址,用我们的重定向检测工具追踪,再把标记指向那个返回 200 的网址。
站点地图和 canonical 标记不一致会怎样?
这一条 Google 在最佳实践里直接点名了:不要在站点地图里写一个网址,又用 rel=canonical 给同一个页面指定另一个。站点地图收录是两者中较弱的信号,所以通常是标记说了算,但你提交的每个网址都会被当作规范网址的候选,而哪些属于重复页仍要由 Google 判定。修法很无聊:让站点地图和 canonical 标记出自同一份数据源,然后用我们的站点地图校验工具检查文件。到底该放哪些页面进去,可以看站点地图最佳实践。
rel=canonical 会和 hreflang 冲突吗?
经常冲突,而且多语言站点受伤最重。Google 的要求是:指定同一语言的规范页面;如果该语言没有,就指定最合适的替代语言。把中文页面的 canonical 指向英文网址,等于主动请 Google 丢掉中文版。
同一批文档里还有两个细节。带 hreflang、lang、media 或 type 属性的 rel=canonical 注解根本不会用于规范化,那是 rel=alternate 的职责。另外,是否身处集群本身就是信号:Google 举的例子是互相引用的 de-de 和 de-ch 页面会被优先选为规范网址,而被落在集群外的 de-at 页面则不会。会拆散这类集群的注解错误,我们的 hreflang 指南里讲过。
需要指向自身的 canonical 吗?
Google 建议加。它的最佳实践要求在规范页面自身上也放一个 rel=canonical 链接,也就是自引用 canonical。
真正出事的是那些用请求网址拼出标记的模板。访客带着跟踪参数进来,标记立刻指向那个带参数的变体,于是每一次广告点击都在声明自己的规范网址。Google 用来举例的「不希望出现在结果里的网址」,正是一个带 gclid 参数的商品页。同一页面还有两条约束:用绝对网址而不是相对路径;绝不要把 canonical 指向网址片段,因为 Google 通常不支持片段。
canonical 写在 head 之外或用 JavaScript 注入还有效吗?
写在 head 之外无效。Google 说明,rel=canonical 链接元素只有出现在 HTML 的 <head> 部分才会被接受,并补充说至少 head 部分必须是有效的 HTML。问题往往就出在后半句:一个没闭合的标签就会把 canonical 挤进 body,在那里它什么都不算。
JavaScript 受支持,但不推荐。JavaScript SEO 基础页面说,Google 搜索会在渲染页面时读取注入的 canonical;而规范化页面则要求你把网址写在 HTML 源码里,并确保 JavaScript 不会把它改成别的值。如果实在没法写进源码,就干脆完全不写,只用 JavaScript 设置。无论哪种做法,只输出一个:Google 警告说,冲突的或多个 rel=canonical 标记可能导致意料之外的结果。
怎么查 Google 实际选了哪个规范网址?
Search Console 的网址检查工具会把 Google 选定的规范网址和你声明的那个并排列出。Google 的排错页面还补了一句值得先知道的话:即使内容问题已经修好,页面仍可能在重复集群里停留最多两周;页面之间的差异越清晰、越显著,分离得越快。当然,如果抓取工具根本到不了这个页面,以上都不成立,而那只是花五分钟看一眼你的 robots.txt。