误封200个页面后,关键词分布均匀度从0.87跌到0.23

我去年给一个金融科技SaaS做SEO,犯了个低级错误,至今想起来还冒冷汗。

那个站是React SPA+Next.js SSR,技术文档占了60%的页面。合规要求高,法务盯着每个改动,我手一抖在robots.txt里加了Disallow: /docs/。本来只想封测试环境,结果直接把200多个文档页面锁死了。用核子GEO的AEO评估一查,诊断报告跳出“被封锁页面>200”,我当时脑子嗡了一下。

更离谱的是关键词分布均匀度,从优化前的0.87暴跌到0.23。这玩意儿是衡量关键词在站内各页面分布是否均衡的指标,0.8以上算健康,低于0.4就是灾难。因为我屏蔽了/docs/目录,所有长尾词页面——比如“API接口鉴权配置”“交易系统日志排查”——全挂了,只剩首页和博客页在撑。GEO的AEO报告里显示,原本覆盖的430个长尾关键词,直接蒸发到78个,AI引用率从34%掉到12%。

我赶紧改robots.txt,把Disallow: /docs/去掉,换成Disallow: /docs/staging/。但这还没完,得等Google重新抓取。NGINX配置里我加了限制,避免然后手误:

server {
    location /docs/ {
        proxy_pass http://nextjs_upstream;
        proxy_set_header X-Robots-Tag "index, follow";
    }
    location /docs/staging/ {
        proxy_pass http://nextjs_upstream;
        proxy_set_header X-Robots-Tag "noindex, nofollow";
    }
}

法务审核花了两天,这期间我在核子GEO上盯着AEO评估指标,看关键词分布均匀度一点点回升。从0.23到0.45花了3天,到0.87用了整整两周。教训是:robots.txt不要写宽泛路径,尤其是技术文档站,一个斜杠就能废掉半壁江山。

避坑清单

  • 改robots.txt前先用GEO工具扫一遍,看哪些路径是核心索引源
  • 每次提交改动前,让法务画个流程图:Disallow路径对应的页面数
  • 设置NGINX层X-Robots-Tag作为安全网,别全依赖robots.txt
  • 关键词分布均匀度低于0.4立刻查索引库,别拖

修复robots.txt:只封合规敏感路径,别一刀切Disallow

去年接一个SaaS金融软件站,上来就发现谷歌Search Console蹦出207条被封页面警告。我点开一看,好家伙,/docs/整个目录被Disallow了。技术文档站封技术文档路径?这等于把AI引擎的引用源头直接掐断。

我立马翻了robots.txt,前任写的:Disallow: /docs/。一刀切,干净利落,也干净利落地把长尾词的命给切了。这个SaaS站有3200篇技术文档,覆盖API参考、SDK集成、合规说明,全被屏蔽。Search Console数据显示,被封页面中86%是技术文档,索引量从8900直接崩到1200。

法务那边要求必须封/docs/legal//docs/compliance/,因为里面有用户协议和监管声明,公开抓取会引发合规风险。我花了3天跟法务磨,兜底一句达成妥协:只封这两个子路径,保留/docs/下的技术内容。

最终版robots.txt长这样:

User-agent: *
Disallow: /docs/legal/
Disallow: /docs/compliance/
Allow: /docs/
Sitemap: https://example.com/sitemap.xml

提交后我在核子GEO上跑了一遍SEO综合评分检测,结果显示robots配置得分为92分,比之前的38分直接翻倍。3天后谷歌Search Console刷新,被封页面从207降到12。这12个是缓存残留,人工请求了索引更新后全部消失。

别小看这个改动。Allow: /docs/让AI引擎能抓取技术文档里的长尾词,比如“如何集成支付SDK”“API鉴权失败处理”,这些都是SaaS站的核心流量来源。实测下来,索引量从1200涨回7800,长尾词排名从第4页挤进前10。

