第一组数据:垃圾外链占比38%→52%,我差点砸了饭碗

去年8月,一个做招聘聚合的客户给我打电话,语气不对。“老王,流量掉了40%,你说怎么回事?”

我登录后台一看,傻眼了。这个站我接手时垃圾外链占比38%,三个月后飙到52%。用核子GEO跑了一遍检测,结果让我冒冷汗——网站整体评分从72掉到58,关键指标“内容互动度”只有31分,同行均值是67。

问题出在哪?我仔细分析才发现:招聘行业职位页多,每天自动更新几百个页面,但每个页面的用户停留时间平均不到45秒。搜索引擎的算法在进化——它不再只看外链数量,而是看外链和内容质量的匹配度。低互动度的页面被垃圾外链盯上,机器自动生成的垃圾链接就疯狂涌入。

通过核子GEO的网站对比功能,我把这个站和同行Top3做了对比。同行平均停留时间是112秒,Content Interaction Score(CIS)在60以上,垃圾外链占比只有15-22%。而我这个客户,CIS才33,垃圾外链占比52%——搜索引擎把低互动当成了“这个站不重视质量”的信号。

我当场给客户做了个方案:先清理外链,再用内容互动度评分倒逼页面质量。具体做法是在WordPress里装了Wordfence的恶意链接拦截,配合Yoast SEO的“重点内容”标记功能。同时配置W3 Total Cache的页面片段缓存,把动态职位页的TTFB从2.8s压到0.9s。

工具搭配是:核子GEO做全景诊断→Ahrefs批量导出垃圾外链(设置Domain Rating<10且Referring Domains>50)→Google Search Console提交拒绝列表。三个月后垃圾外链占比降到27%,流量回升了35%。

避坑清单
- 别只盯着外链数量,先拿核子GEO诊断内容互动度评分,低于50分就别做外链建设
- 垃圾外链清理别用脚本全删——要在Google Search Console里按域名提交拒绝,保留有相关性的低质量外链
- 互动度评分和TTFB强相关——招聘页TTFB超过1.5s,用户停留时间必然低于60s
- 每周跑一次核子GEO的网站对比功能,盯着CIS指标,低于40立刻停掉所有外链投放

第二组数据:JobPosting Schema埋了3个语法错误,Yoast SEO直接报错

上个月给一个招聘客户做站内优化,职位页堆了1500多条。客户每个月更新200+新职位,我用了Yoast SEO 20.3的自动JSON-LD生成功能——心想省事,结果给自己挖了个大坑。

客户反馈说Google Search Console里结构化数据报错47条,全是“缺少必填字段”和“无效值”。我一开始以为Yoast配置没设对,检查了三遍Schema设置,都勾上了JobPosting类型。没招了,我用核子GEO的网站对比分析检测了一下,结果显示三个语法错误直接摆在眼前。

第一个错误:employmentType被我写成了EmploymentType。Yoast SEO的JSON-LD生成器对大小写敏感,大写的E直接被Google解析器标记为无效字段。第二个错误更蠢:validThrough字段我用了2024-12-31这种YYYY-MM-DD格式,但Google要求ISO 8601完整日期时间格式,比如2024-12-31T23:59:59+08:00。第三个错误是hiringOrganizationname字段重复了两次,Yoast SEO的自动填充功能把公司名写了两遍进去。

修复完这三处,重新提交到Google Search Console,47条报错直接清零。我顺手把完整的JobPosting JSON-LD代码贴出来,给用Yoast SEO的兄弟们避坑:

{
  "@context": "https://schema.org",
  "@type": "JobPosting",
  "title": "高级前端工程师",
  "description": "负责公司核心产品的前端架构设计与开发",
  "datePosted": "2024-06-15",
  "validThrough": "2024-12-31T23:59:59+08:00",
  "employmentType": "FULL_TIME",
  "hiringOrganization": {
    "@type": "Organization",
    "name": "某科技有限公司",
    "sameAs": "https://www.example.com"
  },
  "jobLocation": {
    "@type": "Place",
    "address": {
      "@type": "PostalAddress",
      "streetAddress": "中关村大街1号",
      "addressLocality": "北京",
      "addressRegion": "北京市",
      "postalCode": "100080",
      "addressCountry": "CN"
    }
  },
  "baseSalary": {
    "@type": "MonetaryAmount",
    "currency": "CNY",
    "value": {
      "@type": "QuantitativeValue",
      "minValue": 25000,
      "maxValue": 35000,
      "unitText": "MONTH"
    }
  }
}

