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: noindex | CDN/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 步:找源头
用上面的判断表,再按这个顺序查:
- HTTP 响应头(最容易漏):
curl -sI https://yoursite.com/ | grep -i x-robots-tag - 模板:
grep -rn 'noindex' src/layouts src/components src/pages - 环境变量:
env | grep -iE 'robots|index|prod',再看托管平台的环境变量面板 - CMS 配置:内容类型上的默认可索引/可见设置
- 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-in 到noindex,用环境感知逻辑。 - 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 noindex和X-Robots-Tag: noindex有区别吗? 没有——Google 同等对待。响应头版只是加在 HTTP 响应上(对 PDF 这类非 HTML 文件很方便),所以找源头时两处都得查。