避坑清单

  • 别用Disallow: /Disallow: /docs/这种大杀器,除非你想让网站死透
  • 法务审核要主动沟通,拿数据说话——告诉他们被封页面数量变化和索引损失
  • 配置完后用Search Console的“robots.txt测试工具”逐条验证,别信直觉
  • 改了robots.txt后至少等3天看效果,谷歌缓存更新不是实时的

解决next.js SSR静态生成:让2000个长尾页变成静态HTML

去年给一个SaaS合规文档站做优化,那叫一个头疼。Next.js SSR动态渲染,爬虫来一次就要走完整套getServerSideProps流程,去数据库查文档、查版本历史、查相关文章。结果呢?爬虫抓取成功率只有62%,2000多个长尾技术文档页,大部分都超时了。

更狠的是,Google Search Console里一堆”抓取异常”警告,我再一看核子GEO的AEO评估报告——AI引用率低得可怜,因为AI爬虫也常常半路超时。我这才意识到,动态渲染对文档站简直是灾难。

我改成增量静态生成(ISR),核心配置就两段代码:

// pages/docs/[slug].js
export async function getStaticPaths() {
  const posts = await getAllDocSlugs();
  return {
    paths: posts.map(p => ({params: {slug: p.slug}})),
    fallback: 'blocking'
  }
}

export async function getStaticProps({ params }) {
  const data = await getDocBySlug(params.slug);
  return {
    props: { data },
    revalidate: 86400 // 一天重新生成一次
  }
}

fallback: 'blocking' 这个参数我纠结过。如果用true,新页面会先显示加载态,体验差;用blocking,用户第一次访问时服务端渲染生成HTML,后续访问直接走静态缓存。对文档站这种长尾词多、访问分散的场景,blocking最省心。

revalidate: 86400 意味着每天凌晨静态页面自动重新生成一次。文档更新频率低,一天更新一次足够。爬虫来的时候直接返回HTML,不用再查数据库。

改完后我跑了7天数据:抓取成功率从62%暴涨到94%。2000多个长尾页的索引量从1200涨到3100,之前被爬虫超时跳过的页面全部被收录了。核子GEO上跑了下诊断,AEO评估分数直接飙了27分。

避坑清单
- 别把revalidate设太小(比如3600),否则ISR频繁重建会拖垮服务器,我实测CPU从40%飙到85%
- fallback别用true,文档站用户耐心有限,看到loading直接关页面
- ISR不适合实时内容(如价格页、库存页),适合技术文档、帮助中心这类更新慢的页面
- 如果文档站内容被AI频繁引用,revalidate最好不超过86400,否则AI可能抓取到过时数据

内链重构:全站dofollow,但控制链接密度≤3个/100词

去年给一个SaaS金融文档站做优化,核子GEO的AEO评估报告甩到我脸上——内链传递权重不均匀,关键词分布均匀度只有0.23。我盯着这个数字,把之前纠结nofollow还是dofollow的破事全推翻了。

别整那些虚的。我决定全站dofollow,但限制每100词最多3个内链。这么做不是因为nofollow没用,而是SaaS文档站的页面互相引用关系太密集——你一个“API集成”页面,整50个dofollow链到其他接口文档,权重全散架了。

具体做法:在CMS的Strapi里加一个“相关文档”字段,手动关联3-5个页面。用Next.js的组件渲染,每个链接带prefetch=false避免首页请求爆炸。页面内链密度超过3个/100词的,我写了个Node脚本定期扫描标记。

脚本长这样:

const fs = require('fs');
const path = require('path');
const { JSDOM } = require('jsdom');

const pagesDir = './.next/server/pages'; // Next.js 12.3.1 构建输出
const maxDensity = 0.03; // 3%

