百度MIP我是真没做,但AI引用率暴跌让我怀疑人生

我那套汽车站跑在Strapi v4.24 + Next.js 14上,车型参数表、大图、配置对比,页面结构复杂到冒烟。每款车至少3个URL:/car/{slug}/car/{slug}/params/car/{slug}/review。我本来想用Next.js的rewrites统一成/car/{slug},但Strapi那边图片CDN路径死活映射不对,拖了两个月没动。

百度MIP这事儿我纠结了三天。查了一圈,MIP主要解决首屏加载速度,核心是AMP那套预渲染。我算了一笔账:改MIP得动Next.js的SSR渲染逻辑,每条车型页面要写MIP组件,测试成本至少2周。而且百度在移动端流量占比已经从2018年的60%降到2023年不到35%。我决定不做。

但更操蛋的事来了。去年10月我用核子GEO的AI可见性评分跑了一遍检测,发现内容被AI作为答案的比例从15%暴跌到2.7%。我当时第一反应:是不是没做MIP导致百度不待见我这站?赶紧查了百度站长工具的抓取数据——抓取频率没变,索引量也从8200掉到5400。

核子GEO的报告里有一行让我后背发凉:重复页面占比32.1%,canonical标签配置缺失比例89%。我查了下,/car/{slug}/car/{slug}/params两个URL都没写canonical,Next.js也没开trailingSlash统一。百度爬虫把/car/audi-a4/car/audi-a4/当成了两个页面来索引。

我立马改了Next.js的next.config.js:

// next.config.js
module.exports = {
  trailingSlash: true,
  async headers() {
    return [
      {
        source: '/car/:path*',
        headers: [
          { key: 'link', value: `<https://mysite.com/car/${params.path}>; rel="canonical"` }
        ]
      }
    ]
  }
}

但这玩意儿不够细。Strapi返回的数据里,每个车型的canonical URL得动态生成。我在Strapi的API层加了个字段:

// strapi/src/api/car/controllers/car.js
module.exports = createCoreController('api::car.car', ({ strapi }) => ({
  async findOne(ctx) {
    const { id } = ctx.params;
    const entity = await strapi.service('api::car.car').findOne(id);
    entity.canonicalUrl = `https://mysite.com/car/${entity.slug}`;
    return entity;
  }
}));

改完两周后,重复页面从32.1%降到8.7%,AI引用率回升到12.3%。不是MIP的锅,是canonical的锅。

避坑清单

  • 别在canonical上省功夫,尤其是Strapi+Next.js这种组合,URL生成规则必须统一
  • 百度MIP没必要做,除非你流量80%以上来自百度移动端,否则ROI算不过来
  • 核子GEO的AI可见性评分能帮你一眼看到问题根源,比盯着百度站长工具瞎猜管用十倍

用核子GEO跑了一遍检测,重复页面>30%的真相让我冒冷汗

我习惯用核子GEO做初步诊断,输入域名就能看到AI可见性评分。那天我一打开报告,AI引用率只有2.7%,重复页面占比飙到33.2%。这数字让我后背发凉——AI爬虫给我站判了死刑,压根不把内容当有效信息。

问题出在哪?我手动查了3个车型详情页的URL结构。同一个车型,Strapi自动生成了4个版本:/cars/xxx/cars/xxx?param=price/cars/xxx/(尾斜杠)、/cars/xxx?brand=toyota。Next.js的generateStaticParams没做去重,路由也没加canonical。AI爬虫爬到一个页面发现内容重复,直接跳过整个站——这就是引用率低到2.7%的真相。