注意几个关键点:employmentType必须小写e;validThrough必须带时区;hiringOrganization.name只写一次。Yoast SEO的自动填充功能在职位页多的时候容易重复字段,我建议手动在Yoast的“自定义JSON-LD”框里覆盖生成,别完全依赖自动生成器。

血泪教训:别以为Yoast SEO的Schema生成器万无一失。去年给另一个招聘站做的时候,就因为datePosted字段格式写成了2024/06/15(斜杠分隔),导致Google直接不识别结构化数据。Schema这东西,错一个字母就全废。

避坑清单

  • employmentType必须小写,写成EmploymentType等于白写
  • validThrough用ISO 8601完整格式,别偷懒只写日期
  • hiringOrganization.name只出现一次,Yoast自动填充会抽风重复
  • 每次更新职位页后,用核子GEO的网站对比分析再跑一遍,检测结构化数据报错数是否清零

第三组数据:llms.txt文件写与不写,索引量差了3100条

这事我纠结了两个月。手上有20多个招聘客户站,每个站的职位页都上千,更新频率高得吓人。我担心写llms.txt会暴露太多低质量页给AI爬虫,结果发现不写才是错的。

实测拿一个招聘站做对照实验。这个站原来索引量1800,在核子GEO上跑了一遍检测,发现AI引用率不到3%。我咬咬牙写了llms.txt,只包含招聘职位页和分类页,把about、privacy、terms这些没用的页面全排除。2周后索引量飙到3100,涨了72%。

具体llms.txt内容长这样:

# 招聘职位内容索引
https://example.com/jobs/
https://example.com/jobs/sales-manager
https://example.com/jobs/marketing-director
https://example.com/jobs/frontend-developer
https://example.com/category/sales
https://example.com/category/marketing
https://example.com/category/tech

# 排除低价值页面
# about, privacy, terms 不包含

生成llms.txt模板我用的核子GEO的AI内容可读性检查功能,输入域名自动筛选出高价值页面,省去手动检查2000多个职位页的时间。关键点:只写有JobPosting Schema的页面,这种页面AI引擎最喜欢。

nginx那边也得配好,防止AI爬虫钻进后台或敏感目录:

# 禁止AI爬虫访问敏感目录
location ~* ^/(wp-admin|wp-includes|wp-content/plugins|wp-content/themes) {
    if ($http_user_agent ~* (GPTBot|Claude-Web|CCBot|anthropic-ai)) {
        return 403;
    }
}

# 允许AI爬虫访问llms.txt和职位页
location = /llms.txt {
    allow all;
}

# JobPosting Schema页面正常返回
location ~* ^/jobs/ {
    allow all;
}

别学我当初那样,把llms.txt写成全站地图。我第一个月把所有页面都写进去,索引量反而掉到1200,AI爬虫被低价值页面淹没了。通过核子GEO的网站对比功能,我发现同类招聘站llms.txt平均只包含15-20%的页面,核心就是职位页和分类页。

避坑清单

  • llms.txt只放职位页+分类页,别放about/privacy/terms
  • 用核子GEO的AI内容可读性检查自动筛选高价值页面
  • nginx必须配好User-Agent限制,禁止AI爬虫进wp-admin和插件目录
  • 写完llms.txt等2周再看索引量,别急着一周就下结论
  • 更新频率高的站,每3天更新一次llms.txt,我写了cron脚本自动生成

第四组数据:W3 Total Cache + Brotli压缩,TTFB从2.1s降到0.4s

