AIデジマ研究所

サイトマップとインデックスの復旧を、毎週同じスクリプトで答え合わせする

2026-10-18 ・ 大規模修正

サイトマップを登録し直したあと、「Googleがちゃんと読んでくれているか」「発見されていなかった記事がインデックスされたか」を目で確認し始めると、毎週同じ画面を同じ順番で見る作業が増えます。見るのを忘れた週があると、取得が止まっていても気付けません。

結論から書きます。サイトマップとインデックスの復旧は、「登録して終わり」ではなく「毎週同じ3つの問いに機械が自動で答える」ところまでをひとつの作業にします。具体的には、サイトマップが取得され続けているか・未発見だった記事がインデックスされたか・GA4の離脱クリック計測がONになったか、の3つを週1回のスクリプトで判定し、全部がクリアになったらそのスクリプト自体を外します。

この記事は、散らかったサイトをAIで作り変えるマニュアルの「大規模修正:構造を作り直す」の最後の作業です。サイトマップの差し替えや URL の統合(重複を301で寄せる、孤児URLとパーマリンク衝突)が終わったあとに、「本当に直ったのか」を機械に答えさせる段です。


この作業で決まること

この作業が終わると、サイトマップとインデックスの復旧が「終わった」と言える条件が決まります。条件は3つです。

この3つを人の目で毎週見るのではなく、週1回スクリプトに判定させて、1件でも不合格があったときだけ出力させます。全部クリアになったら、スクリプト自体を launchd から外します。「終わり」の形を先に決めておくと、様子見が長引きません。

よくある失敗:Search Console の画面で「表示回数が0件」なのを見て、「まだインデックスされていない」と判断してしまうこと。表示回数0件は「新しすぎてまだ検索されていない」だけの可能性があり、インデックスの有無とは別の指標です。インデックスの判定は、URL Inspection API の verdict で行います。


前提:この作業の前に必要なもの

直前の実測で、自分のサイトでは GSC に登録されていた唯一のサイトマップ(/sitemap.xml)が404を返し、Googleが最後に取得できたのが登録から約17か月前になっていました。そこでサブサイトマップ3本を直接登録し直しました。ただし /sitemap.xml 自体のリライトは直しておらず、robots.txt も404を宣言したままです。実害は出ていませんが、「robots.txt が正常に戻った」と誤認しないために、このスクリプトで毎週状態を出します。


AIに渡すもの

このスクリプトを AI に書かせる、あるいは直させるときに渡すのは次の3つです。

  1. 「終わった」と言える3つの条件(上の3つ)
  2. 判定に使う API と、使ってはいけない代替指標:Search Console API の sitemaps.list と urlInspection.index.inspect、GA4 Data API の runReport を使う。表示回数・順位・インプレッションでインデックスの有無を推定しない
  3. 出力の形:全OKなら無音、1件でも不合格なら Markdown 1本を標準出力とログファイルに書く

3番目は launchd などの定時実行と組み合わせるためです。毎週メールや Slack に全文を流し込むのではなく、「出力があったときだけ気付く」設計にしておくと、通知の疲労で見落とすことがなくなります。


手順

  1. 「発見されていない」と事前に実測した URL を、スクリプトの先頭にリテラルで書く(最大でも数本)
  2. Search Console API の sitemaps().list() を呼び、登録サイトマップごとに lastDownloaded と errors を取る
  3. lastDownloaded と今日の日付の差を日数で出し、30日を超えたら警告を立てる
  4. 旧・壊れた索引(/sitemap.xml)が登録に残っていれば、消したかどうかが分かる形で併記する
  5. 「発見されていない」URL ごとに urlInspection().index().inspect() を呼び、verdict と coverageState と lastCrawlTime を取る
  6. 同じ URL に対して現在の HTTP ステータスも1回だけ取り、coverageState と並べて出す
  7. GA4 Data API に直近7日の eventName × eventCount を問い合わせ、click イベントの有無で離脱クリック計測の状態を判定する
  8. 3つのセクションを Markdown に組み、ログファイルに追記しつつ、--quiet が指定されていて全OKなら標準出力を抑制する
  9. 全OKの判定が出たときだけ「このジョブはもう不要(launchctl unload で外してよい)」の1行を足す

6番目を省いて coverageState だけで判断すると、記事を誤って消す事故につながります。次の「失敗」で理由を書きます。


完了条件


実際に起きた失敗

coverageState が404と言っていた記事が、ライブでは200を返していた

スクリプトを書き始めた段階で、URL Inspection API の coverageState が「Not found (404)」を返している URL が複数ありました。最初は「じゃあ記事が消えているのかもしれない」と考えて、記事の存在そのものを疑いかけました。

実際には、coverageState は Googleが最後にクロールした時点の状態です。現時点のサイトの状態ではありません。該当の URL をブラウザで開いても、サーバーに urllib.request で取りに行っても、200を返していました。クロールが止まっていた間に実体が復旧していたのを、Googleがまだ知らなかっただけでした。

このため、スクリプトでは coverageState と同じ行に 現在の HTTP ステータスを併記するようにしました。「Googleの申告」と「実体」の両方を1行で見せると、クロールが追いついていないだけなのか、本当にページが消えているのかを一目で切り分けられます。この一手間を省いていたら、既に復旧済みの記事を「404のまま」と誤認して消していたはずです。

GSC API の errors を数値として比較していて、サイトマップが常に不合格扱いになった

GSC の sitemaps API は、errors フィールドを 文字列 で返します(たとえば '0')。これを errors == 0 で判定していたので、エラーが0件のサイトマップもすべて「不合格」として赤マークが出続けました。

毎週の出力に赤マークが並ぶ状態が続くと、慣れてしまって「どうせ毎週赤いやつだ」と見出しごと読み飛ばします。そうなるともう、本当にエラーが出た週にも気付きません。スクリプト側で int(s.get("errors", 0) or 0) と明示的に数値変換してから比較することで、赤マークは実際にエラーが出た週にだけ出るようになりました。

通知の信号対雑音比を保つのは、スクリプトそのものを使い続けるための前提条件でした。


よくある質問

Q. Search Console の画面でインデックスを確認するのではだめですか?
A. 1回きりなら画面で足ります。毎週同じ URL を同じ順番で見る作業は、人の目で続きません。URL Inspection API を使えば、同じ判定を同じコードで毎週再現できます。

Q. 全部がクリアになったあとも、スクリプトは残しておくべきですか?
A. いいえ。全OKが出たら launchd のジョブごと外します。「もう不要」の1行をスクリプト自身に出させているのは、外すタイミングを忘れないためです。残しておくと、API のクォータを食いながら無意味な出力を増やし続けます。

Q. GA4 の click イベントは、なぜ復旧の答え合わせに入っているのですか?
A. 離脱クリック(外部サイトへの遷移)の計測が ON になっていないと、サイト上で起きている行動の多くが見えない状態が続きます。サイトマップとインデックスを直すのと同時期に、計測の抜けも1回だけ機械で見ておくと、あとで「見ていなかった期間」を作らずに済みます。


関連記事

次の作業