你在 staging 页上加了 <meta name="robots" content="noindex">,一周后发现生产环境的同一页从 Google 消失了。或者反过来:你在感谢页 meta 里写了 noindex,但它还在搜索结果里。两种情况的根源都是同一个——Google 通过两条通道读取 robots 指令,两条不必一致。HTTP 响应头 X-Robots-Tag 是另一条通道;当两者不一致时,Google 不会选一个作权威,而是合并取最严格的值。
也就是说,CDN 规则里一条不起眼的 X-Robots-Tag: noindex 可以静默杀掉一个 meta 里写着 index 的 HTML 页面。View Source 看不出问题,只有 curl -I 能看到真相。
先判断你属于哪种情况
情况 1:meta 里有 noindex,但页面仍被收录
怎么发现:
curl -s https://yourdomain.com/path | grep -i 'name="robots"'
# 输出:<meta name="robots" content="noindex">
curl -sI https://yourdomain.com/path | grep -i x-robots
# 输出:(什么都没有)—— meta 说 noindex,header 什么也没说
然后 Search Console 的 URL 检查里这一页显示已被收录。
原因:自从你加 meta 之后 Google 还没有重新抓取,或者 meta 是用 JavaScript 渲染的、本次抓取里 Googlebot 没执行 JS。header 是每次请求都会读到的;meta 要等重抓 + 渲染才能生效。
修复:把 noindex 渲染进 SSR 的初始 HTML(不要靠客户端 JS),然后用 URL 检查里的”测试实际网址”确认 Google 在渲染 HTML 里看到了 noindex,再点”申请编入索引”触发重抓。完整移除时间线见 设了 noindex 但页面还在搜索结果里。
情况 2:meta 没有 noindex,但页面却从索引消失
怎么发现:
curl -sI https://yourdomain.com/path | grep -i x-robots
# X-Robots-Tag: noindex, nofollow
浏览器打开页面、查看源代码——没有 robots meta,或者写的是 index, follow。罪魁就是这个 header。
原因:典型泄漏路径:
- Vercel、Netlify、Cloudflare Pages 的预览部署会给 preview 域名注入
X-Robots-Tag: noindex,但生产别名配置错了也命中了。 - WAF 或 CDN 规则原本只想覆盖
*.staging.example.com,但 host 模式同时匹配到了你的主域名。 - 源站中间件根据
NODE_ENV !== "production"加上X-Robots-Tag: noindex,结果生产环境没设这个 env,规则照样生效。
修复:定位哪一层注入了 header。一层一层往回找:
# 直连源站(绕过 CDN)
curl -sI --resolve yourdomain.com:443:ORIGIN_IP https://yourdomain.com/path | grep -i x-robots
# 再走 CDN
curl -sI https://yourdomain.com/path | grep -i x-robots
源站干净、CDN 脏 → CDN 规则;两者都脏 → 源站/应用层。
情况 3:PDF、图片或其他非 HTML 资源从搜索消失
怎么发现:
curl -sI https://yourdomain.com/whitepaper.pdf | grep -i x-robots
PDF、图片、其他非 HTML 响应无法承载 <meta> 标签。对它们而言,Google 唯一能读到的 robots 信号就是 X-Robots-Tag。如果托管平台或框架把 X-Robots-Tag: noindex 作为静态资源的默认值,你的 PDF 永远无法被收录。
原因:某些框架(Next.js 的默认 header、S3+CloudFront 配了默认 noindex 策略)会给所有响应、包括静态资源都加 X-Robots-Tag。
修复:把 noindex 规则限定到 HTML 页面或具体路径,而不是全站默认。
情况 4:表现飘忽——有时被收录有时没被
怎么发现:URL 检查显示渲染后的 HTML 带 noindex,但原始响应(“HTTP 响应”那一栏)没有。或者反过来。
原因:JavaScript 在页面加载后修改 meta。本次抓取 Googlebot 执行了 JS 就看到 noindex;没执行就看到原始的 index 值。header 通道始终被读取;meta 通道依赖渲染。
修复:不要用客户端 JS 切换 robots meta。在 SSR HTML 里就把最终值渲染出来,或者用服务端的 X-Robots-Tag。
情况 5:两边都写了 noindex,页面还在被收录
怎么发现:
# 两个信号都在
curl -s https://yourdomain.com/path | grep -i robots # meta 写了 noindex
curl -sI https://yourdomain.com/path | grep -i x-robots # X-Robots-Tag: noindex
# 但是:
curl -s https://yourdomain.com/robots.txt | grep -i path
# Disallow: /path
原因:robots.txt Disallow 把抓取整个挡住了。Google 永远不去取这一页,永远看不到 meta 或 header,仅凭外链信号继续把 URL 留在索引里(就是那个著名的”虽被 robots.txt 屏蔽,但仍被收录”状态)。这是 noindex 失败最常见的形态。
修复:删掉 Disallow 那一行。URL 必须可抓取,Google 才能看到 noindex 并完成移除。
Google 怎么解决冲突
按 Google 文档:
- meta robots 和
X-Robots-Tag都是有效信号。 - 两者同时存在时,按指令逐项取最严格的值。
noindex胜index,nofollow胜follow,noarchive胜 缺省。- 如果
robots.txt屏蔽了 URL,两个信号都读不到——URL 还可能以无摘要的形式留在结果里。
所以 meta 和 header 之间不存在”谁赢”,是合并。实操原则:生产环境里绝不让它们打架。
最短修复路径
按命中率排序:
- 对问题 URL 跑
curl -I→ 60% 的情况下 header 就是凶手。View Source 里的 meta 会让你忽视真正原因。 - 看
robots.txt→ 25% 的情况下是Disallow让 Google 永远看不到你设的信号。 - 逐层排查请求链路 → 源站 header 正确但边缘错了,就是 CDN / WAF / 托管平台的规则。
- 把 robots meta 写到 SSR,别靠 JS → 剩下的边缘情况几乎都是”JS 设了 meta 但 Googlebot 这次没跑 JS”。
一个安全的生产配置
按内容类型分工。下面这套覆盖绝大多数站:
- HTML 页面:robots meta 写进 SSR HTML。HTML 响应不要再加
X-Robots-Tag,除非有特殊理由。 - PDF、图片、下载文件:用
X-Robots-Tagheader(meta 用不了)。 - Staging 域名:
X-Robots-Tag: noindex严格限定在 staging 主机名上。
示例:把 staging 的 noindex 限定到主机名,而不是全局。
# Nginx——只在 staging
server {
server_name staging.yourdomain.com;
add_header X-Robots-Tag "noindex, nofollow" always;
}
server {
server_name yourdomain.com;
# 这里不加 X-Robots-Tag。每页的 noindex 走 meta。
}
预防建议
- 按文件类型记录哪个信号 canonical,写进仓库里的 SEO README。
- CI 加一条检查:对生产 URL 抽样跑
curl -I,意外出现X-Robots-Tag就让构建失败。 - 同一 URL 绝不同时 meta
noindex+robots.txt Disallow——Google 永远看不到 noindex。 - 不要用客户端 JS 切换 robots meta——Googlebot 本次可能跳过 JS。
- 改完 Vercel / Netlify / Cloudflare 设置后,立刻对若干页面跑
curl -I验证 header 没有意外变化。
FAQ
Q:meta 里设了 noindex 但页面还在 Google。先查什么?
A:先跑 curl -sI https://yourdomain.com/path | grep -i x-robots。如果没 header,再看 robots.txt 是不是对这个路径写了 Disallow。这两步能解决约 85% 的情况。都不是的话,几乎都是”Google 还没重抓”——等,或者用 URL 检查里的”申请编入索引”。
Q:同一页能同时用 meta 和 X-Robots-Tag 吗?
A:能,但必须一致。Google 按最严格的指令合并。meta 写 index、header 写 noindex,最终结果是 noindex。HTML 上同时写两个是冗余,选一个就好。
Q:X-Robots-Tag 能用在 HTML 上吗?
A:能,效果和 meta 完全一致。只是不那么常见,因为大多数 CMS 会替你写 meta。X-Robots-Tag 是非 HTML(PDF、图片、ZIP)等无处写 meta 的场景的正确选择。
Q:staging 把 noindex 泄漏到了生产,怎么最快撤销?
A:先把 header 移掉(部署或改 CDN 规则),再去 Search Console:对受影响 URL 做 URL 检查 → “测试实际网址” → 确认 header 已消失 → “申请编入索引”。首页或顶层页通常 24–72 小时就能重新收录。
Q:nosnippet、max-snippet 在 meta 和 header 之间的合并规则一样吗?
A:一样——同样取最严格的值。meta 写 max-snippet:50、header 写 max-snippet:200,最终生效的是 50。