页面被持续降权,Google 认定的“正主”却是个赌场网站。Mueller 的回应里,藏着比跨域 Canonical 更该关心的事


大家好,我是Neo。

9月中旬,Search Engine Journal 上 Roger Montti 写了一篇我读了两遍的文章:一个 Reddit 用户报告自己的站点正在“缓慢但持续地掉出 Google 索引”,查下去发现,Google 认定的 canonical(正主)竟然是一个跟他业务完全不相关的赌场投注页。

原话大意是:他们的页面都是讲公司和供应商的,而 Google 认为的规范版本是一个赌场页;他翻遍了那个赌场站,找不到任何跟自己内容沾边的页面。

这个帖子后来被 John Mueller 亲自回应了。而 Mueller 的回应,以及另一位 Reddit 用户的补充,把这件事指向了一个跟“跨域 canonical”关系不大、但每个做独立站的人都该知道的技术问题:你的网站可能在给 Googlebot 返回一张“报错壳页”。

这篇我把这件事拆成三层:这个说法哪里站不住、真正的因果链长什么样、以及你现在花 30 分钟能查什么。

先把两个概念说清楚

Cross-domain canonical(跨域 canonical):就是写在 A 网站页面上的 rel="canonical",指向 B 网站的一个 URL。它的作用相当于告诉搜索引擎“这篇内容的正版在别人家”。它是站内 canonical 的跨站版本,Google 一直把它定义为强提示(strong hint),不是命令。

历史上它有两种用法:

  1. 域名迁移的兜底——当 301 重定向因为某些原因实在做不了时,用它把信号传给新域名。放到今天,这种情况基本不该出现了。
  2. 内容同步/转载(syndication)——同一篇文章你发在自己站,也同步给合作媒体,用跨域 canonical 告诉 Google 谁是原版。这个用法后来也被 Google 改了建议。

Google 现在的官方文档(关于 syndicated content 的部分)写得非常直白:转载方应该在文章里加 robots meta 标签来阻止收录,只挡 Google News 就用 <meta name="Googlebot-News" content="noindex">,要同时挡搜索就用 <meta name="Googlebot" content="noindex">。

也就是说:跨域 canonical 已经是一个“没有理由再用”的工具。原因很简单——它只是提示,而 301 重定向和 noindex 是 Google 有义务执行的。用一个“别人可以不听”的方案,去解决一个“有绝对方案”的问题,没有意义。

那“被跨域 canonical 降权”这件事,成立吗?

这里 Montti 的分析很关键,我把它翻译成一句可操作的话:

要让跨域 canonical 真的生效,必须是你自己的页面上写着指向对方的 canonical。

因为信号是从你这边传出去的,不是对方抢走的。如果对方站点上写一行 canonical 指向它自己,跟你没关系;只有你的页面写了指向它,信号才会转移出去。

所以如果你检查完自己的页面,发现根本没有指向外域的 canonical,那这件事基本只有两种可能:

  • 你的站被黑了。 攻击者往你的模板或数据库里注入了指向别处的 canonical。这种情况必须当作安全事故处理。
  • 这压根不是跨域 canonical 的问题。 你看到的只是两个同时发生的现象,被你顺序连成了因果关系。

Montti 在文里讲了一个我很喜欢的比喻:SEO 里的“巧合”长什么样?他举了两个例子——很多人说 disavow 外链几周就见效,实际上它是按月计的;还有很多人把“站内有多篇相似内容”叫成“关键词蚕食”,其实一个站讲一个主题,本来就会有很多页相似内容,那是正常的。他说这有点像“肚子不舒服就说吃了不干净的东西”,实际上可能是别的原因。

Neo的解读:这不是在嘲笑提问的人,而是在说一件对我们更有用的事——降权类问题里,90% 的“原因”是我们自己贴上去的标签。canonical 被抢、被降权、被算法打击,这类标签贴起来很爽,因为它指向外部、不需要改自己。但只要你承认可能是自己站的输出问题,排查方向立刻就变了。

真正的元凶:给 Googlebot 的那张“报错壳页”

这个帖子里最有价值的,是另一位 Reddit 用户(ID 是 No_Wrap_9584)的补充。他自己遇到过一模一样的情况,并且找到了机制。

