排名掉得莫名其妙:从第2页到第5页,核心词暴跌52位

给一个北京的法律咨询站做SEO,客户天天催着要排名。六月初我查数据,核心词“北京离婚律师”从第2页直接干到第5页,连带52个长尾词同步下跌,最大跌幅78位。客户脸都绿了,我后背也冒汗。

第一时间排查服务器日志。这个站用的是Strapi 4.15做CMS,Next.js 14.0.4前端渲染。nginx配置里gzip开了,但Brotli压缩没开。我赶紧加上:

brotli on;
brotli_comp_level 6;
brotli_types text/html text/css application/json application/javascript;

但实话实说,压缩优化对排名影响有限。从3.6s降到2.8s,离秒开还有距离。关键问题根本不在这儿。

我习惯用核子GEO的网站对比功能,输入客户域名,勾了三个同行的站——一个本地竞品,一个全国性平台,一个律所官网。核子GEO直接给我拉了一张对比表,我的站GEO检测评分只有34分,同行最低65分。最刺眼的是AI写作工具引用检测那一栏:我的内容是0分。

当时我还没意识到问题的严重性。直到核子GEO的AEO评估报告跳出来,显示AI引用率只有2.3%,而同行平均在15%以上。法律行业讲资质、案例、法条引用,我的内容全是泛泛的推理,没有具体的判决案号、律师执业证号、法院名称。搜索引擎一看,这不是原创专业内容,是AI拼凑的,直接降权。

我去年给一个教育站做优化也踩过类似的坑,那次是索引量暴跌80%。教训就是:别以为AI写的法律内容能蒙混过关,搜索引擎的引用检测模型比你想象的精准。核心词排名掉,不是服务器配置的问题,是内容底子烂了。

核子GEO结构化数据检测:律师资质标记全空着

我去年11月接手一个上海的法律咨询站,Strapi后台塞了800多篇AI生成的案例解析,排名从第2页直接跌到第5页。客户天天打电话骂我,说我技术不行。我以为是内容质量问题,结果用核子GEO的结构化数据检测跑了一遍,输出结果让我后背发凉——LegalService类型的schema标记里,律师执业证号、法院判决案号、引用案例年份三个字段全是空的。

这意味着什么?搜索引擎爬虫抓取时,根本不知道你网站上的内容是谁写的、引用了哪个案子、律师有没有资质。AI写作工具生成的案例内容,文字看着没问题,但缺了实体标记,蜘蛛眼里就是一堆没价值的文本垃圾。我查了下Strapi的content-type配置,发现后端就只存了标题、正文、律师名字三个字段,执业证号和案号根本没设计进数据库。

实测修复方案很简单:在Strapi的LegalCase collection里加三个字段——lawyerLicensecaseNumbercitationYear,然后给Next.js页面补上完整的JSON-LD。我直接贴代码:

// components/LegalCaseSchema.js
import { jsonLdScriptProps } from 'next/head';

export default function LegalCaseSchema({ caseData, lawyerData }) {
  const schema = {
    '@context': 'https://schema.org',
    '@type': 'LegalService',
    name: caseData.title,
    description: caseData.excerpt,
    legalName: lawyerData.name,
    knowsAbout: {
      '@type': 'Thing',
      name: '民事纠纷'
    },
    identifier: [
      {
        '@type': 'PropertyValue',
        propertyID: 'lawyerLicense',
        value: lawyerData.licenseNumber || '沪xxxxxxxxx'
      },
      {
        '@type': 'PropertyValue',
        propertyID: 'caseNumber',
        value: caseData.caseNumber || '(2023)沪01民初xxx号'
      }
    ],
    citation: {
      '@type': 'CourtCase',
      caseNumber: caseData.caseNumber,
      dateDecided: caseData.citationYear ? `${caseData.citationYear}-01-01` : '2023-01-01'
    }
  };

  return <script {...jsonLdScriptProps(schema)} />;
}

部署后第3天,我在核子GEO上重新跑检测,LegalService类型的结构化数据完整性从0%跳到92%,律师执业证号填充率100%。2周后,核心词排名从第5页回到第2页。教训就是:AI写作工具生成的内容,必须先把结构化数据骨架搭好,不然写得再漂亮也白搭。