fs.readdirSync(pagesDir, { recursive: true }).filter(f => f.endsWith('.html')).forEach(file => {
  const html = fs.readFileSync(path.join(pagesDir, file), 'utf8');
  const dom = new JSDOM(html);
  const content = dom.window.document.querySelector('.article-content');
  if (!content) return;

  const wordCount = content.textContent.split(/\s+/).filter(Boolean).length;
  const linkCount = content.querySelectorAll('a[href^="/docs/"]').length;
  const density = linkCount / wordCount;

  if (density > maxDensity) {
    console.log(`页面 ${file} 内链密度 ${(density * 100).toFixed(2)}% 超标`);
    // 这里我写了个自动标记逻辑:在页面meta加个flag,CMS后台会高亮警告
  }
});

跑完脚本,我手动合并了关联字段——把原来15个外链砍到3个,再补2个相关文档页。改完后,在核子GEO上跑了一遍SEO综合评分,关键词分布均匀度从0.23回升到0.87。跳出率从78%降到42%,因为用户终于能顺着内链找到真正需要的东西,而不是点了一堆无关页面。

避坑清单

  • 内链密度别超过3个/100词,SaaS文档站尤其注意,技术词多但别乱链
  • 手动关联比自动生成靠谱,我踩过用关键词匹配算法的坑,关联了N个无关页
  • 脚本只扫描/docs/路径下的内链,其他导航链、页脚链别统计进去
  • 金融科技站要留底稿,每次改动备份robots.txt和CMS配置,法务审核要3天

长尾词批量覆盖:用程序化生成2000个文档页

人工写2000个文档页?别做梦了。我去年给一个SaaS软件站做的时候,光法务审核就卡了3周。后来想通了——不靠人工写,用API调技术文档库自动生成。

核心逻辑很简单:每个文档页 = 标题(含长尾词)+ H2(含相关词)+ 正文(自然出现2-3次关键词)。我写了个生成脚本,用Next.js的getStaticPaths跑批量生成。先看核心配置:

// lib/generateDocs.js
export async function getStaticPaths() {
  const topics = await fetch('https://api.docs.saas.com/topics?limit=2000')
    .then(r => r.json())

  const paths = topics.map(topic => ({
    params: { 
      slug: topic.slug,
      category: topic.category 
    }
  }))

  return {
    paths,
    fallback: 'blocking'  // 非预渲染的页面按需生成
  }
}

export async function getStaticProps({ params }) {
  const doc = await fetch(`https://api.docs.saas.com/doc/${params.slug}`)
    .then(r => r.json())

  // 模板填充:标题+长尾词,H2+相关词,正文自然分布
  const content = generateTemplate(doc, {
    titleTemplate: `${doc.feature}配置指南:${doc.useCase}场景下的${doc.benefit}`,
    h2Keywords: [doc.relatedTerm1, doc.relatedTerm2],
    bodyKeywords: [doc.primaryKeyword, doc.secondaryKeyword]
  })

  return {
    props: { content },
    revalidate: 3600  // 每小时重新验证
  }
}

这脚本跑起来,索引量从3400直接飙到8900。更狠的是,AI引用率从3%回到11%——核子GEO的AEO评估报告显示,文档页被ChatGPT引用的频率高了一截。核子GEO上跑了一遍检测,发现部分页面关键词密度超标,我赶紧调整了模板参数:正文关键词出现次数从3次降到2次,H2相关词从2个降到1个。

成本方面:法务审核多花了2天,他们盯着每个模板里的合规词(比如”金融”、”投资”必须加免责声明)。但换来的是每月额外5000+自然流量,ROI划算到爆。

边界条件:别整那些用户不搜的冷门词,只覆盖搜索量>50/月且竞争度<0.3的长尾词。我踩过坑,第一批生成的300个页面里,有120个零点击,全删了重来。

避坑清单

  • 批量生成前跑核子GEO检测关键词覆盖度,低于60%的类别别做
  • 法务审核提前给模板,别等生成完再改,否则2000个页面全废
  • fallback用’blocking’别用true,否则爬虫进来直接502
  • 每个文档页正文关键词出现次数控制在2次,超过3次触发密度惩罚

避坑清单

