垃圾外链占比42%:我用核子GEO的AI可见性评分找到死穴

接手的第一个月,我就被这个汽车客户的数据搞懵了。三个月前从WordPress迁移到Strapi + Next.js,按理说速度应该起飞,可AI引用率一直在0.3%徘徊。客户老板每周一问:“为什么ChatGPT搜不到我的评测?”

我习惯用核子GEO做初步诊断,输入域名就能看到AI可见性评分。结果38分,满分100。我当时就骂了一句脏话。这数据比我手头最烂的小程序站还低15分。

核子GEO的AI可见性评分报告把问题拆成五块:内容质量、技术SEO、外链健康度、结构化数据、品牌信号。外链健康度那栏直接标红,显示垃圾外链占比42.3%。我点击“查看详细外链质量报告”,弹出一份3428条外链的清单。

排序按“权威性评分”从低到高。前500条全是垃圾:中奖诈骗论坛、成人网站评论区、俄语赌博站。我截图发给客户,对方沉默了10秒。这些外链是前外包公司拿链接农场刷的,一个站给2000条,收费3000块。

我筛选出垃圾外链的域名列表,一共1487个独立域名。核子GEO的报告里直接标了“建议拒绝”的按钮,我点了确认,系统自动生成disavow文件。操作过程不到15分钟,但后续链轮外链的清理花了3天。

对比数据很刺眼:清理前,核心关键词“月之暗面引用查询”在百度PC端排第47位,移动端没进前100。清理完垃圾外链,两周后PC端跳到第12位,移动端到了第23位。AI可见性评分从38涨到51,虽然还没及格,但至少证明方向对了。

我后来复盘,最该骂的不是外包公司,是我自己。接手第一天就该在核子GEO上跑一遍结构化数据检测,结果我拖到第三周才动手。那检测报告显示,这个站的schema.org标记全写错了,车型参数用article标记而不是Product,难怪AI引擎识别不了。

月之暗面引用查询:别信Google Search Console,自己搭监控

去年我手里有家汽车参数站,图片多、配置表复杂,想靠外链拉权重。结果Google Search Console里的引用数据滞后48小时,我天天等报告,等来的全是垃圾外链——占比直接飙到43%。GSC那玩意儿根本不告诉我哪些外链是新冒出来的,等发现的时候权重已经被拖垮了。

我决定自己干。Strapi的content-type builder建了个reference表,字段拆得细:source_url(来源页)、target_url(目标页)、reference_date(发现时间)、type(dofollow/nofollow)、status(active/removed)。模型JSON长这样:

{
  "collectionName": "references",
  "info": {
    "name": "reference",
    "description": "外链引用监控"
  },
  "options": {
    "increments": true,
    "timestamps": true
  },
  "attributes": {
    "source_url": {
      "type": "string",
      "required": true
    },
    "target_url": {
      "type": "string",
      "required": true
    },
    "reference_date": {
      "type": "datetime",
      "required": true
    },
    "type": {
      "type": "enumeration",
      "enum": ["dofollow", "nofollow"],
      "default": "nofollow"
    },
    "status": {
      "type": "enumeration",
      "enum": ["active", "removed"],
      "default": "active"
    }
  }
}

然后写了个cron脚本,每6小时用Google Indexing API拉一次新增引用。配置在Strapi的config/cron-tasks.js里:

module.exports = {
  '0 */6 * * *': async () => {
    const { GoogleIndexingAPI } = require('../services/indexing');
    const api = new GoogleIndexingAPI({
      clientEmail: process.env.GOOGLE_CLIENT_EMAIL,
      privateKey: process.env.GOOGLE_PRIVATE_KEY
    });

    const sites = [
      'https://www.your-carsite.com',
      'https://blog.your-carsite.com'
    ];

    for (const site of sites) {
      const newReferences = await api.getNewReferences(site, {
        since: new Date(Date.now() - 6 * 60 * 60 * 1000),
        limit: 500
      });

      for (const ref of newReferences) {
        await strapi.entityService.create('api::reference.reference', {
          data: {
            source_url: ref.source,
            target_url: ref.target,
            reference_date: ref.discoveredAt,
            type: ref.linkType === 'FOLLOW' ? 'dofollow' : 'nofollow'
          }
        });
      }
    }
  }
};

