公开页被误打 noindex:定位源头 + 对症修复

模板默认、环境变量泄露或 CDN 头把 `noindex` 留在了本该公开的页面。教你找到真正的源头、移除它,并触发干净的重抓。

Search Console 里一堆 URL 突然进了 Pages → “Why pages aren’t indexed” → “Excluded by ‘noindex’ tag”——全是你想被收录的页。site:yourdomain.com/some-path 没结果。view-source 一看就在那儿:<meta name="robots" content="noindex">。这标签完全按说明书工作:Googlebot 一抓到,URL 就被踢出索引。

最快的修复顺序: 先确认标签来自哪里(HTML meta、X-Robots-Tag 响应头,还是 CMS 字段),针对生产环境去掉它,部署,用 curl 确认 meta 标签和响应头都不再有 noindex,然后对最重要的 10-20 个 URL 用 URL Inspection → Request Indexing。从索引里移除很快;重新进去得按正常爬取节奏走——按 Google 自己的重抓文档,几天到几周。

先排掉一个坑:如果这些 URL 同时被 robots.txt 屏蔽了,Google 根本抓不到它们,连你已经去掉 noindex 这件事都看不到——它们就一直卡着。下面细说。

大多数案例追根都是 starter template 默认值没改、staging 到生产的环境变量漏了,或者 CDN 的响应头规则。本文讲怎么发现并恢复。

noindex 到底藏在哪(判断辅助表)

Google 读 noindex 只有两个物理位置,外加生成它们的配置层。先跑这两条检查,立刻知道自己在哪条分支上:

# 1) 在 HTML 里吗?
curl -s https://yoursite.com/ | grep -i 'name="robots"\|name="googlebot"'
# 2) 在 HTTP 响应头里吗?
curl -sI https://yoursite.com/ | grep -i x-robots-tag
curl 显示的内容来源跳到
HTML 里有 <meta name="robots" content="noindex">模板、CMS 字段或 SSR 条件原因 1、3、4、6
HTML 里有 <meta name="googlebot" content="noindex">模板/CMS 里只针对 Google 的规则同上
响应头里有 X-Robots-Tag: noindexCDN/WAF、托管平台或服务器配置原因 5
两个都没有,但 GSC 还在报报告滞后、robots.txt 屏蔽,或你测错了 URL(缓存/边缘)见”去掉后还卡着”

注意 meta 的 robots 和只针对 Google 的 googlebot 两种都要查——模板可能设的是后者,而很多人只 grep robots

常见原因

按命中率从高到低。

1. 模板脚手架默认带 noindex

很多 Astro / Next starter template 用一个环境标志来切换 robots 标签:

<meta name="robots" content={import.meta.env.PROD ? "index, follow" : "noindex"}>

如果生产构建里 PROD 不是 true(构建命令不对、环境变量缺失、把一个 preview 构建提升成了 prod),每页就吐 noindex。或者开发习惯了”本地都 noindex”,上线时把写死的版本带上去了,没改回来。

怎么判断:

curl -s https://yoursite.com/ | grep -i 'name="robots"'

生产首页吐 noindex 就是这条。然后 grep -rn 'noindex' src/layouts src/components 找到那一行。

2. staging / preview 部署泄露到生产

你给 Vercel/Netlify 的预览配了 noindex(这本身是对的做法)。结果生产域名被错误地指向了一个预览部署,或者生产构建继承了驱动 robots 逻辑的 staging 环境变量。

怎么判断: 在 Vercel 里打开项目 → Deployments,找到当前绑定生产域名的那个部署,确认它是 Production 部署而不是 Preview。再对比它的 Environment Variables 作用域(Production vs Preview)和 staging 的差异。

3. CMS / 框架默认被回溯改动

你改了 CMS 某字段默认(indexable: false),以为只影响新文章,但那些从没显式设过该字段的已有文章,现在也继承了新默认。

怎么判断: 在 GSC 里打开 Excluded by ‘noindex’ tag 看趋势图。某一天的陡然台阶式上升,跟你那天改配置对得上,就是它。

4. 迁移脚本从旧域名复制了 noindex

站点迁移时,脚本把旧页面整个 <head> 复制过来——包括迁移进行中故意设在旧域名上的那个 noindex

