Search Console 突然显示成百上千的 URL 进了 “Excluded by ‘noindex’ tag”——本该公开收录的页。site:yourdomain.com/url-path 没结果。view-source 一看:<meta name="robots" content="noindex">。这个标签完全按说明书工作:Google 看到就立刻把 URL 从索引里挑出去。坏消息:移除是瞬间的。好消息是:去掉标签 + 触发重抓,恢复按正常爬取节奏走(几天到几周)。
大多数案例追根都是 starter template 默认值没改,或 staging 到生产的环境变量漏了。本文讲怎么发现并恢复。
常见原因
按命中率从高到低。
1. 模板脚手架默认带 noindex
很多 Astro / Next starter template 这样写:
<meta name="robots" content={import.meta.env.PROD ? "index,follow" : "noindex"}>
PROD 在你构建里没正确设上,每页就吐 noindex。或者开发习惯了”本地都 noindex”,上线时忘了改。
怎么判断:
curl -s https://yoursite.com/ | grep -i 'meta name="robots"'
生产首页吐 noindex 就是这条。
2. staging / preview 部署泄露到生产
你给 Vercel 预览配了 noindex。然后不小心把生产域名指向了一个预览,或者生产构建继承了 staging 的环境变量。
怎么判断:Vercel / Netlify → 看当前服务生产域名的是哪个 deployment。对比它的环境变量跟 staging。
3. CMS / 框架默认被回溯改动
你改了 CMS 里某个字段默认(indexable: false),以为只影响新文章,但已有文章也继承了新默认。
怎么判断:Search Console → Excluded by noindex。按日期聚类——某一天突然飙升,跟你那天改配置对得上就是这条。
4. 迁移脚本从旧域名复制了 noindex
迁移时脚本把旧页面整个 <head> 复制过来,包括旧域名上故意设的 noindex。
怎么判断:看迁移源的 <head> 内容。旧页面是有 noindex 的(因为迁移中),新页面继承了它。
5. CDN / WAF 规则注入 X-Robots-Tag: noindex
Cloudflare 或 WAF 规则本来给 staging 用,注入了 X-Robots-Tag: noindex HTTP 头。HTML 看不到这个标签,view-source 看着没问题——但 Google 看得到头。
怎么判断:
curl -sI https://yoursite.com/ | grep -i x-robots-tag
看到 X-Robots-Tag: noindex 就是 CDN 在注入。
6. SSR 条件误把公开页 noindex
有 bug 的条件:if (page.category === 'draft') 匹配范围超出预期(比如 'drafts' 子串匹配)。公开页被 noindex。
怎么判断:找 layout 里的条件。用边界情况的文章 slug / 分类测。
最短修复路径
第 1 步:确认范围
Search Console → Pages → “Excluded by ‘noindex’ tag” → 导出列表。数量:几十?几百?全部?
curl -s https://yoursite.com/sitemap.xml | grep -oP '<loc>\K[^<]+' | while read url; do
if curl -s "$url" | grep -q 'noindex'; then
echo "$url"
fi
done | wc -l
第 2 步:找源头
按顺序检查:
- 模板:
grep -rn 'noindex' src/layouts src/components - 环境变量:
env | grep -i robots - HTTP 头:
curl -sI https://yoursite.com/ | grep -i x-robots-tag - CMS 配置:默认可索引设置
- CDN:Cloudflare → Rules → 看响应头转换
第 3 步:修
找到后:
- 模板:生产硬编码
<meta name="robots" content="index, follow"> - 环境变量:生产设
INDEXABLE=true或修条件 - HTTP 头:去掉 CDN 配置里的
X-Robots-Tag - CMS:默认改
indexable: true,手动标已存在的非公开页
第 4 步:部署后 view-source 验证
至少手动检查 5 个样本 URL:
for url in $(head -5 affected_urls.txt); do
echo "=== $url ==="
curl -s "$url" | grep -i 'meta name="robots"'
curl -sI "$url" | grep -i x-robots-tag
done
任何地方都不应有 noindex。
第 5 步:对头部 URL 请求重收
对最重要的 10-20 个 URL(被 noindex 之前流量 / 业务价值最高的),Search Console → URL Inspection → “Request Indexing”。触发快速重抓。
更大量的就重交 sitemap,等自然抓取。
第 6 步:监控恢复
1-4 周内,Search Console “Excluded by noindex” 应该下降,“Indexed URLs” 应该上升。
4 周后还有 URL 缺失,看:
- noindex 期间它们 404 过吗?Google 可能降级了。
- 它们有独特价值吗?还是本来就薄?Google 不一定重新收薄页。
第 7 步:加 CI 校验
# 部署后 CI 跑
curl -s https://yoursite.com/ | grep -q 'meta name="robots" content="index'
[ $? -eq 0 ] || { echo "Production has noindex!"; exit 1; }
每次部署都跑,防止回归。
哪些情况可能不是你操作错了
恢复时间取决于 Google 抓取频率。noindex 留得越久,恢复越慢(Google 降级了它移除的 URL)。别期待一夜恢复,几周是常态。
容易误判的情况
以为去掉 noindex 就够——还得让页面被重抓。没有新抓取,Google 索引就保持”已移除”,直到下次访问。
预防建议
- 永远不要把
noindex设为生产默认。默认index, follow,用环境感知逻辑让 staging opt-in 到 noindex。 - CI 校验:部署后至少抽 5 个生产 URL 断言吐
index, follow。 - 各环境 CI 都抽样校验
<meta name="robots">。 - staging 用平台级
X-Robots-Tag: noindex(Vercel/Netlify 环境变量驱动的响应头),不写在源代码里。 - 每月看一次 Search Console → Pages 有没有意外的 “Excluded by noindex” 飙升。
FAQ
- Google 会自动重收吗? 会——下次抓取后。URL Inspection 的 “Request Indexing” 能加速最重要的 URL。
- 能只让 preview 部署 noindex 吗? 能——按环境逻辑在平台层设置,不写在源代码里。