他的原话大意是:

用 Google 搜那个第三方 canonical URL,结果显示的标题是“Application error: a client-side exception has occurred (see the browser console for more information)”——这是一条通用的 JavaScript 应用报错信息。而我们自己的站,在偶发故障、应用加载不正常的时候,显示的正好是同一句话。所以我们怀疑:Googlebot 在某个时间点抓到的不是真实页面内容,而是一个错误页/回退响应;Google 就把多个显示同一张错误壳的 URL 当成了重复内容,于是选了一个“外部”页面做 canonical,我们的页面随后掉出索引。

他描述的三种情况其实都指向同一个结果(后面 Mueller 也确认了):

结果 含义 对你的影响
A. 你的页面被当作 canonical,但收录的是服务器报错信息 Google 收了你,但收的是错误文案 页面在正常内容上不出现在搜索里
B. 你的页面被判定成 soft-404 Google 认为这页没内容 同上
C. 别人的页面成了 canonical 你的页面被视为副本 同上

注意第三种情况的荒谬之处:A 和 B 就是你自己的问题,C 只是它的一种表现形式。 这就是为什么我说“跨域 canonical 降权”是一个误导性的描述——它不是原因,它是症状之一。

这条报错信息是什么来头

我去查了这条具体的报错。Application error: a client-side exception has occurred (see the browser console for more information) 是 Next.js 默认的客户端异常页面——它是 React 应用在浏览器端抛错时兜底显示的那一屏。

这个症状在开发者社区里跟 Search Console 的 Soft 404 已经绑了不止一年:Next.js 仓库的 issue 里,从 2018 年就有人在问“Next.js 会不会导致 Search Console 里的 Soft 404”,2024–2026 年仍然有大量讨论帖在处理“URL 完全正常、返回 200、内容也在,但 GSC 就是报 Soft 404,而 URL 检查工具给出的抓取结果是那句 Application error”。

其中一个被反复提到的机制是版本错位(version skew):

  1. Googlebot 第一次抓取时,加载的是你那一版构建的 JS chunk;
  2. 你在两次抓取之间重新部署了,旧 chunk 的文件名变了,原来的 URL 变成 404;
  3. Googlebot 第二遍抓取(Google 会做两阶段抓取)时,去加载旧 chunk → 加载失败 → 页面渲染中断 → 只留下一张报错壳;
  4. Google 把它归类为 Soft 404(或按上面的 A/B/C 三种方式处理掉)。

这解释了为什么这种问题最难查:你自己打开页面永远是对的(你的浏览器拿的是新 chunk),只有带着旧快照回来的爬虫看到的是烂页。而且它不是“永久坏掉”,它会间歇性出现,所以你会觉得“时好时坏”。

有意思的是,这跟一个更老的问题同源:AI 时代的抓取器基本不执行 JavaScript。多家第三方做的 AI 可读性审计都在提醒同一件事——GPTBot、OAI-SearchBot、ClaudeBot、PerplexityBot 这类抓取器拿的是服务端返回的 HTML,只有 Googlebot 会去渲染。对一个全靠客户端渲染、又时不时吐报错壳的站来说,丢的不只是 Google 的收录,还有 AI 搜索的整条入场资格。

Mueller 的完整回应:三种结局都很差,所以要在“上线前”解决

Mueller 先说这个解释“可能成立”,然后建议用 Search Console 的网址检查工具(Live URL Checker) 看 Google 实际渲染出来的页面长什么样。

他第二条回复更实在,我把它完整转述一遍(要点):

  • 他明确说“这个问题本身其实不重要”——是的,三种结局都很让人困惑,但三种结局的后果是一样的:你的页面在正常内容上不出现在搜索里。所以纠结“到底算 A 还是 B”没意义。
  • 真正的解法是让这类错误在你手上被发现,而不是让谷歌先发现。 Mueller 提到他自己做小站的方式:上线前跑大量自动化测试;只要发现一次线上问题,就让代码代理给这个场景补一个测试用例。
  • 还可以加监控:定时(比如每小时)抓取你最关键的页面,检查有没有异常,这样问题在变成“稳定的爬虫问题”之前就被修掉了。

