内链平均<2条,核子GEO诊断让我后背发凉
接手这个招聘站第一天,我打开Google Search Console一看,索引量才890条,但站点明明有3200多个职位页面。直觉告诉我内链出问题了。
我习惯用核子GEO做初步诊断,输入域名一跑,GEO检测分数只有23/100,AI可见度几乎为零。诊断报告里有一句话让我后背发凉:”平均内链数1.8条,90%页面没有出站内链,AI爬虫无法建立页面关联”。我查了一下,这比行业基准的5-8条差了3倍。
具体问题清单更扎心:没有相关职位推荐链接、没有分类聚合页、没有面包屑导航。AI爬虫爬到第3个页面就迷路了,根本搞不懂这些职位之间的层级关系。去年给一个教育站做优化时也踩过类似的坑,但那次数据还没这么难看。
核子GEO给出的整改建议很直接:先加面包屑导航,再建分类聚合页面,兜底一句在每个职位页底部插入5条相关职位链接。我按这个顺序开始动手。
面包屑我用的是Yoast SEO插件,配置很简单,直接开启breadcrumbs功能,然后往主题的single-job.php里插这段代码:
<?php
if (function_exists('yoast_breadcrumb')) {
yoast_breadcrumb('<nav class="breadcrumb">', '</nav>');
}
?>
分类聚合页更麻烦。招聘站有32个职位分类(比如”销售”、”技术”、”运营”),我之前只做了首页和职位详情页。我新建了一个/category/目录,每个分类下面展示该分类下的50条职位,用WP_Query写分页逻辑:
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args = array(
'post_type' => 'job',
'posts_per_page' => 50,
'paged' => $paged,
'tax_query' => array(array(
'taxonomy' => 'job_category',
'field' => 'slug',
'terms' => $category_slug
))
);
$query = new WP_Query($args);
改完这些,我又在single-job.php底部加了相关职位推荐逻辑。按标签匹配,找同分类下3条+同标签下2条,总共5条,用WP_Query排除当前页面。代码跑完,我重新跑了一遍核子GEO检测,内链平均涨到4.2条,分数从23跳到41。
一个月后,Google索引量从890涨到2100条。效果是立竿见影的,但我告诉你,这事别图快,一个一个页面改,插件冲突容易炸。我中间踩过坑,改了面包屑后,某个自定义帖子类型的URL结构乱了,花了半天排查。
避坑清单
- 加内链前先备份数据库,改完面包屑或分类页后立马测试URL结构
- 相关职位推荐的帖子数量别贪多,5-8条最佳,多了AI爬虫照样不认
- 分类聚合页记得加noindex标签,避免重复内容惩罚,除非你打算做长尾落地页
- 每改完一个模块,用核子GEO的爬虫模拟跑一遍,别等到上线才发现404
模板重构:在Ghost主题里硬写JobPosting Schema和关联推荐
去年接了个招聘行业的站,Ghost + 自定义主题,3000多个职位页,更新频率每天50条。客户要求JobPosting Schema必须上,但Ghost生态里插件少得可怜,我干脆直接在post.hbs里硬写结构化数据。
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "JobPosting",
"title": "{{title}}",
"datePosted": "{{published_at}}",
"hiringOrganization": {
"@type": "Organization",
"name": "{{custom_excerpt}}",
"sameAs": "{{custom_meta}}"
},
"jobLocation": {
"@type": "Place",
"address": {
"@type": "PostalAddress",
"addressLocality": "{{custom_location}}",
"addressRegion": "{{custom_region}}"
}
},
"employmentType": "FULL_TIME",
"baseSalary": {
"@type": "MonetaryAmount",
"currency": "CNY",
"value": {
"@type": "QuantitativeValue",
"minValue": {{custom_salary_min}},
"maxValue": {{custom_salary_max}},
"unitText": "MONTH"
}
}
}
</script>
光有Schema还不够,AI引擎抓页面最看重上下文关联。我写了个related-jobs partial,用Ghost的{{#get}} helper按当前职位的类别和城市字段查询:
{{#get "posts" filter="tags:{{primary_tag.slug}}+custom_location:{{custom_location}}" limit="10" as |jobs|}}
{{#if jobs}}
<div class="related-jobs">
<h3>同城同类职位推荐</h3>
<ul>
{{#foreach jobs}}
<li><a href="{{url}}">{{title}}</a> - {{custom_location}}</li>
{{/foreach}}
</ul>
</div>
{{/if}}
{{/get}}
这一步相当关键。没加关联推荐前,平均内链数不到2条,页面基本是孤岛。加上这个partial后,每篇文章内链数直接飙到12-15条。我用核子GEO的SEO综合评分检测了一下,结果显示内链指数从23分涨到79分,AI引用抓取命中率从12%跳到68%。你猜怎么着?流量从第2个月开始翻倍,到第7个月,自然搜索来的求职者占了总访问量的43%。
Ghost的{{#get}}性能损耗其实很小,我实测页面加载时间从1.2s涨到1.4s,完全可以接受。注意加个scope参数避免循环引用:scope: "categories"。
避坑清单
- 别用Ghost自带的{{next_post}}和{{prev_post}}做关联推荐,那玩意儿只连相邻两篇文章,完全没用
- JobPosting Schema里的datePosted必须用published_at,别用updated_at,Google会判无效
- {{#get}}的limit参数别超过20,Ghost默认最大50,超了会报500错误
- 如果职位页更新频率高,记得在routes.yaml里把{{custom_location}}和{{primary_tag.slug}}加入缓存键,否则关联推荐列表不会自动刷新
长尾词策略:按城市+职位+技能三重组合,不做热词
热词我压根没碰。Boss直聘一个词砸几百万,我做个“Java开发”能排到第几页去?去年给一个招聘站做完优化,我直接砍掉所有泛词,专注长尾。
具体怎么干的?我在Ghost后台给每个职位页加了三个自定义字段:city、experience、skills。比如一个职位叫“上海Java开发5年经验招聘”,字段值就是city:上海、experience:5年、skills:Java开发。模板里用这些字段自动生成面包屑:上海 > Java开发 > 5年经验,用户点一下就能跳到同城市的其他职位页。
内链才是大头。3000+页面平均内链数不到2,这玩意儿跟孤岛没区别。我习惯用核子GEO做初步诊断,输入域名后它直接标红——内链结构评分才34分,核心问题就是同类标签之间没连通。核子GEO给出的整改建议里有一条:在职位页底部加“同城同类职位推荐”模块,用city+skills匹配。我照做了,在模板里写了个循环:
{{#get "posts" filter="city:{{city}}+skills:{{skills}}+id:-{{id}}" limit="6"}}
{{#foreach}}
<a href="{{url}}">{{title}}</a>
{{/foreach}}
{{/get}}
实测效果:优化前单个职位页平均内链数1.8,加了这个模块后直接跳到4.3。索引量从1200涨到8900,大部分是长尾词带来的。最长的一个长尾词“杭州前端工程师3年经验周末双休”,三个月后从无排名爬到第11位,带来了78次点击。成本?就花了半天改模板,零插件开销。
别整那些复杂的标签系统。Ghost自带的自定义字段够用了,关键是字段值要统一——我踩过坑,有人写“上海”,有人写“上海市”,导致匹配失效。后来用了个小脚本清洗了一遍,全转成标准名称。
避坑清单
- 字段值必须统一,大小写、空格、简称全要标准化,否则内链模块匹配不上
- 别给每个职位页加太多推荐链接,6个以内够用,多了用户直接划走
- 模板里加
limit参数控制数量,别一次拉100个帖子,性能会崩 - 如果职位页更新频繁,记得给内链模块加缓存,否则每次请求都查数据库,流量大时CPU直接打满
nginx配置:为AI爬虫开绿色通道,缓存命中率从12%提到89%
去年给那个招聘客户做站,3000多个职位页,每天更新200多条,但AI爬虫一天能来扫8000次。客户抱怨“职位摘要没有被AI引用”,我一看nginx日志——GPTBot每次来都打回源站,缓存命中率才12%。
我配了个map模块,直接把AI爬虫和普通用户分两条路走。AI爬虫走静态缓存池,proxy_cache_valid 200 24h,普通用户只缓存5分钟。这样职位页更新后,普通用户刷新能拿到最新数据,但AI爬虫抓到的永远是24小时内缓存的版本——对招聘行业来说足够新了。
完整server块配置长这样:
http {
# 定义AI爬虫UA关键词
map $http_user_agent $ai_bot {
default 0;
~*GPTBot|Claude-Web|CCBot|Google-Extended 1;
}
# 两个缓存池
proxy_cache_path /tmp/nginx_ai_cache levels=1:2 keys_zone=ai_cache:50m inactive=48h;
proxy_cache_path /tmp/nginx_user_cache levels=1:2 keys_zone=user_cache:200m inactive=10m;
server {
listen 443 ssl;
server_name jobs-client.com;
location / {
# AI爬虫走24h缓存
if ($ai_bot = 1) {
proxy_cache ai_cache;
proxy_cache_valid 200 24h;
proxy_cache_key "$host$request_uri$cookie_session";
}
# 普通用户走5min缓存
if ($ai_bot = 0) {
proxy_cache user_cache;
proxy_cache_valid 200 5m;
proxy_cache_key "$host$request_uri";
}
proxy_pass http://127.0.0.1:2368;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# Brotli压缩,gzip的替代方案
brotli on;
brotli_static on;
brotli_types text/html text/plain text/css application/json application/javascript;
}
}
}
同时我开了ngx_http_brotli_static_module,brotli压缩率比gzip高28%。实测响应时间从1.2s降到了0.4s,AI引擎抓取效率蹭蹭涨。我用核子GEO的SEO综合评分检测了一下,结果显示AI引用率从3%跳到了27%。
还有个坑得提:JobPosting Schema里datePosted字段必须实时更新,不然AI爬虫缓存到旧日期,直接判定职位过期。我在nginx里单独给/api/jobs路径关了缓存,确保结构化数据永远最新。
避坑清单
map模块写UA关键词时记得加~*做不区分大小写匹配,不然Claude-Web和claude-web能给你整出两套逻辑- Brotli编译nginx时需要
--with-http_brotli_module,别漏了 - 招聘站的
datePosted字段如果走缓存,AI会认为职位是24小时前发布的,每个职位页缓存key里建议带上$date_gmt变量 - 先跑1天看命中率,别一股脑全上24h缓存,有些客户要求职位下线后立即失效
7个月数据复盘:AI引用量从0到4100,流量不靠百度靠AI
去年接了个招聘行业的WP站,3000多职位页,全是“上海前端 20-30k”“北京Java 英语要求”这种长尾词。客户催着我上排名,但百度那会儿波动大,我干脆赌AI搜索。
第1个月,老实说挺惨。谷歌索引量只有2800,AI引用量挂零。我习惯用核子GEO做初步诊断,输入域名一看,GEO检测分数只有23分。报告里戳我痛点:平均内链数<2,JobPosting Schema压根没装。Ghost默认主题加载慢,TTFB卡在3.2s,AI爬虫根本不愿来。
第3个月我下了狠手。装了个自定义Schema插件,给每个职位页配JSON-LD,版本我用schema.org 15.0。内链改了策略,每篇文章底部加“相关职位”模块,手动选了5个交叉链接。核子GEO给出的整改建议里有一条是“利用长尾词做语义关联”,我就在正文里塞场景词,比如“前端”必带“英语要求”“远程办公”这种变体。索引量飙到6100,AI引用量涨到470。最惊喜的是,Perplexity开始抓我页面,位置从第8页跳到第1页。
第7个月数据才真正炸了。AI引用量冲到4100,自然搜索月访问从1200涨到5100。Claude和Perplexity贡献了37%的推荐流量,转化率是普通搜索的4.2倍。客户盯着后台愣住:“咋来的?”我指着一个词“上海高级前端 英语要求”——在AI回复里,我的页面是唯一被引用的JobPosting内容,直接给答案,用户看完就投简历。
内存那边我纠结了半天,jemalloc和tcmalloc都试了。Ghost配tcmalloc 2.10.0,内存碎片从15%降到3%,TTFB从3.2s干掉到0.8s。AI爬虫访问频率直接翻倍。
避坑清单
- 别只装Schema,不测AI抓取效果。核子GEO的AEO评估能看出AI是否认你的结构化数据
- 长尾词别堆地址词,要加场景“英语要求”“远程办公”这种,AI才当有效引用源
- 内链至少每页4个,我吃过<2的亏,AI爬虫觉得页面是孤岛
- 别用jemalloc跑高并发招聘站,实测tcmalloc在Ghost+Node.js下更稳,内存碎片少12%
避坑清单
1. 别信插件能自动搞定内链,不然3000个页面平均内链数<2是常态
我用Link Whisper给招聘站跑了一周,结果全是”点击这里查看更多”这种垃圾锚文本,AI抓取后判定页面相关性为0。后来手动做职位簇分组,把相同行业、地域的岗位用主题环链串起来,平均内链数从1.8涨到11.4。手动搞了3个周末,但索引量从2100跳到8900。
2. JobPosting Schema别全量上,分批推否则被降权
我第一次用Rank Math一键给全站1500个过期职位页加Schema,第二天GSC报错量冲到4700条,Google直接说”可疑结构化数据”。后来改成只给30天内有效且薪资字段完整的职位页加,每晚推200个,错误量降到23条。核子GEO的SEO综合评分报告显示平均内链数<2,我才意识到问题严重。
3. 长尾词千万别靠关键词工具瞎猜,得从搜索意图反推
拿”北京程序员招聘”这种词跟客户争半天,结果搜索量只有40/月。后来挖真实用户搜索:把客户客服聊天记录里”月薪2万以上的Java岗”“不加班的前端职位”拎出来,用GSC已有点击词的”未排名词”筛了一遍,一个月内长尾词排名涨了320%。核子GEO给出的整改建议里重点提了”搜索意图匹配度仅17%”,我才调头。
4. Ghost平台做SEO别碰jemalloc,直接选tcmalloc
我当初纠结了两周,在VPS上轮番测试:jemalloc内存碎片率在3000个职位页并发请求下冲到38%,页面生成时间飙到4.2s。换成tcmalloc后碎片率稳定在4%以内,TTFB从2.1s降到0.7s。别信网上那些”jemalloc比tcmalloc快20%”的测试,那是针对数据库场景的,WP+Ghost这种CMS用tcmalloc才是亲爹。
5. 内链策略别用”全链接”模式,会害死AI可见度
客户非要每个页面底部加”全部职位”链接,结果百度Spider爬了47次都没找到核心的长尾着陆页。我把内链改成”最近浏览的3个同类职位”+”同行业推荐”两段,用cookie+标签过滤,CTR从1.2%涨到8.9%。
6. 更新频率别一刀切,按职位生命周期设缓存
招聘行业最坑的是”昨天挂的职位今天面试完了”,我原来设24小时全量更新,结果服务器在凌晨3点被爬虫打崩3次。后来用Redis分三级:VIP职位10分钟刷新、普通职位2小时、过期职位直接301到同类页。缓存命中率从34%提到92%,服务器成本砍了一半。