怎么判断: 把迁移后页面的 <head> 和目标模板做 diff。旧源码有 noindex,新页面就原封不动继承了。

5. CDN / WAF / 托管平台注入 X-Robots-Tag: noindex

Cloudflare(Transform Rules → Modify Response Header)、某条 WAF 规则,或托管平台级设置,注入了 X-Robots-Tag: noindex HTTP 响应头。HTML 是干净的,view-source 看着没问题——但 Google 对待响应头和 meta 标签一模一样。这是最容易漏掉的原因,因为浏览器里看不到。

怎么判断:

curl -sI https://yoursite.com/ | grep -i x-robots-tag

看到 X-Robots-Tag: noindex(或带路径/爬虫限定的变体,比如 X-Robots-Tag: googlebot: noindex),就是平台在注入。Cloudflare 上查 Rules → Transform Rules → Modify Response Header 和所有 Page Rules;Vercel/Netlify 上查响应头配置(vercel.json / netlify.toml / _headers)。

6. SSR 条件误把公开页 noindex

有 bug 的条件匹配过宽,比如 if (page.category.includes('draft'))'drafts-roundup' 也圈进去了,或者某个状态判断把 undefined 当成”未发布”。公开页被 noindex。

怎么判断: 找 layout/路由里的条件,用边界情况的 slug 和分类去测。把一个已知正常的公开 URL 算出来的 robots 值打日志看看。

最短修复路径

第 1 步:确认范围

在 GSC:Pages → Why pages aren’t indexed → Excluded by ‘noindex’ tag → Export。是几十、几百,还是全部 URL?这能告诉你是单个坏页,还是站点级默认出了问题。

想直接从 sitemap 快速统计全站,HTML 和响应头都要查:

curl -s https://yoursite.com/sitemap.xml \
  | grep -oP '<loc>\K[^<]+' \
  | while read -r url; do
      html=$(curl -s "$url" | grep -i 'name="robots"\|name="googlebot"')
      hdr=$(curl -sI "$url" | grep -i 'x-robots-tag')
      if echo "$html $hdr" | grep -qi 'noindex'; then echo "$url"; fi
    done | tee affected_urls.txt | wc -l

第 2 步:找源头

用上面的判断表,再按这个顺序查:

  1. HTTP 响应头(最容易漏):curl -sI https://yoursite.com/ | grep -i x-robots-tag
  2. 模板grep -rn 'noindex' src/layouts src/components src/pages
  3. 环境变量env | grep -iE 'robots|index|prod',再看托管平台的环境变量面板
  4. CMS 配置:内容类型上的默认可索引/可见设置
  5. CDN:Cloudflare → Transform Rules / Page Rules → 响应头转换

第 3 步:在正确的层面修

  • 模板:index, follow 设成默认;noindex 只对非生产环境生效。生产能触达的地方一律不要写死 noindex
  • 环境变量: 设上正确的生产值(比如 INDEXABLE=true),并确认构建真的读到了它。
  • HTTP 响应头: 从 CDN/平台删掉 X-Robots-Tag 规则,或把它限定到只对 staging 主机名生效。
  • CMS: 把内容类型默认改成 indexable: true;手动重新标记那几个确实该私密的页(感谢页、后台、站内搜索结果)。

第 4 步:部署后用 curl 验证

部署后,对至少 5 个样本 URL 同时检查 meta 标签响应头:

for url in $(head -5 affected_urls.txt); do
  echo "=== $url ==="
  curl -s "$url"  | grep -i 'name="robots"\|name="googlebot"'
  curl -sI "$url" | grep -i x-robots-tag
done

两处都不应有 noindex。如果你用了 CDN,请走 CDN(而不是只走源站)发请求,这样测的才是 Google 实际收到的边缘响应。

第 5 步:对头部 URL 请求重收

对最重要的 10-20 个 URL,在 GSC 打开 URL Inspection,逐个粘贴 URL,点 Request Indexing。按 Google 的说法,每天有配额,而且同一个 URL 反复请求并不会让它抓得更快——每个头部 URL 提交一次就够,别耗在那上面。其余的就重交 sitemap,让自然抓取来处理。

第 6 步:监控恢复