Neo的解读:Mueller 这段话其实是在讲一个成本结构。你要么花几小时做自动化测试和页面监控,要么花几个月等索引恢复——而且恢复的节奏是按月算的,这条我们在 9 月 4 日那篇里写过(“排名恢复按月算,不按周算”)。这笔账很好算。

30 分钟巡检清单:如果你怀疑自己的站也在“吐错误页”

按这个顺序做,先做便宜的:

步骤 怎么查 通过标准
1. 查有没有指向外域的 canonical 全站搜索页面源码 / HTML 里的 rel="canonical"、HTTP 响应头里的 Link: <...>; rel="canonical",看是否有非本站域名 没有外域 canonical(除非你主动做迁移,且知道自己在干什么)
2. 查是否被黑 GSC 的“安全性问题”、页面源码里莫名的脚本/跳转/canonical 注入 无异常注入
3. 抓取层巡检 用 curl 抓一批关键页(不带 JS),看 HTTP 状态和正文是不是“错误壳” 状态 200 且正文包含真实内容
4. 看 Google 看到的版本 GSC 网址检查 → 测试实际网址 → 看“已抓取的网页”截图和 HTML 与用户看到的版本一致
5. 部署与版本一致性 检查是否有“旧 chunk 404”的可能(构建产物文件名变化、缓存策略) 旧构建的静态资源短期仍可访问,或部署时保持原子切换
6. 上线前的自动化拦网 每次发布后自动抓取核心页,断言“必须包含某段关键文案” 失败即告警,不带病上线

第 3 步是最容易被忽略、也最有效的一步。大多数团队检查的是“页面能不能打开”,而这个问题的定义是“页面能不能被正确打开并抓到”。检查的对象不是你的浏览器,是爬虫。

如果你已经在 GSC 里看到可疑的 Soft 404 或“重复网页,Google 选择的规范网页与用户指定的不同”,顺序应该是:先确认页面内容能稳定、干净地输出 → 再看重定向和 canonical → 最后在 GSC 里请求重新抓取。先修内容再请求抓取,否则你只是让 Google 更快地确认这个页面不行。

顺便说一句转载这件事

如果你做多语言站、或者有内容同步给合作方(这是出海独立站很常见的操作),别再考虑用跨域 canonical 了。按 Google 现在的官方建议:

  • 能 301 就 301;
  • 转载方加 noindex(只挡新闻用 Googlebot-News,要挡搜索用 Googlebot);
  • 原站保留完整版本,别做“两边都想收录”的设计。

这套方案的好处是它不依赖搜索引擎的善意。canonical 是提示,noindex 和 301 是执行。

Neo的解读:这件事真正的启示

我读完这个案例,最想强调的不是 canonical 的技术细节,而是三件事:

第一,“降权”这个标签正在掩盖真问题。 我们习惯把一切掉排名归因到算法、竞争对手、平台,因为这些解释不需要我们改动任何东西。但这次案例里,凶手是自家站点一张随手写出来的报错页。

第二,AI 时代让“技术卫生”的重要性上升了,不是下降。 过去只要 Googlebot 能渲染,客户端渲染的毛病还不至于致命。现在你的内容要同时被 Googlebot、GPTBot、OAI-SearchBot、ClaudeBot、PerplexityBot 等多个抓取器读取,其中大多数不执行 JS。一张偶发出现的报错壳,在传统搜索里可能只是几个 Soft 404,在 AI 搜索里可能意味着你的页面根本没进检索池。

第三,监控是唯一能买到的确定性。 Mueller 那条“每小时抓关键页”的建议,成本几乎为零,收益是“你在谷歌之前发现问题”。这件事没有任何工具能替你判断,只能自己定时跑。

最后

如果你只做一件事:今天去查一下你的站有没有指向外域域名 canonical,然后用 curl 抓三个核心页,确认返回的正文是真实内容而不是一张应用报错页。

这两件事都不需要花钱,也不需要装任何工具,但它们能排除掉一类最隐蔽、后果最长(按月恢复)的问题。

跨域 canonical 导致的降权,绝大多数时候不是跨域 canonical 的问题。真正的问题,是你的页面给爬虫看的那份内容,和给你自己看的那份不一样。