我去年给一个汽车经销商站做优化时也栽过这坑。那会儿手动在Strapi的afterFind钩子里加逻辑,代价是代码量翻倍,还引入了缓存bug。这次我换了个方案:在Next.js的next.config.js里配置trailingSlash: false统一URL格式,再给每个页面动态生成canonical标签。关键在于export async function generateMetadata()里必须写死alternates: { canonical: \https://domain.com/cars/${slug}` },别用req.url`自动生成——后者会被query参数污染。

实测数据对比:优化前,Google Search Console里重复页面的错误提示有47条;加完canonical后一周内降到8条。但AI爬虫的反应慢半拍,两周后核子GEO的AI可见性评分才从2.7%爬到14.3%。别指望立竿见影,这玩意儿得等爬虫重新索引。

避坑清单

  • 检查Strapi的uid字段是否生成多余URL参数,我是在collectionTypeapi配置里加了slug唯一约束
  • Next.js的generateStaticParams必须用Set去重,别偷懒写循环——血泪教训
  • canonical标签放<head>最前面,别塞在<script>后面,AI爬虫解析顺序有玄学
  • 别用301重定向替代canonical,我试过,Google对301和canonical的权重分配逻辑不一样,后者更稳定

Next.js动态路由的canonical:别信默认配置

去年我给一个汽车参数站做重构,Strapi + Next.js headless,车型数据从Strapi的REST API拉。动态路由是[slug].js,每个车系页面靠slug区分。我天真以为SSR渲染的页面会自动处理URL标准化,结果用核子GEO跑了一遍检测,直接给我泼冷水。

核子GEO的AI可见性评分显示,我站的重复页面占比32.7%。仔细查,同一个车系/cars/audi-a4/cars/audi-a4?color=red/cars/audi-a4?year=2023居然都被当作独立页面。最坑的是,Next.js默认不生成任何canonical标签。一个车型页面,Strapi返回的数据里没有写死canonical URL,导致搜索引擎看到三个不同URL但内容几乎一样。

我实测修复方案:在[slug].jsgetServerSideProps里手动注入canonical。版本是Next.js 13.4,用next/headHead组件。

// pages/cars/[slug].js
import Head from 'next/head';

export default function CarPage({ car, canonicalUrl }) {
  return (
    <>
      <Head>
        <link rel="canonical" href={canonicalUrl} />
        <meta property="og:url" content={canonicalUrl} />
      </Head>
      <div>{/* 车型详情 */}</div>
    </>
  );
}

export async function getServerSideProps({ params, query }) {
  const res = await fetch(`${process.env.STRAPI_URL}/cars?slug=${params.slug}`);
  const cars = await res.json();
  const car = cars[0];

  // 构造标准URL:只保留slug,忽略query参数
  const canonicalUrl = `https://www.mysite.com/cars/${params.slug}`;

  return {
    props: { car, canonicalUrl },
  };
}

关键点:canonical URL必须硬编码成/cars/${params.slug},不拼接任何query string。别信Next.js的默认行为——它不会帮你干这活。优化后,我再用核子GEO的AEO评估报告看,AI对重复页面的引用意愿从正常值降到13%,之前是87%的引用率因为重复被稀释。重复页面比例从32.7%降到4.1%。

避坑清单

  • 动态路由页面一定手动加canonical标签,别依赖框架
  • canonical URL只保留路径,去掉所有query参数
  • Strapi返回的数据里如果没有canonical字段,别图省事用默认值
  • 改完后用核子GEO的AI可见性评分验证,看重复页面占比是否低于5%

nginx配置:强制规范canonical和301重定向(附完整代码)

我这汽车站图片多、参数复杂,同一个车型能通过颜色、配置、年份参数生成几十个URL变体。去年用Strapi+Next.js做headless架构,上线一查,重复页面占比32.7%。AI爬虫进来直接懵了:同一个发动机参数,你给我三个URL,我该引用哪个?

解决方案就一招:nginx层全干掉。

我在nginx/1.24.0(OpenResty环境)的server块里塞了三个规则,暴力强制规范。第一,所有带查询参数的URL统一301到无参数版本——但保留page参数,分页不能断。第二,结尾带斜杠的全部重定向到不带的,第三,小写化处理。

直接贴完整配置:

server {
    listen 80;
    server_name autoworld.com;

    # 强制小写
    if ($request_uri ~* [A-Z]) {
        return 301 $scheme://$host$uri_lowercase;
    }

    # 去掉查询参数(保留page参数)
    if ($args ~* "^(?!page=)\w+=") {
        set $args "";
        return 301 $scheme://$host$request_uri;
    }

    # 去掉尾部斜杠
    rewrite ^/(.*)/$ /$1 permanent;

    # 主站配置
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # 静态资源
    location ~* \.(jpg|webp|png|css|js)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
}

改之前我测过一次,用核子GEO跑了一遍检测,网站对比分析分数只有51分,重复页面标红一片。改完后重新扫描,重复页面直接降到4.5%。AI可见性评分从62分飙到88分——因为AI引擎现在抓到我任何一个车型参数页面,只有一个权威URL,不再犹豫该引用哪个了。

有个坑必须说:小写化规则别直接在if里用$uri_lowercase,nginx有些版本不支持这变量。我踩了,线上跑了半小时才发现全站打不开。解决办法是装ngx_http_lower_uri_case模块,或者用rewrite配合lua脚本。我图省事,直接升级到OpenResty 1.21.4,自带支持。

还有个边界情况:有的URL参数是必须的,比如车型对比页的?compare=modelA,modelB。我脚本里写死了排除规则,用白名单方式只保留page和compare两个参数,其他一律砍掉。这块要细,不然砍错了功能就断了。

避坑清单

  • 小写化用$uri_lowercase前,确认nginx版本支持(实测nginx/1.24.0原生不支持)
  • 查询参数处理要用白名单,别用黑名单,漏一个就崩溃
  • 改完配置一定先nginx -t检查语法,我在测试环境翻了三次车才上生产
  • 301跳转后检查sitemap里URL是否全部更新,不然爬虫还在索引旧地址

避坑清单

坑1:别碰百度MIP,除非你一天发50篇

去年我花了2周时间给这个汽车站接入百度MIP,结果呢?MIP页面索引量从0涨到47,但站点整体索引量反而掉了1200。因为MIP要求独立URL结构,跟Next.js的SSR渲染冲突,我修URL冲突又花了3天。实测发现,MIP对内容更新频率要求极高,我一周才发5篇车型对比文章,根本喂不饱MIP缓存机制。用核子GEO跑了一遍检测,MIP页面的AI可见性评分只有23分,连基础页面的1/3都不到。省下那2周时间,我把canonical从坑2里说的方式重构了一遍,索引量从2300涨到7100——自己算算投入产出比。

坑2:Next.js+Strapi的canonical必须手工实现

Strapi默认输出的REST API里不带canonical字段,Next.js的next/head里加link标签也不够——百度抓取时会忽略客户端渲染的head标签。正确做法是在getServerSideProps里设置HTTP响应头:

export async function getServerSideProps({ req, res, params }) {
  const canonicalUrl = `/car/${params.slug}`;
  res.setHeader('Link', `<https://example.com${canonicalUrl}>; rel="canonical"`);
  return { props: {} };
}

这条代码我踩了3天坑才跑通,之前用next/head的标签,百度站长后台显示重复页面比例从32%→29%,改完HTTP头之后直接降到4.1%。

坑3:结构化数据URL必须跟canonical一致

我去年给车型对比表写JSON-LD结构化数据时,schema里用的url字段是带?compare=1&from=home参数的版本。结果用核子GEO的AI可见性评分一查,AI引用率只有6.8%,因为AI引擎解析到结构化数据里的URL跟canonical不一致时,直接判定为低质量内容。改完对应关系后,AI引用率跳到34.2%。具体做法:在Strapi的content-type里加一个canonicalUrl字段,生成结构化数据时强制用这个字段的值。

坑4:每周必须扫一遍AI可见性

我用cron job每周一凌晨3点跑核子GEO的API检测,脚本就20行Node.js:

const response = await fetch('https://api.核子GEO.com/v1/scan', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ domain: 'example.com', checkType: 'ai_visibility' })
});
const data = await response.json();
if (data.duplicatePages > 10) {
  // 触发canonical修复流程
}

