デプロイパイプラインにSEO監査を組み込む:API、終了コード、CIレシピ
CIからサイトを監査する実用的なレシピ:3つのRESTエンドポイント、ビルドゲートが読み取れるスコアフィールド、実際の回帰とインフラのブリップの違い.
視認性を最も失う技術的回帰は、コードレビューでは見えない. 誤ったホストを指すcanonicalタグ、自己参照を失うhreflangブロック、リバースプロキシ設定から削除されたContent-Security-Policyヘッダー、ハイドレーションの背後にコンテンツを移動させるルート―それらのすべては見た目が良く、すべてのテストに合格するdiffに乗って出荷される. それらは数週間後に、トラフィックチャートで表面化し、原因となったコミットから長い時間が経ってスクロールアウトした後に現れる. 修正は構造的である:誰かが思い出す日ではなく、デプロイ時に監査を実行する. すべてのSEOReportレポートはRESTで利用可能で、レスポンスは数値スコアブロックを持ち、シェルスクリプトはそのブロックを終了コードに変換できる。 それが全体の仕組みである。
機械が時間通りに検出する4つの回帰クラス
当社のエンジンのチェックは、人間のレビューで生き残る失敗モードにきれいにマッピングされており、具体的に名前を付ける価値がある。なぜなら、それらが実際にゲートが保護しているものだからだ.
Hreflang。 チェックセットは自己参照、リターンリンク、x-defaultの正確性、正しく形成されたURL、各代替ターゲットがインデックス可能か、ターゲットのcanonicalが合致しているかをカバーする。 CMS移行でURLパターンを書き換えると、すべてのロケールでリターンリンクが壊れ、個別に見ると壊れているように見えない。
Canonical化。 存在、ターゲットのインデックス可能性、リダイレクトフリーターゲット、オフサイトcanonical. この失敗の最悪のバージョンは、本番に出荷されたステージングcanonicalである ― 静かにインデックスしたくないホストを指名するページ.
セキュリティヘッダー。 Content-Security-Policy、HSTS、Referrer-Policy、X-Frame-Options、X-Content-Type-Options、Permissions-Policy. これらはインフラ構成に存在し、アプリケーションコードにはないため、プロキシやエッジ構成の変更時に消え、誰も気づかない正しい理由だ.
レンダーパリティ。 すべての監査はホームページを2回取得する ― プレーンHTTP、次に実際のブラウザ ― そしてタイトル、H1、canonical、メタディスクリプション、JSON-LD、本文テキスト量を2つで比較する。 公開されたレンダーパリティデータが判断に達したとき、ほとんどのサイトはHTMLとして配信されたものを読むすべてに対して実質的に薄いページを提供していた。 設定ファイルのssr: false1つでサイトをそのグループに移動させるだけで十分だ。
4つすべてが決定論的で、すべてが安価にチェックでき、すべてが疑わしいときにのみ人が検査する種目である.
3つのエンドポイントと1つのループ
APIが表面化するパイプラインは小さい。 認証はベアラートークン:アカウントを作成し、ダッシュボードからキーを発行し、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 で特に重要なのは、ボディに関する 2 つの点です.
forceRerun は、API が既存のスナップショットを再利用するために存在します。ボタンをクリックする人にとっては合理的ですが、デプロイゲートには不適切で、そうしないと前回のリリースが評価されてしまいます。 応答は submission.reusedSnapshot で何が起こったかを教えてくれます。 強制的な新規実行は有料アカウント機能です。該当権限のないキーは、理由を示す 403 を返し、静かに古いデータを返すことはありません。
監査範囲は URL パスから推定されます。 ベアオリジンはフルサイト監査を実行します。パス付きの URL は、そのページを単独で監査します。 したがって、パイプラインは毎回デプロイ時にホームページをゲートし、変更が触れた特定のルートを追加できます。追加パラメータは不要です.
その後 poll. 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か月以内に無効化される. それらを終了コードで分ける:ゲートに強制させた判定には 1、判定がまったく出なかった実行には 75 ― 通常の EX_TEMPFAIL ― を使用する。 ほとんどの CI システムは、2 回目を再試行し、1 回目は人間に通知するように設定できる.
スコアブロックを読む
ready が true になると、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}'
そのフィールドのうち 3 つがほとんどの信号を担う.
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 は同じオブジェクトをダウンロード可能なアーティファクトとして返す ― 2 つのデプロイ間の差分を後で検査できるようにビルドに添付する価値がある。
ワークフローへの組み込み
上記は CI ベンダー固有ではない。 GitHub Actions では、ゲート全体が既に持っているスクリプトを呼び出す 1 つのステップで構成される。
- 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 を報告します。 本番オリジンに対するデプロイ後は、クローラーが体験するものに近く、よりシンプルです.
隣接する2つの形状を知っておく価値があります. あなたのオーケストレーションがすでにスクレイピングプラットフォーム上にある場合、our Apify actor はこの接着剤なしで同じエンジンをスケジュールで実行します. エージェントの場合、同じベアラーキーがhttps://seoreport.dev/mcp で MCP 接続を認証し、レポートツールは connect で広告されます — トラフィック低下を調査するエージェントは監査を実行し、発見を自分で読むことができ、これは REST サーフェスとともに developers page に記載されています。
ゲートがカバーしないこと
デプロイゲートは1つの質問に答えます:このリリースは回帰を導入しましたか. デプロイなしで変わるすべてのものについては黙っています — 期限切れ証明書、ダッシュボードで編集されたCDN 設定、レンダリングをブロックし始めるサードパーティスクリプト、あなたの正規URLと衝突する競合他社の移行。 ドメイン単位の監視はゲートの常時オン補完で、同じアカウントと同じキーから読み取ります developers page に記載されています.
狭いバージョンから始めて. 1つのエンドポイント、1つのフィールド、failingCriticalChecks > 0、監査が全く実行できなかったときの正直なexit 75。 年に2回発火し、両方の回で信頼されるゲートは、誰もがスキップするようになった包括的なものより価値があります.
サイトのランキングを確認する
アクション可能な発見と優先修正を含む無料のAI搭載SEOレポートを取得
サインアップ不要.