seo-drift について
seo-driftは、ドメインやページを監視するためのSEOスナップショット比較スキルです。基準スナップショットを保存し、変更や悪化を示して、過去の記録も一覧できます。
主な機能
- 01ドメインまたはURLの基準取得
- 02現在の状態と基準の比較
- 03重要度別のSEO変化検出
- 04過去のスナップショットと指標一覧
- 05ページ情報とGoogle実測データの任意取得
活用シーン
- 01デプロイ後のSEO悪化の確認
- 02ページのSEO項目の変更監視
- 03ドメイン指標の経時確認
MCP 対応
SEOデータの取得にはSE Ranking MCP サーバーが必要です。任意でFirecrawl MCPからページメタデータを取得し、Google APIで実測データやインデックス状態のスナップショットを記録できます。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ seranking/ seo-skills --skill seo-driftインストール後、Claude Code で/seo-driftを入力して読み込まれたか確認します。
同梱ファイルreferences/drift-thresholds.md
詳細
出力例:examples/seo-drift-wix-com-20260514/compare/DRIFT-REPORT.md
SEO Drift
SEO のための Git です。ドメインまたは URL の SEO 状態のスナップショット(「ベースライン」)を取得し、以降の実行時に現在の状態とベースラインを比較して、劣化を検出します。デプロイ、リニューアル、コンテンツ削除後に、気づかないうちに悪化する問題を検出します。
謝辞: SEO スキルとしての drift フレームワークは、AgriciDaniel による
claude-seoで生まれました(元のコンセプトは Dan Colta と Pro Hub Challenge に帰属します)。どちらも MIT ライセンスです。この実装は独自のものですが、枠組みは同氏らのものです。
前提条件
- SE Ranking MCP サーバーが接続されていること。
- Claude の
WebFetchツールが利用可能であること(URL モードでのページフィンガープリント取得に使用)。 - ユーザーが対象のドメインまたは URL と、サブコマンド(
baseline、compare、history)を指定すること。
オプションのフラグ
| フラグ | モード | 効果 |
|---|---|---|
--no-firecrawl | baseline, compare | Firecrawl がインストールされている場合でも、Firecrawl による <head> と JSON-LD の取得をスキップします(クレジットを節約できますが、canonical/robots/og:*/JSON-LD の差分を確認できる範囲が狭まります)。 |
--skip-cwv | baseline, compare | google-api.json が設定されている場合でも、Google CrUX の取得(ステップ 4b)をスキップします。コンテンツや構造の変化だけを確認したい場合や、CrUX のレート制限への懸念が CWV の確認よりも優先される場合に便利です。seo-drift/SKILL.md:107, 131 にある同氏らの設定に倣っています。 |
--baseline-id <n> | compare | 最新のベースラインではなく、ID を指定して特定のベースラインと比較します。 |
--limit <n> | history | 表示する履歴エントリーの件数を制限します。 |
サブコマンド
baseline <target>
現在の SEO 状態を取得し、スナップショットファイルに書き込みます。差分は生成されません。
compare <target>
対象の最新のベースラインを読み込みます。現在の状態を取得して差分を比較し、DRIFT-REPORT.md を生成します。
history <target>
保存されている対象のすべてのベースラインについて、日付と主要な指標(DA、トラフィック、キーワード数)を一覧表示します。差分は生成されません。
処理
baseline モード
- 対象を検証します。 ドメインか URL かを判定します。ドメインは
example.com、URL はhttp(s)://で始まるものです。- SSRF 対策(URL モード)。 対象が URL の場合は、
python3 -c "from scripts.google_auth import validate_url; import sys; sys.exit(0 if validate_url('{target}') else 1)"を使って検証します(または、ヘルパースクリプト内でvalidate_urlを直接インポートします)。ループバック(127.0.0.1、::1、localhost)、プライベート IP 範囲(10/8、172.16/12、192.168/16)、リンクローカル(169.254/16)、Google メタデータエンドポイントを拒否してください。検証に失敗した場合は、明確なエラーを出して中止し、取得処理に進まないでください。未検証の URL を Firecrawl/WebFetch/Google API に渡すと、内部サービスに対する SSRF のリスクがあります。seo-drift/SKILL.md:97にあるものと同じ方法です。
- SSRF 対策(URL モード)。 対象が URL の場合は、
- 事前確認。 標準の 3 段階の事前確認(クレジット残高、Firecrawl の利用可否、Google API)については、
skills/seo-firecrawl/references/preflight.mdを参照してください。このスキル固有の注意事項は次のとおりです。- このスキルで見込まれる SE Ranking のコスト:ステップ 4(URL モードのページスナップショット)を含めるかどうかに応じて、通常は約 10~20 SE Ranking クレジットです。
- Firecrawl:WebFetch によるフォールバックが可能なため任意です。利用できる場合、URL ごとに Firecrawl クレジットを 1 クレジット消費します(URL モード)。利用できる場合は、スナップショットで
<head>と JSON-LD の内容も取得するため、canonical/robots/og:*/JSON-LD の変更を差分で検出できます。利用できない場合、スナップショットは部分的なものになります。利用可能な場合でも Firecrawl をスキップするには--no-firecrawlを指定します(差分の対象範囲は狭まりますが、クレジットを節約できます)。 - Google API:ティア 0 では CrUX の p75 LCP/INP/CLS の取得が可能になります(ドメインモードではオリジン、URL モードでは URL)。ティア 1(URL モードのみ)ではさらに URL Inspection の状態(
indexStatusVerdict、googleCanonical、lastCrawlTime)を取得し、以降の比較でフィールドデータとインデックス登録の変化を検出できます。詳しい手順はskills/seo-google/references/cross-skill-integration.mdの「seo-drift」を参照してください。
- ドメインスナップショット(常に実行):
DATA_getDomainOverviewWorldwide— DA、トラフィック、オーガニックキーワード数と有料キーワード数。DATA_getDomainKeywords— 上位 100 件のオーガニックキーワードと順位。DATA_getBacklinksSummary— 被リンク総数、参照ドメイン総数。DATA_getBacklinksRefDomains— 権威性を含む上位 20 件の参照ドメイン。
- ページスナップショット(対象が URL の場合):
WebFetch(常に実行)+mcp__firecrawl-mcp__firecrawl_scrape(利用可能な場合)- WebFetch(無料):
<title>、すべての<h1..h6>、lang、単語数、内部リンク数、画像数、文章レベルの差分比較に使う本文の Markdown を抽出します。 - Firecrawl(URL ごとに Firecrawl クレジットを 1 クレジット消費)— WebFetch が除去する
<head>と<script>の内容を取得します。metadataから:canonical URL、robots メタ、og:title、og:description、og:image、twitter:card。- 返された
htmlから:すべての<script type="application/ld+json">ブロック。検出された@typeとブロック全体の内容のハッシュの両方を記録します。これにより、型の一覧だけでなく、スキーマ内容の変更も差分で検出できます。
- Firecrawl が利用できない場合(または
--no-firecrawlが指定された場合): WebFetch のフィールドのみがフィンガープリントに含まれます。BASELINE.mdに次のように記載します:Snapshot fields recovered via WebFetch only — canonical, robots, og:*, twitter:*, and JSON-LD changes will not be detected on subsequent compares. Install Firecrawl for full coverage. - 取得したフィールドのフィンガープリントハッシュを計算します。
- ページ権威性も取得します:
DATA_getPageAuthority。 4b. Google フィールドデータのスナップショット(google-api.json が存在し、かつ--skip-cwvが設定されていない場合のみ) - ティア 0(設定されている場合は常に実行):URL モードでは
python3 scripts/pagespeed_check.py "{target}" --crux-only --json、ドメインモードではpython3 scripts/pagespeed_check.py "https://{domain}" --crux-only --json(オリジンレベルの CrUX)を実行します。結果の p75 LCP/INP/CLS/FCP/TTFB と、ソースラベル(「URL」または「origin」)を保存します。 - ティア 0(設定されている場合は常に実行):25 週間のトレンド期間のスナップショットとして
python3 scripts/crux_history.py "{target_or_origin}" --jsonを実行し、crux_history_baselineとして保存します。以降の比較では、直近週からの変化を検出できます。 - ティア 1(URL モードのみ):
python3 scripts/gsc_inspect.py "{target_url}" --site-url "{config.default_property}" --jsonを実行します。indexStatusVerdict、coverageState、googleCanonical、userCanonical、lastCrawlTimeを保存します。 --skip-cwvが指定された場合は、このステップ全体をスキップし、cwv/crux_historyフィールドにnullを保存します。その後、比較モードのルールにより「フィールドデータの変化:ベースラインで--skip-cwvフラグが指定されたためスキップ」と表示されます。- CrUX のデータが不十分な場合は、該当する指標に
nullを保存して処理を続行します。
- WebFetch(無料):
- スナップショットファイルを書き込みます:
seo-drift-{target-slug}-{YYYYMMDD}/snapshot.json。 - インデックスを更新します:
seo-drift-{target-slug}/baselines.json—{date, snapshot_path}のエントリを追加します。
比較モード
- 対象を検証し、最新のベースラインを特定します。
seo-drift-{target-slug}/baselines.jsonを確認します。- SSRF 対策(URL モード)。 ベースラインモードと同じ
validate_url()チェックを行います。プライベートアドレス、ループバックアドレス、メタデータアドレスへのアクセスを拒否します。 - ベースラインが存在しない場合はベースラインモードに移行し、後でもう一度確認するようユーザーに伝えます。
- SSRF 対策(URL モード)。 ベースラインモードと同じ
- 現在の状態を取得します(ベースラインモードと同じデータ)。
references/drift-thresholds.mdを使用して各指標を差分比較します。- ドメインオーソリティ:±5で黄色、±10で赤。
- 推定オーガニックトラフィック:±20%で黄色、±50%で赤。
- オーガニックキーワード数:±10%で黄色、±30%で赤。
- トップ3キーワード数:±15%で黄色、±40%で赤。
- トップ100キーワードの変動:検索ボリュームの大きいキーワードが1つでも減少した場合は赤。
- 参照ドメインの純増減:-5~-20で黄色、<-20で赤。
- ページレベル(URL モード):canonical/robots/lang/H1の変更は赤、タイトルまたはメタディスクリプションの変更は黄色、スキーマタイプの追加・削除は黄色、og:*/twitter:*の変更は黄色。
- Firecrawl 依存の差分に関する注意: canonical/robots/og:/twitter:/JSON-LDの差分を比較するには、ベースラインと現在のスナップショットの両方をFirecrawlで取得している必要があります。いずれかのスナップショットがWebFetchのみで取得されている場合、これらのフィールドは問題なしとして扱わず、
not comparable — Firecrawl-only fields missing from {baseline | current} snapshotと表示します。 - Googleデータの変動(両方のスナップショットにGoogleのフィールドがある場合のみ):
- LCP p75が20%以上増加 → 赤。
- INP p75が20%以上増加 → 赤。
- CLS p75が絶対値で0.05以上増加 → 黄色。
- FCP/TTFB p75が30%以上増加 → 黄色。
- 検査ステータスが
INDEXEDから別のステータスに変化 → 赤。 googleCanonicalが変化 → 黄色。lastCrawlTimeが60日より前 → 黄色。- 注意: いずれかのスナップショットにGoogleのフィールドがない場合(いずれかの取得時に認証情報が不足していた場合)、
Field-data / indexation drift: not comparable — Google fields missing from {baseline | current} snapshot.と表示します。
DRIFT-REPORT.mdを作成します。赤の指摘を最初に、その次に黄色、最後に緑/プラスの差分を記載します。最後に「最初に調査すべき項目」の推奨事項を記載します。
履歴モード
baselines.jsonを読み込みます。- 各エントリについて、日付、DA、トラフィック、キーワード数、トップ3キーワード数を1行の概要として出力します。
- 表を含む
HISTORY.mdを作成します。
出力形式
ベースラインモード
seo-drift-{target-slug}-{YYYYMMDD}/:
seo-drift-{target-slug}-{YYYYMMDD}/
├── snapshot.json (the captured state)
└── BASELINE.md (one-page human summary of what was captured)
比較モード
seo-drift-{target-slug}-{YYYYMMDD}/:
seo-drift-{target-slug}-{YYYYMMDD}/
├── DRIFT-REPORT.md (synthesised: red/yellow/green changes — primary deliverable; inlines 01-domain-deltas, 02-keyword-churn, 03-backlink-deltas, 04-page-deltas as sections)
└── evidence/
├── baseline-snapshot.json (the prior reference — kept for replay)
├── current-snapshot.json (today's state — kept for replay)
├── 01-domain-deltas.md (DA, traffic, keyword count changes — raw step output)
├── 02-keyword-churn.md (top-100 entries/exits)
├── 03-backlink-deltas.md (new + lost backlinks/domains)
└── 04-page-deltas.md (URL mode only: HTML fingerprint diff)
トップレベルにはDRIFT-REPORT.mdのみを配置します。4つの差分ステップファイルは、DRIFT-REPORT.md内の名前付きセクションにインラインで記載します。evidence/には、今後の再差分比較や監査で使用できるよう、生の差分ダンプと両方のスナップショットJSONを保存します。
DRIFT-REPORT.mdの形式:
# Drift Report: {target}
> Baseline: {baseline date} · Current: {today's date}
## RED — investigate today
- {finding} ({severity rationale})
- ...
## YELLOW — investigate this week
- {finding}
- ...
## GREEN — positive deltas
- {finding}
- ...
## Field-data drift (CrUX + URL Inspection)
- LCP p75: {baseline} → {current} ms ({Δ%}) {↑ red / ↑ yellow / stable / ↓ green}
- INP p75: {baseline} → {current} ms ({Δ%}) {…}
- CLS p75: {baseline} → {current} ({Δ absolute}) {…}
- Indexation status: {baseline INDEXED → current EXCLUDED} (URL mode)
- googleCanonical: {baseline → current} (if changed)
- (Or: `Field-data / indexation drift: not configured` / `not comparable — missing from {snapshot}`)
## What to investigate first
1. {prioritised action with reasoning}
2. ...
履歴モード
seo-drift-{target-slug}-{YYYYMMDD}/HISTORY.md:
# History: {target}
| Date | DA | Traffic | Keywords | Top-3 |
|---|---|---|---|---|
| 2026-04-27 | 42 | 18,500/mo | 1,247 | 89 |
| 2026-03-15 | 41 | 17,200/mo | 1,213 | 85 |
| ...
ヒント
- レート制限を守ってください:10 req/sec。ベースラインの実行では、4~6件の呼び出しを順番に行うため、余裕を持って実行できます。
- 実行前に
DATA_getCreditBalanceを呼び出してください。ドメインのベースラインは約10~15 SE Rankingクレジット、URLのベースラインは約15~20 SE Rankingクレジット+1 Firecrawlクレジット、比較は約20~30 SE Rankingクレジット+1 Firecrawlクレジット(現時点の状態を取得)です。 - スナップショットは v0.4.0 ではローカルのみに保存されます。チームでベースラインを共有する必要がある場合は、共有ファイルシステム上の同じ
seo-drift-{target-slug}/ディレクトリを全員で参照するか、プライベートリポジトリにコミットしてください。ベースラインはJSON形式で、Gitとの相性が良好です。 - ベースラインの取得頻度は、SE Rankingの履歴エンドポイントが月単位の粒度であるため、月1回が自然です。バックリンクデータについては、週1回ではノイズが多すぎます。チームへの引き継ぎ時に、推奨する取得頻度を記載してください。
- 「過去1時間に何か壊れたか」をデプロイ時に確認する用途では、URLモードのページフィンガープリント部分が主要な手段です。これは月次データに依存しません。
- ドリフトの検出結果に基づいて、自動で否認したり修正したりしないでください。このスキルは診断を行い、判断するのは人間です。
- オーソリティ履歴がすべてゼロになる場合の注意点:
DATA_getPageAuthorityHistory(URLモード)またはDATA_getDomainAuthorityHistoryが対象期間全体でゼロの値を返す場合は、「履歴が不十分」とみなしてください。差分を計算したり、データ欠損に基づいて低下を示したりしないでください。現在値のエンドポイント(DATA_getPageAuthority/DATA_getDomainOverviewWorldwide)と照合し、現在値に意味のある値がある一方で履歴がフラットな場合は、傾向を捏造せず、DRIFT-REPORT.mdにデータ品質のフラグとして記載してください。 - 何もしない場合のコストは、気づかれない低下です。月1回実行するコストは約15クレジットです。月1回実行してください。