在部署管道中加入 SEO 审计:API、退出码与 CI 配方
一个可用的 CI 审计配方:三个 REST 端点,构建门可读取的分数字段,以及真实回归与基础设施波动的区别.
造成最大可见度损失的技术回归在代码审查中是不可见的. 一个 canonical 标签指向错误主机,一个 hreflang 块失去自引用,一个 Content-Security-Policy 头从反向代理配置中被删除,一个路由将其内容移至水化后——这些都在看似正常的差异中被打包并通过你所有的测试. 它们在数周后才显现,在流量图中,远在导致它们的提交滚动出视图后才出现. 解决方案是结构性的:在部署时运行审计,而不是等有人记得时. 每个 SEOReport 报告可通过 REST 访问,响应携带一个数值分数块,shell 脚本可以将该块转换为退出码。 这就是整个机制.
四类回归只有机器能及时捕捉
我们引擎的检查与人类审核中存活的失败模式一一对应,值得具体命名,因为它们正是门实际在保护的内容.
Hreflang。 检查集涵盖自引用、返回链接、x-default 正确性、格式良好的 URL、每个替代目标是否可索引,以及目标的 canonical 是否一致。 CMS 迁移重写 URL 模式可能一次性破坏所有语言的返回链接,且单独查看时任何语言都看不出问题。
Canonicalization。 存在性、目标可索引性、无重定向目标以及站外 canonical. 这种失败的最糟版本是将预发布 canonical 推送到生产——一页悄悄地将你不想被索引的主机列为目标.
安全头。 Content-Security-Policy、HSTS、Referrer-Policy、X-Frame-Options、X-Content-Type-Options 与 Permissions-Policy. 它们存在于基础设施配置中,而非应用代码,这正是它们在代理或边缘配置更改时消失且无人注意的原因.
渲染一致性。 每次审计都会两次获取首页——一次纯 HTTP,一次真实浏览器——并比较标题、H1、canonical、meta 描述、JSON-LD 与正文文本量。 当我们发布的 render-parity data 做出判断时,大多数网站向任何读取 HTML 的人提供的页面都明显更薄。 配置文件中的一个 ssr: false 就足以将网站移入该组。
四者皆为确定性、检查成本低且只有在已怀疑时才会被人检查的事物.
三个端点与一个循环
API 的表面需求对管道来说很小。 认证为 bearer token:创建账户,从 dashboard 发行密钥,并将其作为 Authorization: Bearer sr__live_your_api_key 发送。 同一密钥打开 REST 和 MCP;完整参考请参见开发者页面。
提交报告是一条 POST:
JOB_ID=$(curl -sS -X POST https://seoreport.dev/api/v1/reports \-H "Authorization: Bearer $SEOREPORT_API_KEY" \-H "Content-Type: application/json" \-d '{"url": "https://example.com", "forceRerun": true}' \| jq -r '.report.jobId')
在 CI 中,关于请求体的两件事很重要.
forceRerun 存在是因为 API 在有可用快照时会重用它——对点击按钮的人来说合理,但对部署门来说不合适,否则会评估前一次发布。 响应会告诉你在 submission.reusedSnapshot 中发生了什么。 强制全新运行是付费账户功能;没有该权限的密钥会收到 403,说明原因,而不是静默返回陈旧数据。
审计范围从 URL 路径推断。 一个裸起点会执行全站审计;带路径的 URL 只审计该页面。 因此管道可以在每次部署时对首页进行门控,并添加变更触及的具体路由,而无需额外参数.
然后轮询. GET /api/v1/reports/:id/ready 是廉价的状态端点——它返回 ready、status、stage、pollAfterMs,以及当运行失败时的 error 对象:
for _ in $(seq 1 60); doREADY=$(curl -sS -H "Authorization: Bearer $SEOREPORT_API_KEY" \"https://seoreport.dev/api/v1/reports/$JOB_ID/ready")CODE=$(echo "$READY" | jq -r '.error.code // empty')if [ -n "$CODE" ]; thenecho "audit did not complete: $CODE"exit 75fi[ "$(echo "$READY" | jq -r '.ready')" = "true" ] && breaksleep 5done
那个 exit 75 是有意为之,也是大多数集成最容易出错的部分。
区分回归与从未发生的运行
error.code 携带机器可读的原因和一个 retryable 布尔值。 DNS_FAILURE、CRAWLER_BLOCKED、REDIRECT_LOOP、TLS_ERROR、NO_CONTENT 和 STALE_ENGINE_VERSION 被标记为不可重试,因为重试会产生相同的答案。 该列表的大部分描述了站点上的条件,且其中几项——重定向循环、TLS 错误、现在阻止爬虫的机器人规则——是真正的部署缺陷,值得因其导致构建失败. 该集合之外的代码是瞬态的,值得再次尝试.
将“站点回归”与“审核无法运行”合并为同一红色构建的门将在一个月内被禁用. 在退出代码中将它们分开:1 用于你要求门执行的判决,75——传统的 EX_TEMPFAIL——用于完全没有判决的运行。 大多数 CI 系统可以配置为重试第二次并让人类处理第一次.
阅读分数块
一旦 ready 为真,GET /api/v1/reports/:id 返回报告对象。 score 块是门读取的部分:
REPORT=$(curl -sS -H "Authorization: Bearer $SEOREPORT_API_KEY" \"https://seoreport.dev/api/v1/reports/$JOB_ID")echo "$REPORT" | jq '.report.score| {overall, totalChecks, passedChecks, failedChecks,warnChecks, inconclusiveChecks, failingCriticalChecks}'
这三个字段携带了大部分信号.
failingCriticalChecks 是引擎将其视为关键的失败计数——那些能够从索引中移除页面或完全隐藏内容给爬虫的失败。 对于第一个门,这就是你需要的唯一数字,> 0 是第一天的可辩护阈值。
overall 是复合分数,作为闸门使用:存储前一次部署的值,并在新值下降超过你选择的容差时失败。 这捕捉了单个检查未标记的慢性侵蚀.
domainScores 按 seo、ai、performance、security 和 brand 将分数拆分,每个都有自己的 pass、fail 和 warn 计数。 每域最低值允许不同团队拥有不同预算——安全分数是一个有意义的门,供任何拥有边缘配置的人使用,独立于内容团队发布的任何内容.
inconclusiveChecks 值得自己的规则:永远不要以其为门。 当引擎无法得出可辩护的判决时,检查报告为不确定,并将其视为失败会训练每个人忽视门.
分数块来自报告的免费英雄部分,因此构建门读取它而不解锁完整发现. 当你想要完整负载进行归档时,GET /api/v1/reports/:id/result 返回解锁报告的完整结果,GET /api/v1/reports/:id/download?format=json 返回相同对象作为可下载的工件——值得附加到构建中,以便以后可检查两次部署之间的差异。
将其接入工作流
上述内容均非 CI 供应商特定. 在 GitHub Actions 中,整个门是一个调用你已有脚本的步骤:
- name: SEO audit gateenv:SEOREPORT_API_KEY: ${{ secrets.SEOREPORT_API_KEY }}AUDIT_URL: https://example.comrun: ./scripts/seo-gate.sh
当 seo-gate.sh 提交、投票并以决策结束时:
CRITICAL=$(echo "$REPORT" | jq -r '.report.score.failingCriticalChecks // 0')SECURITY=$(echo "$REPORT" | jq -r \'.report.score.domainScores[] | select(.domain == "security") | .score')if [ "$CRITICAL" -gt 0 ]; thenecho "::error::$CRITICAL critical checks failing"exit 1fiecho "clean — security domain at $SECURITY"
在部署完成后运行,而不是针对预览环境. 预览 URL 通常需要基本身份验证或机器人挑战,而无法获取页面的审计会报告 CRAWLER_BLOCKED 而不是分数。 部署后针对真实源是更简单且更接近爬虫体验的.
两个相邻的形状值得了解. 如果你的编排已经托管在抓取平台上,our Apify actor 在计划中运行相同的引擎,而不需要任何此类粘合. 对于代理,使用相同的 bearer key 在 https://seoreport.dev/mcp 处验证 MCP 连接,报告工具在 connect 上公布——一个调查流量下降的代理可以自行运行审计并阅读发现,这些内容与 开发者页面 上的 REST 表面一起记录。
门控不涵盖的内容
部署门回答一个问题:此版本是否引入了回归. 它对所有不通过部署而发生的更改保持沉默——过期证书、在仪表盘中编辑的 CDN 配置、开始阻止渲染的第三方脚本、竞争对手的迁移导致你的规范冲突的变化。 每域监控是门控的始终开启补充,并且读取与 开发者页面 上描述的相同账户和相同密钥.
从窄版本开始. 一个端点,一个字段,failingCriticalChecks > 0,以及当审计根本无法运行时的诚实 exit 75。 每年触发两次且两次都被信任的门比每个人都学会跳过的全面门更有价值.
查看您的网站排名
获取一份免费的 AI 驱动的 SEO 报告,包含可操作的发现和优先修复建议,帮助提升您的网站。
不需要注册。.