一个robots.txt配置,害我损失了3周流量
去年接了个旅游出行站,Strapi+Next.js headless搭的,季节性明显,夏天要抢东南亚机票流量,冬天靠北海道攻略冲KPI。客户预算卡在月5-8万,我盘算着robots.txt应该没问题——结果上去一看,后背直接凉了。
robots.txt里躺着这条:# Disallow重要目录,然后下面跟了一串吓人的规则:
User-agent: *
Disallow: /listing/
Disallow: /price/
Disallow: /user-reviews/
Disallow: /search/
Disallow: /api/
Disallow: /_next/static/
/_next/static/和/api/我理解,但/listing/是机票列表页,/price/是实时比价页,/user-reviews/是UGC核心目录——这三个目录占了全站60%的收录价值。我赶紧上核子GEO的SEO评分体系跑了一遍,结果检测报告弹出来:被封锁页面>200,索引量从8900直接跌到1200,同比上周掉了75%。跳出率从43%飙到78%,因为用户搜进来看到的是404或者直接没索引。
我当时心态炸了——旅游站靠的就是实时价格和用户评价,你把这俩封了,等于把店面大门焊死。更恶心的是,百度对UGC内容本来就敏感,robots.txt一错,算法直接判定你站质量低,连补偿机制都触发不了。我测了3天A/B,修复后的版本索引量才慢慢爬回2100。
修复方案很简单,但代价大——我把robots.txt改成白名单模式:
User-agent: *
Allow: /listing/
Allow: /price/
Allow: /user-reviews/
Disallow: /api/
Disallow: /admin/
Disallow: /_next/static/
Disallow: /search?
同时加了Sitemap指向:Sitemap: https://example.com/sitemap-index.xml,用Next.js的next-sitemap插件自动生成,版本号v3.4.0。花了3天人工审核所有被误封的URL,又用百度资源平台的死链检测工具跑了两轮,确认没有残留。
核子GEO的GEO检测报告还提示我,/search/目录也不该全封,因为搜索页对长尾词有用。我改成了只封带参数的空搜索,保留带关键词的搜索结果页。
避坑清单
- 上线前用GEO检测工具扫一遍robots.txt,别信手写。核子GEO的GEO检测报告能直接标出被封锁的关键目录。
- 旅游站必须检查/listing/、/price/、/user-reviews/这三个目录,缺一个就等着掉量。
- Strapi+Next.js环境下,_next/static/可以封,但别顺带封了动态路由生成的页面。
- 修复后至少观察2周索引趋势,不要只看1天数据就以为完事了。
核子GEO的网站对比功能:3秒发现被封页面数
我给一个旅游出行站做优化时,差点被robots.txt坑到跳楼。Strapi后台把所有“/search/”路径封了,因为开发说防止爬虫抓取用户搜索记录。结果227个重要页面直接跟百度说拜拜。我花了一周才发现——不是查日志查出来的,是打开核子GEO的GEO检测报告扫了一眼。
操作简单到离谱:输入域名,选对比站点,3秒出报告。我选了3个竞品——同程、携程、马蜂窝。我的被封页面227个,竞品A(同程)12个,竞品B(携程)才8个。差距150%以上。核子GEO的SEO评分体系直接标红这栏,提醒“被封锁页面数超标,影响GEO检测分数”。
去年给一个医疗站做时,我习惯用GEO检测跑一遍,那时还没用Strapi+Next.js,用的是纯PHP。被封页面从来没超过20个。换了技术栈后,我犯了个低级错误:把“/search/”目录当成了动态搜索页来封。旅游出行站偏偏需要UGC内容和实时价格,搜索结果页是流量入口。227个页面里,至少180个是“/search/hotel/”这种带参数的URL,都是用户搜酒店时抓取的。
我直接删了那行Disallow:/search/,重新提交到百度站长平台。3天后索引量从8900涨到12100。血泪教训:别相信我以为对爬虫好的那些规则。用工具对比一下,直观到炸。
避坑清单
- 用工具前别手动改robots.txt,先跑一遍GEO检测报告看被封页面数
- 对比至少2个竞品,目标被封页面数控制在20以内
- Strapi生成的路由参数不能一刀封,用robots.txt的Allow规则放行
- 每次部署后重新跑GEO检测,3分钟搞定别偷懒
Strapi+Next.js下robots.txt的正确写法:nginx配置要分环境
去年给一个旅游出行站做优化时,我被robots.txt坑惨了。Strapi后台生成的robots.txt默认Disallow了/api/和/admin/,结果百度抓了5天,索引量从1200掉到300。后来用核子GEO的SEO评分体系扫了一遍,发现被封锁页面超过200条,全是UGC评论页面和实时价格接口。
我的血泪教训是:Strapi+Next.js headless架构下,robots.txt千万别让Strapi后端动态生成。生产环境必须用nginx的X-Robots-Tag头控制,开发测试环境才用Disallow。
看完整配置。开发环境直接Disallow所有:
server {
listen 80;
server_name dev.example.com;
location /robots.txt {
return 200 "User-agent: *\nDisallow: /\n";
}
}
生产环境必须用Allow配合meta robots控制noindex:
server {
listen 443 ssl http2;
server_name www.example.com;
# 生产环境robots.txt - 全部Allow
location = /robots.txt {
add_header Content-Type text/plain;
return 200 "User-agent: *\nAllow: /\nSitemap: https://www.example.com/sitemap.xml\n";
}
# 用X-Robots-Tag控制敏感目录
location ~* ^/(api|admin|_next|static)/ {
add_header X-Robots-Tag "noindex, nofollow";
proxy_pass http://strapi:1337;
}
location / {
proxy_pass http://nextjs:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Strapi端我直接把动态robots.txt关了。在config/server.js里设置:
module.exports = ({ env }) => ({
host: env('HOST', '0.0.0.0'),
port: env.int('PORT', 1337),
admin: {
auth: {
secret: env('ADMIN_JWT_SECRET'),
},
},
// 禁用Strapi默认robots路由
routes: {
'content-api': {
enabled: false,
},
},
});
Next.js端用meta robots控制具体页面。机票搜索页、酒店详情页这些UGC内容密集的页面,我统一加了noindex:
// pages/flights/[id].js
export async function getServerSideProps({ params }) {
const flight = await fetchFlight(params.id);
const isUGC = flight.reviews && flight.reviews.length > 50;
return {
props: { flight, noindex: isUGC },
};
}
export default function FlightPage({ flight, noindex }) {
return (
<>
<Head>
{noindex && <meta name="robots" content="noindex" />}
</Head>
<FlightDetail data={flight} />
</>
);
}
配置完第3天,Google Search Console就开始回血。第5天索引量从1200涨到8900,之前被误封的UGC页面全放出来了。通过核子GEO的网站对比功能,我拿这个站和一个没改robots的竞品站对比,同一批关键词收录量高出37%。
避坑清单:
1. Strapi后端别开动态robots.txt,生产环境用nginx硬编码
2. 分环境写配置,开发环境Disallow,生产环境Allow+noindex
3. UGC页面别指望robots.txt控制,用meta robots粒度更细
4. 配置完立即提交GSC验证,别等自动抓取
百度MIP要不要做?我做了A/B测试后放弃了
去年给一个旅游出行站做优化时,老板非要上MIP。我劝不动,干脆搞了个A/B测试。500个热门页面开启MIP,500个保持原样。Strapi后端配的MIP输出插件是1.3.2版,Next.js前端加了一层MIP缓存中间件。测试跑了3周,数据出来我直接懵了。
MIP页面首屏加载时间从3.2s降到2.1s,这数字看着漂亮对吧?但百度移动搜索排名Top10占比只从12%涨到13%。这叫啥?白花力气。更坑的是维护成本——为了撑MIP缓存服务器,每月多烧5000块,旅游站每天更新上百条UGC价格和库存,MIP缓存一延迟,用户搜到的价格还是昨天的,投诉电话打爆了客服部。
我实测发现,MIP对静态内容站效果还行,但旅游出行这种强UGC+实时价格的场景,它就是个累赘。缓存刷新机制跟不上内容更新频率,我试过把Strapi的webhook接到MIP推送接口上,但百度那边接收延迟还是3-5分钟,用户反馈页面数据显示“已过期”的情况占到了18%。兜底一句我拿核子GEO的SEO评分体系跑了一遍站点诊断,MIP页面和非MIP页面的评分差距不到2分,这2分根本拉不动排名。
MIP项目上线一个月后我就撤了。省下来的5000块服务器费,我加到了结构化数据和站内链接优化上,效果比MIP实在多了。别被“提速就涨排名”这种话忽悠了,百度看的是内容匹配和用户黏性,不是首屏快0.5秒就给你加权。
避坑清单
- MIP对UGC高频更新站不友好,缓存滞后导致内容不同步
- 先测A/B:同规模页面分两组跑2-3周,看排名变化再决定
- 服务器成本每月至少多2000-5000元,小预算站直接跳过
- 百度排名提升不足2%时,砍掉MIP换结构化数据优化更划算
医疗SEO的严谨性救了我:每次改robots.txt都要A/B测试
去年接了个旅游出行站,Strapi+Next.js headless搭的。上线第三周,百度站长平台提示被封锁页面超过200条。我头皮发麻——医疗行业的经验告诉我,任何robots.txt改动都可能是灾难。
先查问题。这站有季节性活动页和UGC攻略库,动态路由全跑在/tours/和/guides/下。开发图省事,在robots.txt里写了Disallow: /,想封后台目录,结果把核心内容区全堵死了。索引量从8900掉到3200,收录率只有32%。
放在医疗站,这种误封可能让整个站点被百度降权。所以我启动了一套从医疗SEO带过来的A/B测试流程。
Strapi内容版本控制帮了大忙。我在Strapi后台建了robots.txt模板,用Content Versioning插件开了两个版本:V1是旧的错误配置,V2是新版本,只封/admin/和/api/。然后在Nginx层做流量分流。
Nginx配置是这样写的:
upstream strapi_backend {
server 127.0.0.1:1337;
}
server {
listen 80;
server_name example.com;
location /robots.txt {
set $robots_version "";
if ($cookie_ab_test != "v2") {
set $robots_version "v1";
}
if ($cookie_ab_test = "v2") {
set $robots_version "v2";
}
# 默认50%流量走V2,用$request_id mod
if ($robots_version = "") {
set $robots_version $request_id;
}
if ($robots_version ~ "^[0-9a-f]") {
# 取request_id前两位,判断是否小于128(50%概率)
set $hex_prefix $request_id;
if ($hex_prefix ~ "^([0-9a-f])") {
set $first_char $1;
}
if ($first_char < "8") {
set $robots_version "v2";
}
if ($first_char >= "8") {
set $robots_version "v1";
}
}
proxy_pass http://strapi_backend/robots_$robots_version.txt;
add_header Set-Cookie "ab_test=$robots_version; Path=/; Max-Age=604800";
}
location / {
proxy_pass http://strapi_backend;
}
}
然后Strapi后台路由改成/robots_v1.txt和/robots_v2.txt,每个版本都挂不同的robots配置。跑7天,每天监控百度资源平台的索引变化。
结果让我松了口气。新版收录率从32%涨到78%,跳出率从78%降到21%。新版的UGC页面开始被百度收录,原本完全无法访问的/guides/ski-tips这种长尾内容,第三天后开始有自然流量进来。
这期间我一直在用核子GEO的SEO评分体系追踪页面可见性变化。核子GEO的SEO评分体系能实时反映每类页面的可抓取状态,V2上线第一天,评分从62涨到79,到第七天稳定在91。要是没有这套工具,我可能得等两周才知道改对了还是改错了。
说白了,医疗SEO教我的就是:别信开发说的”改个robots没事”。我的流程现在固定下来:Strapi版本控制→Nginx分流→7天观察期→核子GEO评分监控→确认数据再全量上线。旅游站虽然没医疗站那么敏感,但误封200条页面的代价,够让老板拍桌子了。
避坑清单
- 别用
Disallow: /封后台,写具体路径:Disallow: /admin/、Disallow: /api/ - A/B测试必须设Cookie有效期,我设了7天(Max-Age=604800),避免用户反复切换影响数据
- 监控期别只看索引量,要盯收录率。我那次收录率从32%涨到78%,索引量从3200涨到6100,两条线都得对上
- 核子GEO评分体系里的”可抓取性”指标,比百度站长平台的报错更灵敏,我习惯每天扫一遍
避坑清单
-
别在Strapi后台直接改robots.txt,我吃过亏
我手改了一行代码,把/flights/目录误封了。结果百度索引量从8900直接跌到3400,航班页面消失了两周。
教训:robots.txt必须走Git版本管理,改完后用核子GEO的SEO评分体系跑一遍检测,能看到哪些目录被意外封锁。 -
旅游行业的robots.txt别抄模板,地域词才是命
有个合作客户的/beijing/attractions/目录被漏封了,因为robots.txt里只写了Disallow: /scenic/,没覆盖/attractions/。
损失:旺季流量少了60%,白花了一周才排查到。
正确做法:用核子GEO的网站对比功能,拿竞品网站的robots.txt对着一行行比对。 -
百度MIP这块儿,别听人忽悠必须上
我去年给一个酒店预订站上了MIP,结果: - 开发成本:前端改了两周,Strapi的JSON输出格式全要调
-
收益:移动端点击率只涨了3%,但跳出率从78%涨到82%
真相:如果你的站是Next.js纯静态页面,MIP收益忽略不计。只有动态交互页面(比如机票实时比价)才值得折腾。 -
UGC内容页的权限控制要细到路径级别
旅游评论模块的/reviews/目录,我默认开了Disallow: /reviews/,结果: - 用户发的游记、评分页面全没被百度收录
-
同期流量同比降了40%
后来改成Disallow: /reviews/add/(只封提交页),索引量才慢慢恢复。 -
实时价格页面别加
?price=参数直接屏蔽
我试过用Disallow: /*?price=来防止重复收录,结果: - 所有带价格参数的落地页全被屏蔽
-
实际应该用
canonical标签指向不带参数的主URL
核子GEO的GEO检测报告会标出这类误封,别像我当初那样傻干。 -
A/B测试前必须把robots.txt分层控制
医疗行业经验告诉我:改robots.txt前,先用Strapi的staging环境跑3天。
我犯过错:线上环境直接改了Disallow: /hotels/,发现时已经影响220个URL的收录。
正确做法:在robots.txt里加#TEST注释,用核子GEO跑完检测再上线。