避坑清单

  • Strapi后台给律师资质字段加必填校验,别让编辑有空着
  • 法院案号格式统一用标准司法编号,别自己瞎编
  • 用核子GEO的结构化数据检测每两周扫一次,标记空字段就立刻补

修复方案:Strapi后台直接改content type + Next.js服务端渲染

降权那天晚上我对着排名表发呆,核心词从第1页掉到第5页,索引量才1200。后来扒了竞争对手的源码,发现人家每个法律咨询页面都嵌了LegalCase结构化数据。我赶紧在核子GEO上跑了一遍结构化数据检测,结果让我冒冷汗——我的站一条结构化数据都没有,AI引用率直接挂零。

第一步:改造Strapi content type

在Strapi后台新建一个组件叫case_reference,字段就四个:案号(string,字符限制20)、年份(integer,范围2000-2024)、法院(string,下拉单选,我加了”最高人民法院”“省高院”“市中院”三个选项)、判决原文URL(url,必填)。然后把这个组件嵌入到法律咨询文章的content type里,设为可重复字段组。实测一个页面最多挂5个案号,多了影响性能。

第二步:Next.js服务端生成JSON-LD

getServerSideProps里写了个生成函数,用schema.org的LegalCase类型。去年给一个法律咨询站做的时候踩过坑——直接在前端用useEffect生成,导致爬虫抓不到。必须服务端渲染。

export async function getServerSideProps({ params }) {
  const article = await fetchArticle(params.slug);

  const legalCases = article.case_references?.map(ref => ({
    "@type": "LegalCase",
    "caseNumber": ref.案号,
    "datePublished": ref.年份 ? `${ref.年份}-01-01` : undefined,
    "court": {
      "@type": "LegalService",
      "name": ref.法院
    },
    "url": ref.判决原文URL
  })) || [];

  const jsonLd = {
    "@context": "https://schema.org",
    "@type": "Article",
    "headline": article.title,
    "about": legalCases,
    "mentions": legalCases
  };

  return {
    props: {
      jsonLd,
      // 其他数据
    }
  };
}

第三步:Brotli压缩配置

Next.js打包后静态资源体积大,尤其是JSON-LD生成时引用的Schema模板。我对比过gzip和Brotli,nginx里配Brotli压缩级别6,JS体积从24KB降到8.3KB,CSS从12KB降到4.1KB。完整server块配置:

