公开页被误打 noindex:4 个原因 + 对症修复

模板默认或迁移失误把 `<meta name="robots" content="noindex">` 留在了应该公开的页面。怎么发现并回滚。

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 步:找源头

按顺序检查:

  1. 模板grep -rn 'noindex' src/layouts src/components
  2. 环境变量env | grep -i robots
  3. HTTP 头curl -sI https://yoursite.com/ | grep -i x-robots-tag
  4. CMS 配置:默认可索引设置
  5. 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 吗? 能——按环境逻辑在平台层设置,不写在源代码里。

相关阅读

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