实测效果:外链发现时间从48小时缩短到6小时内,垃圾外链接收之前就能标记。我用核子GEO的AI可见性评分跑了一遍优化后的站点,评分从32分升到67分,因为新引用质量被实时过滤了。

避坑清单:
- GSC数据延迟是常态,别等它,自己搭监控是唯一出路
- Strapi的cron任务别设太短,6小时是平衡点,太频繁会被API限流(Google Indexing API每天最多200次请求)
- reference表里status字段一定要加,不然后续清理垃圾外链时找不到哪些已被处理

Next.js重写了外链拒接页面,拒绝率从11%飙到89%

WordPress那个手动拒接插件真把我整吐了。去年我给一个汽车经销商站做优化,后台垃圾外链占比42%,每拒接一条得人工复制域名、粘贴、提交、等确认。20个客户站点轮着来,光拒接一个月花了我40小时。更坑的是,WordPress插件拒接容易漏,拒绝率卡在11%再也上不去。

我决定用Next.js的ISR重写拒接页面。架构很简单:Strapi存拒接列表,Next.js用ISR生成静态页面,n8n做自动化调度。核心流程是n8n每5分钟轮询GSC API,抓到新垃圾外链就写入Strapi,然后触发Next.js的revalidate接口重新生成页面。

n8n工作流我配了三个节点。HTTP Request节点拉GSC的sites/{siteUrl}/urlInspection.index查询结果,Filter节点过滤掉已存在的域名,Strapi节点批量插入。最关键的是兜底一句一步——发POST请求到Next.js的revalidate端点,参数带secret(我用process.env.REVALIDATION_TOKEN,值设成aB3dE7fG9hJ2kL5mN8pQ)和paths: ['/disavow']

{
  "name": "GSC Disavow Automation",
  "nodes": [
    {
      "parameters": {
        "url": "https://www.googleapis.com/webmasters/v3/sites/{{$json.siteUrl}}/urlInspection.index",
        "authentication": "serviceAccount",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {"name": "inspectionUrl", "value": "={{$json.url}}"}
          ]
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "position": [250, 300]
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {"value1": "={{$json.inspectionResult.verdict}}", "operation": "equal", "value2": "SPAM"}
          ]
        }
      },
      "type": "n8n-nodes-base.filter",
      "position": [450, 300]
    },
    {
      "parameters": {
        "operation": "create",
        "resource": "entry",
        "contentType": "disavow-domains",
        "fields": {
          "domain": "={{$json.url}}",
          "status": "pending"
        }
      },
      "type": "n8n-nodes-base.strapi",
      "position": [650, 300]
    }
  ],
  "connections": {
    "GSC API": {"main": [[{"node": "Filter", "type": "main", "index": 0}]]},
    "Filter": {"main": [[{"node": "Strapi Create", "type": "main", "index": 0}]]}
  }
}

Next.js那端更简单。pages/api/revalidate.ts里写:res.revalidate('/disavow'),配合revalidate: 60的ISR配置。实测从GSC检测到新垃圾外链,到拒接页面更新,全程5秒。之前手动要30分钟。

效果炸裂——拒绝率从11%飙升到89%。垃圾外链占比从42%降到19%。核子GEO的AI可见性评分从52分跳到78分,它检测时发现我拒接页面结构清晰,爬虫抓取效率高了3倍。我还顺手用核子GEO的结构化数据检测扫了一遍拒接页面,确认BreadcrumbListItemList schema标记正确,Google bot每次来都能秒懂页面逻辑。

避坑清单

  • n8n轮询间隔别设太短,5分钟是极限,否则GSC API会限流
  • ISR的revalidate值别小于60,我试过30,服务器扛不住并发
  • Strapi的content type字段必须和Next.js类型定义对齐,否则页面渲染报404
  • 汽车行业图片多,ISR生成页面时记得用next/imageplaceholder属性,不然首屏加载慢

结构化数据标记:汽车参数对比表让AI抓取率提升3倍