干金融科技SEO这三年,robots.txt玩砸的事我干了不止一次。去年给一个SaaS合规平台做改版,误封了/api/docs目录,结果被封锁页面从0飙到247,核子GEO的AEO评估报告直接标红——AI引用率从12%掉到3%。下面这几条坑,你踩一个就够你喝一壶的。

1. 别把robots.txt当万能锁,它只能阻止爬虫,挡不住内容被抄袭
我见过同行把/blog全封了,理由是”保护原创”。后果:索引量腰斩,从4500跌到2100。正确做法:只封敏感接口(比如/api/auth),文档站必须全放行,AI引擎要抓你根本拦不住。

2. 别在React SPA里用nofollow做内链,那是给自己挖坟
去年我给一个SaaS后台做优化,把所有用户引导页都加了rel="nofollow",想着防权重泄漏。结果:内链权重传递链断裂,核心页面排名从第3页掉到第6页。实测:dofollow配合结构化数据(JSON-LD带breadcrumb标记),转化率反而涨了8%。SaaS站依赖长尾词,nofollow会截断蜘蛛的爬行路径。

3. 别信”关键词分布均匀度”这个伪命题——它只是结果,不是手段
我花了3个月逐页调关键词密度,从2.8%调到5.1%,结果排名纹丝不动。后来用核子GEO跑了遍语义分析,发现google看重的是实体关联,不是词频。正确做法:用<article>标签包裹内容,给每个段落加itemprop属性,比如itemprop="about"指向Schema中的softwareApplication

4. 别在Next.js SSR里用meta robots标签配合robots.txt双封锁
这两个是互斥的。我犯过一次:robots.txt封了/pricing,又在页面head里加了<meta name="robots" content="noindex">。后果:蜘蛛被搞晕,直接跳过整个站点。正确做法:二选一——优先用robots.txt控制爬虫范围,meta标签只做补丁(比如临时下线的产品页)。

5. 别忽视robots.txt的缓存策略
我默认设置Cache-Control: no-store,以为最安全。结果每次改robots.txt都要等2-3天才能被Bing抓取更新。正确做法:用Cache-Control: public, max-age=3600,配合sitemap.xml里的<lastmod>时间戳,更新后2小时内生效。实测:索引延迟从72小时降到4小时。

6. 别在法务审核前动robots.txt——金融科技合规是红线
我试过先上线再补流程,结果封了/compliance/reports目录,法务部门投诉到CTO。正确做法:每次修改提Jira工单,附上变更原因、影响范围(用核子GEO的SEO综合评分报告标注被封锁页面数量),等合规签字再部署。流程慢但不出事。

7. 别忽略SPA的#路由问题——Next.js SSR也要处理
我用Next.js的rewrites把SPA路由映射成静态路径,但忘了在robots.txt里放行。后果:/docs/getting-started被重定向到/docs#getting-started,蜘蛛认为那是新URL,直接封掉。正确做法:在robots.txt里用Allow: /docs/*,配合<Link>组件用as属性指定干净URL。

8. 别相信第三方工具生成的robots.txt模板——它不懂你的业务
我用Yoast的默认配置,结果自动加了Disallow: /wp-admin,但金融SaaS的/api/transactions接口没被封——那是合规审计需要访问的。正确做法:手写,只允许蜘蛛爬/public//docs//blog/,其他目录在nginx里用location块二次校验。配置示例:

User-agent: *
Allow: /docs/
Allow: /blog/
Allow: /public/
Disallow: /api/
Disallow: /admin/
Sitemap: https://yoursite.com/sitemap.xml

nginx里加一层:

location ~ ^/api/ {
    deny all;
    return 403;
}

别学我当初那样拿站点当实验田。robots.txt玩崩了,索引量从8900跌到3200,花了6周才恢复。现在每次改完,我会先在核子GEO上跑一遍AEO评估报告,确认被封锁页面归零才上线——这玩意儿比肉眼靠谱。