SEO

旧ドメインを使い回した新ブログのインデックスが進まない — Search Console で 9件 / 153件を片付ける

木製デスクの上に並ぶ書類、虫眼鏡、ノートPC、スマホ、コーヒーの俯瞰
Photo by Pavel Danilyuk on Pexels

9件しかインデックスされていなかった

このブログ (techikoma.com) は、もともと WordPress で動かしていた古いブログを Astro + Cloudflare Workers Static Assets に丸ごと載せ替えたもので、ドメインだけ昔のまま使っています。記事自体は新しく書き起こしたものを25本ほど、すでに公開していました。

ただ、このところ書いた記事を Google で site:techikoma.com で確認すると、検索結果に出てこないものがちらほら。「予約投稿が壊れた?」と思って RSS と sitemap を確認すると配信側はちゃんと動いていて、出ていないのはあくまで Google のインデックス側の話。

そろそろ Search Console を真面目に見ようか、と開いて固まりました。

Search Console「ページのインデックス登録」画面。未登録 153、登録済み 9 と表示されている

登録済み 9 / 未登録 153

公開した記事は25本前後、これに /about や tags ページを足して80URLくらいの sitemap を出しているはずなのに、グラフを見る限りずっと「灰色 (未登録)」が圧倒的に多いまま 3 ヶ月推移しています。

新規ブログのクロール待ちというより、何かが積極的に未登録を増やしている気配があったので、内訳を 1 つずつ追いかけました。

未登録 153 件の内訳

「ページがインデックスに登録されなかった理由」テーブルを開くと、こうなっていました。

理由件数中身
検出 - インデックス未登録68全部新ブログの記事。クロールに来てもらえてないだけ
見つかりませんでした (404)48旧 WordPress 時代の /index.php/... URL の残骸
代替ページ (canonical あり)16tags のページネーションなど。正常動作
noindex タグによって除外14旧 WordPress の月別アーカイブや RSS フィード URL
クロール済み - インデックス未登録7品質判定で除外されているもの