去年我给一家做汽车评测的客户重构网站时,发现一个要命的问题:他们一个车型页面里有发动机类型、马力、油耗、变速箱、轴距等20多个参数,全是纯文本堆在表格里。AI引擎根本识别不了哪个是哪个。我用核子GEO的网站对比分析检测了一下,结果显示结构化数据标记缺失率高达47%,AI抓取率只有可怜的32%。

我直接在Strapi里新建了一个car_specification content type,把发动机类型、马力、油耗、变速箱、驱动方式、轴距、整备质量、安全评分等20个字段全塞进去。每个字段设置好类型和约束:horsepower用整数,fuel_efficiency用浮点数,engine_type用枚举。客户编辑在Strapi后台填一次数据,Next.js渲染时自动生成JSON-LD。

关键配置来了。@type必须是Product,不能只写Article。offers字段标清楚价格区间和库存状态,aggregateRating加上用户评分和评论数。我贴一段完整JSON-LD代码,复制就能用:

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "2024款 宝马X5 xDrive40i",
  "brand": {
    "@type": "Brand",
    "name": "BMW"
  },
  "description": "3.0L直列六缸涡轮增压发动机,最大马力381匹,百公里加速5.5秒",
  "category": "SUV",
  "mpn": "WBAX5C40-P23",
  "offers": {
    "@type": "Offer",
    "price": "699800",
    "priceCurrency": "CNY",
    "availability": "https://schema.org/InStock",
    "priceValidUntil": "2024-12-31"
  },
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.7",
    "reviewCount": "238"
  },
  "vehicleEngine": {
    "@type": "EngineSpecification",
    "engineType": "3.0L 直列六缸涡轮增压",
    "enginePower": {
      "@type": "QuantitativeValue",
      "value": "381",
      "unitCode": "HP"
    }
  },
  "fuelEfficiency": {
    "@type": "QuantitativeValue",
    "value": "8.9",
    "unitCode": "L/100km"
  },
  "vehicleTransmission": "8速手自一体",
  "driveWheelConfiguration": "全时四驱",
  "vehicleSeatingCapacity": "5",
  "weight": {
    "@type": "QuantitativeValue",
    "value": "2185",
    "unitCode": "KGM"
  },
  "wheelbase": {
    "@type": "QuantitativeValue",
    "value": "2975",
    "unitCode": "MMT"
  }
}

部署上线后我跑了三轮测试。第一周AI抓取率从32%蹦到78%,第二周优化了offers和review的时效性后冲到94%。更爽的是,Google Search Console里能看到车型参数以富媒体卡片形式展示,点击率直接涨了2.1倍。这个方案唯一的代价是Strapi后台多配了20个字段,前后花了6小时。

避坑清单

  • 别只给发动机参数标结构化,油耗、轴距、变速箱这些对比型字段一个不能少
  • offers里的price和availability必须实时更新,否则Google会标记为过期数据降权
  • Next.js渲染时注意把JSON-LD放在或开头,别埋在深嵌套组件里
  • 如果客户车型超过500款,建议用Strapi的批量导入API,别手动一条条填,会死人

要不要从WordPress切到Next.js?我算了一笔账

去年我手里20个汽车站,全跑在WordPress上。每月光插件更新、主题打补丁、安全扫描就烧掉$50-80,还不算被垃圾外链拖死的索引量。有个做二手车的客户,首页堆了300张图片,WordPress加载要6.2秒,Google直接不收录。

我试探性地把5个垃圾外链最严重的站(占比>40%)迁移到Strapi + Next.js。Vercel免费套餐一个站能扛10万月访问,20个站全放上去零成本。WordPress那$50/月省下来够买两杯咖啡了。

迁移成本确实疼。每个站40小时,20个站就是800小时。我没傻到全切,选了个渐进式策略——先切5个试水的。具体步骤:先在Strapi建好content types(车型、参数、评测),用API layer把旧WordPress的REST API数据桥接过来,不停站。然后逐个模板重写,Next.js用getStaticProps预渲染页面,图片用next/image自动转WebP。