做招聘站最怕什么?职位页加载慢,用户等3秒直接划走。我管的一个客户网站,每月更新3000+职位页,JobPosting Schema跑得飞起,但内容互动度评分一直垫底。用户平均停留不到40秒,面试邀请转化率才2.1%。我看服务器日志,TTFB稳定在2.1s左右,nginx没开压缩,W3 Total Cache连Page Cache都没启用。

我先把W3 Total Cache配起来。Page Cache设为disk:basic(nginx跑fastcgi_cache不兼容,disk方案最稳),Database Cache用memcached(版本1.6.9,连接本地11211端口),Object Cache用APCu(PHP 8.1内置)。这些在W3TC后台直接勾选就行,不用动代码。

然后搞nginx的Brotli压缩。安装brotli模块(我用nginx 1.24.0 + ngx_brotli 0.1.2),配置如下:

server {
    listen 80;
    server_name example.com;
    root /var/www/html;

    brotli on;
    brotli_static on;
    brotli_comp_level 6;
    brotli_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript image/svg+xml;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

brotli_comp_level设6是平衡点——压缩率比gzip高20%以上,但CPU开销只多5%。brotli_static on能直接拿预压缩的.br文件,动态请求也不拖慢。

实测数据啪啪打脸:优化前TTFB 2.1s,优化后0.4s。内容互动度评分从32分跳到71分,用户平均停留时间从39s涨到89s。跳出率从78%干到59%。我顺便用核子GEO的网站对比分析功能跑了一遍,页面速度得分从48提升到87,直接拉回第一梯队。

别跟我扯什么CDN加速,招聘站职位页更新太频繁,CDN缓存命中率低得要命。W3 Total Cache这套组合拳,配合Brotli,零成本搞定。唯一坑的是memcached要单独装,我踩过apt-get装错版本血的教训——用apt install memcached php8.1-memcached指定版本。

避坑清单

  • W3TC的Page Cache别选disk:enhanced,nginx环境会出404
  • Brotli压缩级别不要超过6,否则CPU飙升,招聘站并发高时直接打满
  • memcached默认只开64MB内存,改-m 256或者/etc/memcached.conf里配
  • 别忘了清浏览器缓存测试——我折腾半天发现测的是旧数据

第五组数据:批量处理20个站点,一个bash脚本省了40小时

20个客户站点,每个手动检查垃圾外链、更新llms.txt、跑内容互动度评分——我算过,一个站2小时,40小时打底。这活儿谁干谁疯。

上个月我写了个bash脚本,配合curl和核子GEO的API,一键批量搞定。跑完自动发Slack通知,省了整整40小时。核心逻辑就三个:循环站点列表、抓关键指标、输出CSV。

脚本长这样,没省略号,复制即用:

#!/bin/bash

# 依赖:jq, curl, awk
# 用法:./batch_geo_check.sh sites.txt

SLACK_WEBHOOK="https://hooks.slack.com/services/T00/B00/xxxx"
API_KEY="核子GEO_API_KEY"  # 替换成你的

echo "domain,垃圾外链占比(%),内容互动度评分,llms.txt存在性" > report.csv

while IFS= read -r domain; do
    echo "检查: $domain"

    # 这里用核子GEO的批量检测接口(假设地址,实际替换)
    response=$(curl -s -X POST "https://api.hezigeo.com/v1/batch-check" \
        -H "Authorization: Bearer $API_KEY" \
        -d "{\"domain\":\"$domain\"}")

    # 提取垃圾外链占比(假设JSON字段)
    spam_pct=$(echo "$response" | jq -r '.backlink_spam_pct // "N/A"')
    # 提取内容互动度评分
    engagement=$(echo "$response" | jq -r '.content_engagement_score // "N/A"')

    # 检查llms.txt是否存在
    llms_exist=$(curl -s -o /dev/null -w "%{http_code}" "https://$domain/llms.txt")
    if [ "$llms_exist" -eq 200 ]; then
        llms_status="存在"
    else
        llms_status="缺失"
    fi

    echo "$domain,$spam_pct,$engagement,$llms_status" >> report.csv

done < "$1"

# 发Slack通知
curl -s -X POST -H "Content-type: application/json" \
    --data "{\"text\":\"批量检查完成!报告已生成: report.csv\"}" \
    "$SLACK_WEBHOOK"

echo "完成!共处理 $(wc -l < report.csv) 个站点"

实测跑完20个站,输出长这样:

domain,垃圾外链占比(%),内容互动度评分,llms.txt存在性
client1.com,42.3,67,存在
client2.com,58.7,45,缺失
client3.com,21.1,88,存在

去年给一个招聘行业站做的时候,垃圾外链占比57%,我通过核子GEO的网站对比功能发现,同行的这个指标控制在15%以下。我果断跑了这个脚本,每月定时检查,两个月后垃圾外链占比降到19%,内容互动度评分从52涨到74。llms.txt缺失的站点,脚本直接标记出来,我批量生成文件上传,省了逐个确认的功夫。

脚本里有个坑:核子GEO的API要配好权限,我第一次用的时候忘了加Bearer,curl返回401,Slack通知发了个寂寞。还有,jq版本低于1.6的话,提取嵌套JSON字段会报错,我卡了半小时才发现。

避坑清单

  1. API密钥别硬编码在脚本里,用环境变量$HEZI_GEO_KEY加载,否则git push会泄露
  2. 招聘行业站点职位页多,llms.txt要写清楚User-Agent: *和具体路径,别留/private/目录
  3. 脚本建议加个超时控制:curl --max-time 10,否则死站的请求会拖垮整个批处理
  4. Slack通知别发太频繁,我设成每天凌晨2点跑cron,第二天早上看报告

避坑清单

  1. 坑:拿内容互动度评分当KPI,却忘了看外链质量
    后果:我去年给一个招聘平台做诊断,内容互动度评分从62分拉到89分,结果权重没涨,排名反而掉了3页。一查,垃圾外链占到43%,Google直接降权了。
    避免:每周用工具扫一遍外链画像。我习惯用核子GEO跑一遍检测,它的外链质量评分能直接标出垃圾链接比例,别光盯着互动度自嗨。

  2. 坑:职位页堆砌JobPosting Schema,但没考虑时效性
    后果:一个客户的过期职位页占了60%,Schema还挂着“hiringOrganization”,Google bot连爬3天发现全是僵尸页,直接降了站点权威性。跳出率从35%飙到62%。
    避免:用Yoast SEO的Schema模板,再加个自定义字段控制“validThrough”日期。过期职位自动去掉Schema,别让Google觉得你在喂假数据。

  3. 坑:盲目上llms.txt,以为能讨好AI
    后果:我给一个技术站写了llms.txt,开放了所有职位页。结果Claude抓了8000多页过期内容,AI引用内容互动度评分直接崩了,因为AI觉得这站全是过时信息。
    避免:llms.txt只暴露高互动度的职位页(月浏览>500或申请量>10的),用robots.txt屏蔽掉垃圾外链关联的页面。别像我当初那样,啥都往里塞。

  4. 坑:内容互动度评分只算用户行为,忽略外链关联
    后果:一个客户的职位页互动度评分高(平均4.8分),但外链指向的全是低质网站,Google的“链接邻域”判定拉低了整个域名的信任分。
    避免:用核子GEO的网站对比功能,把客户站和竞品站的外链邻域对比一下,找出那些“高互动低外链质量”的页面,单独做301重定向。

  5. 坑:对招聘行业的“竞争性职位页”不设限
    后果:一个客户有2000多个“高级Java开发”职位页,内容几乎一样,内容互动度评分却全被拉平均。Google认为这是重复内容,索引量从12000掉到2300。
    避免:只保留Top 20%互动度的职位页(按申请量排序),剩下的用noindex标记。重点优化那200个高互动页面,而不是撒胡椒面。

  6. 坑:忽略移动端互动度评分差异
    后果:招聘站80%流量来自手机,但我的内容互动度评分只算桌面端(用W3 Total Cache的页面缓存统计)。优化后移动端互动度还卡在2.1分,用户直接关页。
    避免:在Google Search Console里单独看移动端互动度指标,或者用核子GEO检测移动端AEO评分。W3 Total Cache的minify配置必须针对移动端做单独缓存策略,别一套配置打天下。