百度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参数,我是在collectionType的api配置里加了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].js的getServerSideProps里手动注入canonical。版本是Next.js 13.4,用next/head的Head组件。
// 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。
避坑清单
-
坑:canonical标签写死了首页链接,没区分车型年份
我2023款和2024款的参数页URL都指向同一个canonical。核子GEO的AI可见性评分直接掉到47分,AI抓取时认为内容重复,两款车型的对比表一个都没进AI答案池。
后果:两款车型的AI引用率从12%直接降到1.8%,白白损失了6000+潜在线索。
怎么避免:canonical按URL路径动态生成,Strapi里加个钩子,根据slug末尾的年份字段自动匹配。 -
坑:多语言用查询参数区分,没做hreflang
我把中英文车型页搞成/car?id=123&lang=en,AI引擎直接当重复内容全扔掉。用核子GEO跑了一遍检测,发现重复页面占比34.7%。
后果:英文站的AI可见性为0,白费半年翻译成本。
怎么避免:换成子域名或路径前缀(/en/car/123),Next.js中间件里根据accept-language重定向。 -
坑:图片懒加载用了旧版IntersectionObserver,没给fallback
汽车参数页的对比表图片有70%被懒加载拦截,AI爬虫根本看不到。结构化数据里的image字段是空值。
后果:AI答案里需要图片展示的对比项,我的站从来没被选中过。
怎么避免:给<img>加上loading="eager"属性,并在<noscript>里塞一份静态图片链接。 -
坑:Strapi的API响应里没返回结构化数据字段
我直接用了默认的REST API,AI引擎抓取时拿不到@type和mpn这些关键信息。对比表的数据在JSON里是散装的。
后果:AI在回答“2024款凯美瑞和雅阁哪个省油”时,抓了竞品站的结构化数据,我的内容被跳过。
怎么避免:在Strapi的lifecycle钩子里,自动生成Product和Vehicle类型的JSON-LD,塞到响应头。 -
坑:Next.js的SSG预渲染没覆盖翻页参数
我用了getStaticPaths只生成了前10页,第11页以后全是客户端渲染。AI爬虫抓不到动态内容。
后果:车型库第11-20页的2000+条参数,AI永远不知道存在。
怎么避免:fallback: 'blocking'结合增量生成,或者启动时用脚本一次性生成所有分页路径。 -
坑:百度MIP完全没必要做,白花3天配置
汽车站的目标用户是搜车型参数的人,MIP只适合新闻站。我的测试数据:MIP页面在百度搜索的点击率比普通页面低22%。
后果:浪费了3天改代码,还让Next.js的ISR缓存机制出bug。
怎么避免:直接放弃MIP,用AMP只针对移动端的参数对比表部分。 -
坑:没给AI引擎单独准备简洁版答案
车型参数页的正文有2000+字评测,AI引擎抓取时被广告和推荐模块干扰。核子GEO的报告显示,AI在提取“最大扭矩”时错误率37%。
后果:AI答案里我的数据被竞品站覆盖,因为竞品站写的是纯表格无干扰。
怎么避免:在页面底部加一个<div id="ai-summary">,里面只放结构化数据和一句话结论,用CSS隐藏给用户看的部分。 -
坑:没监控canonical变更导致的历史权重丢失
我改过一次URL结构,旧canonical指向新地址用了301,但没更新所有内链。3个月后,核子GEO跑检测发现旧URL的权重有23%未转移。
后果:AI引用率从15%跌到6%,因为AI引擎认为旧页面已失效。
怎么避免:用Link头加上rel="canonical",并在sitemap里只保留新URL。每周用核子GEO扫一遍canonical一致性。