大约 1-4 周内,Excluded by ‘noindex’ tag 数量应该下降,Indexed 应该上升。抓取频繁的站点,头部页常常几天内就回来;长尾要更久。Google 明说请求抓取”并不保证会立刻、甚至根本不保证会被收录”,所以别指望一夜翻转。

4 周后还有 URL 缺失,看:

  • noindex 期间它们返回过 404 吗?Google 可能降级了。
  • 它们是不是确实又薄又重复?低价值页面无论标签怎样,Google 都可能不再收录。

第 7 步:加 CI 校验,防止回归

# 部署后在 CI 里跑,针对线上边缘 URL
robots=$(curl -s https://yoursite.com/ | grep -i 'name="robots"')
echo "$robots" | grep -qi 'noindex' && { echo "FAIL: production emits noindex"; exit 1; }
curl -sI https://yoursite.com/ | grep -qi 'x-robots-tag: *noindex' && { echo "FAIL: X-Robots-Tag noindex header"; exit 1; }
echo "OK: no noindex in HTML or headers"

每次部署都对生产主机名跑一遍。HTML 和响应头都要查——这一步大多数团队都会忘掉响应头那半。

去掉后还卡着?检查 robots.txt

页面恢复不了最常见的原因:你去掉了 noindex,但同一个 URL 还在 robots.txt 里被 disallow。Google 抓不到被屏蔽的页,就永远看不到 noindex 已经没了——URL 一直被排除。Google 自己的屏蔽收录文档说得很直白:“If the page is blocked by a robots.txt file or the crawler can’t access the page, the crawler will never see the noindex rule.”

修法:确保受影响路径在 robots.txt 里是允许抓取的,留足时间让 Google 重抓并读到改动。用 URL Inspection 工具验证——它会显示线上 URL 的 “Crawl allowed?” 以及检测到的索引规则。

其他”去掉了却还被排除”的原因:

  • 你测的是源站,Google 读的是边缘。 走 CDN/生产主机名重测,别用绕过 URL。
  • 报告只是滞后。 GSC 反映的是上次抓取;URL Inspection 里的实时测试才是准的。
  • 还有第二个源头在注入。 一个页面可能 HTML 干净,却仍从 CDN 带着 X-Robots-Tag: noindex(或反过来)。永远两处都查。

预防建议

  • index, follow 设为生产默认。只对 staging opt-innoindex,用环境感知逻辑。
  • staging 的 noindex 用平台/主机级 X-Robots-Tag(环境变量驱动的响应头),不写在源代码里——这样它永远不会被带到生产。
  • 每次部署都跑第 7 步的 CI 校验(HTML 响应头都查)。
  • 每月看一次 Pages → Excluded by ‘noindex’ tag 有没有意外飙升;某一天的台阶式上升几乎总能对应上一次配置改动。

FAQ

  • 去掉标签后 Google 会自动重收吗? 会,下次抓取时。URL Inspection 的 Request Indexing 能加速最重要的 URL,其余按正常爬取节奏恢复(几天到几周)。
  • 打了 noindex 多快掉出索引,去掉后多快回来? 掉出很快——常在下次抓取后的几天内,抓取频繁的站点有时约 72 小时。回来更慢,因为 Google 会降级它之前丢弃过的 URL。
  • 我去掉了 noindex 但页面还被排除——为什么? 多半是该 URL 同时被 robots.txt 屏蔽,Google 抓不到就看不到改动。放开路径后重新 inspect。再确认没有残留的 X-Robots-Tag 响应头。
  • 反复请求重收会更快吗? 不会。Google 说同一 URL 重复请求不会抓得更快,而且每天有配额。每个头部 URL 提交一次就好。
  • 能只让 preview / staging 部署 noindex 吗? 能——用环境感知逻辑,或限定到 staging 主机名的主机级 X-Robots-Tag 响应头来设,绝不要写死在共享源码里。
  • meta robots noindexX-Robots-Tag: noindex 有区别吗? 没有——Google 同等对待。响应头版只是加在 HTTP 响应上(对 PDF 这类非 HTML 文件很方便),所以找源头时两处都得查。

相关阅读

标签: #SEO #排查 #排查 #结构化数据 #noindex