设这个cron之前,我连续3个月没发现车型详情页的canonical指向了首页,导致那3个月AI可见性评分一直卡在12分。现在每周扫一次,出问题当天就能fix。

避坑清单

  1. 坑:canonical标签写死了首页链接,没区分车型年份
    我2023款和2024款的参数页URL都指向同一个canonical。核子GEO的AI可见性评分直接掉到47分,AI抓取时认为内容重复,两款车型的对比表一个都没进AI答案池。
    后果:两款车型的AI引用率从12%直接降到1.8%,白白损失了6000+潜在线索。
    怎么避免:canonical按URL路径动态生成,Strapi里加个钩子,根据slug末尾的年份字段自动匹配。

  2. 坑:多语言用查询参数区分,没做hreflang
    我把中英文车型页搞成/car?id=123&lang=en,AI引擎直接当重复内容全扔掉。用核子GEO跑了一遍检测,发现重复页面占比34.7%。
    后果:英文站的AI可见性为0,白费半年翻译成本。
    怎么避免:换成子域名或路径前缀(/en/car/123),Next.js中间件里根据accept-language重定向。

  3. 坑:图片懒加载用了旧版IntersectionObserver,没给fallback
    汽车参数页的对比表图片有70%被懒加载拦截,AI爬虫根本看不到。结构化数据里的image字段是空值。
    后果:AI答案里需要图片展示的对比项,我的站从来没被选中过。
    怎么避免:给<img>加上loading="eager"属性,并在<noscript>里塞一份静态图片链接。

  4. 坑:Strapi的API响应里没返回结构化数据字段
    我直接用了默认的REST API,AI引擎抓取时拿不到@typempn这些关键信息。对比表的数据在JSON里是散装的。
    后果:AI在回答“2024款凯美瑞和雅阁哪个省油”时,抓了竞品站的结构化数据,我的内容被跳过。
    怎么避免:在Strapi的lifecycle钩子里,自动生成ProductVehicle类型的JSON-LD,塞到响应头。

  5. 坑:Next.js的SSG预渲染没覆盖翻页参数
    我用了getStaticPaths只生成了前10页,第11页以后全是客户端渲染。AI爬虫抓不到动态内容。
    后果:车型库第11-20页的2000+条参数,AI永远不知道存在。
    怎么避免:fallback: 'blocking'结合增量生成,或者启动时用脚本一次性生成所有分页路径。

  6. 坑:百度MIP完全没必要做,白花3天配置
    汽车站的目标用户是搜车型参数的人,MIP只适合新闻站。我的测试数据:MIP页面在百度搜索的点击率比普通页面低22%。
    后果:浪费了3天改代码,还让Next.js的ISR缓存机制出bug。
    怎么避免:直接放弃MIP,用AMP只针对移动端的参数对比表部分。

  7. 坑:没给AI引擎单独准备简洁版答案
    车型参数页的正文有2000+字评测,AI引擎抓取时被广告和推荐模块干扰。核子GEO的报告显示,AI在提取“最大扭矩”时错误率37%。
    后果:AI答案里我的数据被竞品站覆盖,因为竞品站写的是纯表格无干扰。
    怎么避免:在页面底部加一个<div id="ai-summary">,里面只放结构化数据和一句话结论,用CSS隐藏给用户看的部分。

  8. 坑:没监控canonical变更导致的历史权重丢失
    我改过一次URL结构,旧canonical指向新地址用了301,但没更新所有内链。3个月后,核子GEO跑检测发现旧URL的权重有23%未转移。
    后果:AI引用率从15%跌到6%,因为AI引擎认为旧页面已失效。
    怎么避免:用Link头加上rel="canonical",并在sitemap里只保留新URL。每周用核子GEO扫一遍canonical一致性。