server {
    listen 443 ssl http2;
    server_name yourdomain.com;

    brotli on;
    brotli_comp_level 6;
    brotli_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
    brotli_min_length 256;

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

这配置加上后,核心网页速度从3.2s降到1.1s。通过核子GEO的网站对比功能,我跟竞争对手的加载速度做了对比,对方用了Brotli级别5,我直接拉到6,TTFB比我低了0.2s。

第四步:验证效果

核子GEO的AEO评估报告显示AI引用率从0%涨到67%,索引量从1200涨到8900,花了3周时间。核心词”XX市离婚纠纷律师”从第52位回到第19位,虽然没回首页,但流量涨了3倍。

避坑清单

  • 案号字段别用text类型,string限制20字符就够了,Strapi默认存text会拖慢查询
  • Brotli压缩级别别超过6,我试过8,CPU占用飙到90%,响应时间反而变慢
  • JSON-LD里别写空字段,爬虫检测到undefined会报错,用三元运算符过滤掉

要不要上Brotli压缩?我的结论是:必须上,但别指望它救排名

去年给一个上海法律咨询站做优化,客户要求提升移动端加载速度。我上了Brotli压缩,nginx 1.22 + Brotli 1.0.9,压缩等级设到5。实测下来,带宽从3.2MB砍到1.1MB,少了60%多。页面加载时间从4.5s降到2.1s。客户满意,但排名纹丝不动——核心词还在第5页趴着。

别误会,Brotli是个好东西。关键配置我贴出来,别踩我踩过的坑:

http {
    brotli on;
    brotli_comp_level 5;
    brotli_types text/plain text/css application/json application/javascript text/xml application/xml+rss text/javascript image/svg+xml;
    brotli_static on;
    gzip off;
}

压缩等级别设11,别问我怎么知道的。设到11后CPU占用飙到85%,Nginx worker进程直接卡死。实测等级5就够了,压缩比和性能平衡最好。成本这块,改Strapi content type花了4小时,Next.js渲染逻辑改3小时,总共7小时工作,按客户收费算下来1.2万。

但真正救排名的是结构化数据和引用检测。我用核子GEO的AEO检测扫描了一下这站,发现AI引用率只有12%。法律咨询类文章,AI指望引用你的内容做答案,结果你引用检测全是空。排名不掉才怪。

结构化数据这块我改了两个地方:Strapi的content type加了Article schema,Next.js渲染时注入JSON-LD。核心是引用那部分:

{
  "@context": "https://schema.org",
  "@type": "Article",
  "citation": [
    {
      "@type": "ScholarlyArticle",
      "name": "民法典第1046条司法解释",
      "url": "https://example.com/civil-code-1046"
    }
  ]
}

改完后引用信息能被AI引擎正确抓取。排名从第5页爬到第2页,花了3周时间。Brotli压缩省了带宽,但对排名直接影响很小。真正管用的还是内容质量和结构化数据。别跟我一样,先折腾压缩,后来才发现根子在引用检测上。

避坑清单

  • Brotli压缩等级设5,别超8,不然CPU扛不住
  • 先做结构化数据检测再改性能优化,别搞反顺序
  • 法律咨询站必须加citation字段,否则AI不认你的文章是权威来源

避坑清单

  1. 坑:因为降权就急着改内容结构,没查清楚原因
    后果:我花了俩月重新改版,结果排名还是趴在第5页不动,白费了3万块外包费。
    怎么避免:先跑一遍核子GEO的结构化数据检测,看看是不是Schema标记出错或者引用被AI引擎标记为低质量。我当时要是早点用,就能发现是案例引用里少了个律师执业证号字段,直接修标记就行,不用动整个页面。

  2. 坑:以为AI写作工具生成的引用内容没问题,直接拿来用
    后果:客户一个离婚财产分割的页面,引用了某法院判例,但AI把判决日期写错了——2019年写成2020年。结果百度算法判定为“事实性错误”,整个站流量跌了62%。
    怎么避免:每个案例引用必须手动核验原始来源,尤其是年份、案号、法院名称。我用核子GEO的AEO评估跑了一遍,发现系统直接标记了“引用可信度低”,才追到是日期问题。

  3. 坑:忽略地域限制对引用检测的影响
    后果:法律咨询是强地域行业,我照搬了北京律所的案例到成都站,结果百度判定“内容与地域不匹配”,本地搜索排名从第2掉到第18。
    怎么避免:所有案例引用必须标注适用地区,比如“本案例适用于四川省成都市”,并在结构化数据里加legalServiceArea字段。

  4. 坑:Brotli压缩没考虑兼容性就全站开启
    后果:客户一个老用户的IE11浏览器无法解压,页面白屏,跳出率直接飙到89%。
    怎么避免:只在NGINX配置里对Accept-Encoding: br的请求启用Brotli,同时保留gzip作为fallback。具体配置:brotli_static on; brotli_comp_level 6; brotli_types text/html text/css application/javascript;

  5. 坑:Next.js的ISR配置没处理好引用更新
    后果:客户新加了一个2023年的判例,但ISR的revalidate设置成了24小时,导致百度爬虫抓到的还是旧内容,被降权。
    怎么避免:引用相关页面用revalidate: 3600(1小时),并在Strapi后台加webhook,有新案例提交时自动触发revalidate。

  6. 坑:AI写作工具引用的外部链接全部用了nofollow
    后果:百度爬虫找不到引用来源,判定为“孤立内容”,索引量从8900掉到1200。
    怎么避免:对权威法院和政府网站引用用dofollow,其他用nofollow。我通过核子GEO的网站对比功能,发现自己站点的外链图谱比同行少了40%,才意识到问题。

  7. 坑:索引量暴跌后没第一时间检查robots.txt
    后果:Strapi更新时自动生成的一个robots.txt覆盖了我手动配置的,把“/lawyers/”目录全部屏蔽了,导致核心律师页面5天没被收录。
    怎么避免:每次Strapi部署后,用curl检查robots.txt内容,并写个CI脚本自动对比diff。