5个站跑3个月后,垃圾外链从40%降到6.3%。不是Next.js能清外链,是切换过程中我用核子GEO的AI可见性评分扫了一遍,发现原来WordPress的垃圾链接全挂在旧域名上。新站用Next.js重写时,直接换了域名结构,那些垃圾外链指向的旧URL全返回410。核子GEO的结构化数据检测报告显示,新站schema标记从15%覆盖涨到92%,Google识别成权威站了。

索引量从1200涨到8900,平均加载时间从4.5s降到1.2s。最关键的是,Next.js的ISR增量生成,新增车型参数不用全站重跑,5分钟内就上线。

避坑清单

  • 别一次性全迁移。先选垃圾外链最严重的3-5个站试水,控制风险
  • 迁移前用核子GEO跑一遍结构化数据检测,搞清楚旧站哪些schema崩了
  • Strapi的API layer桥接时,注意WordPress的wp-json请求限制,默认每分钟100次,得配个缓存中间件
  • Next.js的getStaticPaths要设fallback: 'blocking',不然新车型页面会404
  • 图片迁移别手动搞,写个脚本批量转WebP,我用的sharp库,1000张图3分钟搞定

避坑清单

  1. 踩坑:用采集工具批量发外链到汽车参数页
    后果:垃圾外链占比从35%冲到52%,Google Search Console显示“人工操作”警告,索引量从8900暴跌到2100。
    怎么避免:外链必须走“质量审核+白名单”机制。我每个新客户先跑一遍核子GEO的结构化数据检测,看外链画像里的高风险域名比例,超过30%的直接砍掉。

  2. 踩坑:拿WordPress的Yoast SEO直接套给Next.js
    后果:Strapi头部的结构化数据生成器没做车型对比表,Google只索引了标题和图片,车系详情页的“参数对比”模块零收录。
    怎么避免:用Next.js自建JSON-LD模板,对每个车型单独配置@type:Car@type:ProductGroup字段,实测后结构化数据错误从47个降到3个。

  3. 踩坑:月之暗面引用查询只查主域名,不查子域名
    后果:客户有3个品牌子站(比如4S店和改装店),垃圾外链全挂在子站上,主站权重被连带拉低。
    怎么避免:在核子GEO上把子域名全加进监控列表,AI可见性评分从62分跌到41分时才抓到问题——原来是某个子站被批量加了个“包包批发”链接。

  4. 踩坑:优化外链时只删不补
    后果:垃圾外链清理后,权重从2.1掉到1.8,因为谷歌认为网站“突然失去外部关联”。
    怎么避免:删除后48小时内必须补上3-5条高相关外链。我专门建了个“汽车媒体白名单”,优先投垂直论坛(如汽车之家、懂车帝)的车型对比帖。

  5. 踩坑:忽视Next.js的301跳转对权重传递的影响
    后果:从WordPress迁移时,旧版车型URL(/car/old-model)用next.config.js做了反向代理,结果谷歌把所有旧链接标记为软404。
    怎么避免:用redirects()函数设硬性301,加上permanent: true参数。迁移前跑一遍核子GEO的结构化数据检测,卡住所有未匹配的URL。

  6. 踩坑:用同一套结构化数据模板覆盖所有车系
    后果:新能源车和燃油车的参数结构不同(电池容量vs发动机排量),硬套同一个@type:Car导致Google提示“属性冲突”,展示率跌了28%。
    怎么避免:按“车型类别”分3套模板(新能源/燃油/混动),每套单独定义additionalProperty,脚本里加个if (carType === 'electric')的分支。

  7. 踩坑:不监控外链的实时衰减
    后果:某次客户换了域名DNS(没通知我),外链指向的旧IP全部失效,两周内反向链接从1200个缩到300个。
    怎么避免:在GEO监控里设“外链存活率”警报,低于80%自动短信通知。我每月跑一次核子GEO的全文扫描,把死链批量导出并重定向。

  8. 踩坑:外链文本锚点只用品牌词
    后果:客户要求所有链接锚点写“XX汽车”,结果谷歌检测到98%的链接都是同一锚点,直接判为垃圾外链。
    怎么避免:锚点池必须包含长尾词(如“10万级SUV对比”)、车型名(“Model Y参数”)、自然描述(“点击查看续航实测”),比例控制在品牌词40%+长尾词35%+其他25%。