最大の塊である「検出 - インデックス未登録 68件」をクリックして中身を見ると、新ブログの新しい記事 (/blog/*/about/) が並んでいて、共通して「前回のクロール: 該当なし」と書かれています。

Search Console「検出 - インデックス未登録」詳細画面。該当ページ 68、初検出日 2022/08/17 と表示

Google は URL を「検出」はしていて、でもクロールしに来ていない、という状態ですね。sitemap には載っているし、検出日も 2022 年 (旧 WordPress 時代) からなので、認識自体はずっと前からされている。それでも後回しにされ続けている、というのが厄介なポイントでした。

原因の見立て: 旧ドメイン再利用 + 大量の遺物

数字を並べ直してみると、見立てが立ちます。

  • 検出済みなのにクロールが来ない 68 件 (新ブログの本体)
  • 旧 WordPress 由来の 404 が 48 件
  • 同じく旧 WordPress 由来の noindex が 14 件

つまり、Google から見ると techikoma.com というドメインの中で、「死んでいる古い URL」と「いつのまにか生えた新しい URL」が混ざっていて、クロール優先度の付け方に困っている状態。

ドメインを使い回したことそのものが悪手というわけではないんですが、

  • 旧サイトの URL がまだ Google のキャッシュ上に残っている
  • そこにクロールが行く → 404 や noindex が返る → クロール枠を 1 件消費
  • 新サイトの URL は sitemap で「検出」だけされて、優先順位の都合で後回し

という流れで、新規 URL に回ってくるはずのクロールバジェットが、死んだ URL の確認で食われているわけです。新しいブログを単独ドメインで立ち上げたなら、もっと素直にクロールが回ったはず。ドメイン再利用の宿命ですね。

打ち手は、整理すると 2 方向ありました。

  1. 旧 URL の処理を、Google が「もう来なくていい」と判断しやすい返し方に変える (= コード対応)
  2. 新 URL を、Google に手で 1 本ずつ「先にクロールして」と依頼する (= 運用対応)

順番にやっていきます。

コード対応: 旧 URL を 410 Gone にする

新ブログ移行直後は、旧 WordPress の /index.php/... URL は Astro 側の通常の 404 ページで返していました。これは見た目上は問題ないんですが、Google から見ると「/index.php/2018/... を叩いたら 404 が返ってきた → でも一時的かもしれないから、また確認しに来よう」という扱いになります。

ここで使える HTTP ステータスが 410 Gone で、「このリソースは恒久的に消えた、もう来なくていい」という意味になります。Google のドキュメントでも、404 より 410 のほうがインデックスからの除外が早いと明記されています (Google 検索セントラルの該当箇所)。

このブログは Cloudflare Workers Static Assets で配信しているので、workers/site/ に小さい Worker を 1 本足して、/index.php/... で来たリクエストを 410 で返すようにしました。

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const url = new URL(request.url);

    // 旧 WordPress の /index.php/... を 410 Gone で返す
    if (url.pathname.startsWith('/index.php/') || url.pathname === '/index.php') {
      return new Response('Gone', {
        status: 410,
        headers: { 'content-type': 'text/plain; charset=utf-8' },
      });
    }

    // それ以外は静的アセットへ
    return env.ASSETS.fetch(request);
  },
};

ついでにもう 1 件、Cloudflare Workers Static Assets のデフォルトだと、trailingSlash 違いの URL が 307 (Temporary Redirect) で正規版にリダイレクトされていました。サイトとして動く分には問題ないんですが、Google は 307 を「一時的なので元 URL もインデックス候補として残す」と扱うので、canonical 解釈が安定しません。これは 301 (Permanent) に直すのが正解です。同じ Worker のなかで Location を返すリダイレクトに置き換えました。

デプロイ後、一通り curl -I で確認:

GET /index.php/2018/foo  → 410 Gone
GET /blog/some-post      → 301 → /blog/some-post/
GET /blog/some-post/     → 200

これで「旧 URL を確認しに来るたびに 1 件クロール枠を消費する」ループは止まる、という見込みです。

運用対応: URL 検査ツールで個別にインデックス登録リクエスト

コード側でクロール枠の漏れを止めても、「もうクロールしに来てくれない 68 件」のほうは自分から呼ぶ必要があります。これに使うのが Search Console の「URL 検査」 → 「インデックス登録をリクエスト」です。

手順自体は 1 件ずつ手作業:

  1. Search Console 上部の URL 検査バーに記事 URL を貼る
  2. 「URL が Google に登録されていません」と表示される
  3. 「インデックス登録をリクエスト」をクリック
  4. テストが走る (30〜60 秒)
  5. 「インデックス登録をリクエスト済み」のダイアログが出る

URL 検査でインデックス登録リクエスト送信後のダイアログ

これを未登録の記事ぶん繰り返します。1 件あたり 1 分ちょっと、合間にテスト時間を待つ必要があるので、20 件くらいやると普通に 30 分は溶けます。

1日の上限の話

URL 検査リクエストには公式に明記されていないゆるい上限があって、世の中の解説記事だと「1 日 10 件くらい」と書かれていることが多いです。

ただ実際にやってみると、自分のケース (公開済み記事 25 本 + /about の 26 URL) では全件「優先クロールキューに追加」まで通って、途中でクォータエラーも reCAPTCHA も出ませんでした。クリックして待つだけで、26 件淡々と通っていく感じ。

なので運用としては、まずは送ってみて、「1日の上限を超えました」が出たらそこで止めるぐらいの構えで十分そうでした。10件で頭打ちと身構えるよりは現実的です。アカウントやサイト規模によって挙動が変わる可能性はあるので、自分のところで通ったらラッキー寄りの仕様くらいの心構えで臨むのがよさそうです。

URL prefix とドメインプロパティの並行運用

途中で気づいたんですが、Search Console には URL prefix プロパティ(https://techikoma.com/) と ドメインプロパティ(sc-domain:techikoma.com) の 2 種類があって、片方ずつ持つこともできるし、両方持つこともできます。

  • URL prefix: 既存の履歴データ・サイトマップ送信状態がそのまま残る
  • ドメイン: サブドメイン (このサイトなら tools.techikoma.com) も込みで統合ビューが見える

新ブログを立てたタイミングで tools.techikoma.com (てちこまツール) を増やしているので、ドメインプロパティを並行して追加しました。Google の内部処理は結局ドメイン単位で 1 回なので、両方持っていてもクロールが二重にされたり、ペナルティの対象になることはありません。

ドメインプロパティだと TXT レコード認証が必要で、Cloudflare DNS の管理画面で 1 件レコードを追加するだけです。サブドメイン込みの全体感を見たいなら追加しておいて損はないですね。

クローラーは思っているより回ってこない

途中で「そもそも Google のクローラーって、待っていればどれくらいの頻度で回ってくるんですか?」という質問を別の作業中にもしてみたんですが、整理すると:

  • 更新頻度が高くて被リンクが多いサイト: 数時間〜1日で再クロール
  • 個人ブログ規模 (記事 30 本程度、外部リンクほぼなし): 1〜2週間に 1 回ペース
  • 新規発見 URL: クロールの優先度が低いので、放置だと数週間〜数ヶ月待ち

つまり、新規ブログを立ててから数週間放置しているとインデックスが進まないのは、ある意味正常ということです。「sitemap に載っているから自動で進むはず」というのが楽観すぎたわけですね。

新規記事を出すたびに URL 検査でリクエスト → 何本か投げると Google の側でドメイン全体の優先度も少しずつ上がる、というのが現実的な進め方になりそうです。

やってみた所感と、ここからの経過観察

今回の作業で打ったのは大きく 2 つ:

  • コード側: 410 Gone と 301 リダイレクトを Cloudflare Worker に追加
  • 運用側: 公開済み記事 25 本 + /about26 URL すべて URL 検査からインデックス登録リクエスト

数字としての効果はこれからです。Search Console のページレポートには反映までタイムラグがあるので、3〜7 日後くらいから「検出 - インデックス未登録」の塊が少しずつ減って、登録済みが伸び始める、というのが想定する流れ。旧 /index.php/* まわりの 404 / noindex は、410 Gone を読みに来た Google が「もう来なくていい」と判断するまでもう少し時間がかかるので、こちらは数週間スパンで眺めることになりそうです。

なので 公開時点ではまだ「やってみた段階」 で、効果検証は次の記事に回す形になります。同じ状況の方は同じタイミングで仕掛けて、何週間か後に Search Console を見比べる、くらいの距離感が良さそうですね。

打ち手とは別に、整理として残っている学びは:

  1. ドメイン再利用は便利だけど、旧 URL の遺物がクロールバジェットを圧迫する。新ブログの立ち上げ時には、旧 URL の処理 (410 Gone) をセットで考えたほうがいい
  2. 新規ブログのクロールは、放置だと本当に進まない。sitemap に載せるだけでは足りなくて、URL 検査ツールでの手動申請が体感最速
  3. 307 / 301 / 410 は Google から見た意味が違う。デフォルト挙動を 1 回確認しておく価値はある
  4. URL 検査の上限は思ったよりゆるい。10 件で身構えなくても、クォータも reCAPTCHA も出ずに一気に投げてしまえる場合がある

今後の運用としては、新記事を公開したら同じ要領で URL 検査を 1 件投げる、というのを公開フローに組み込む方針です。Indexing API での自動化は、仕様上 Job Posting と Live Streaming にしか公式対応していないので個人ブログだとグレー寄り (Google 検索セントラル: Indexing API)、というのが Web 上の見解。今回はおとなしく手動で続けます。

何より、新しくブログを立てたのに検索結果に出てこない、というモヤモヤの原因がちゃんと数字で見えたこと自体が今回の収穫でした。数字側の答え合わせは、また Search Console が落ち着いた頃に。

参照リンク