つ積み上げログ技術ブログ記事一覧へ

自主執筆記事

404.html で転送すると、ブラウザは飛ぶが検索エンジンには404のまま

GitHub Pages は301を返せない。404.html に JS を入れて転送したが、HTTPステータスは404のままで、5日間 約7,000URLが行き先を失っていた。200を返す実体ファイルに置き換えるまでの記録。

SEO公開: 2026/09/23更新: 2026/09/30
GitHub Pagesリダイレクトドメイン移転canonical

01 / 本文

ブラウザで飛ぶので、動いていると思っていた

静的サイトを別ドメインへ移した。旧ドメインのDNSはそのまま GitHub Pages を向いている。

GitHub Pages は 301 を返せない。サーバー側の設定ファイルを置ける仕組みが無いからだ。そこで 404.html を使った。存在しないパスはすべてこのファイルが返るので、中の JavaScript でパスごと転送する。

旧URLをブラウザで開くと、一瞬で新しいURLに変わる。狙いどおりに見えた。5日間そのままにした。

02 / 本文

検索エンジンが見ているのは本文ではない

確認をブラウザでやったのが間違いだった。ブラウザは HTTPステータスが404でも本文の JavaScript を実行する。だから飛ぶ。

検索エンジンが見るのは、その手前のステータスコードだ。curl でリダイレクトを追わずに叩くと 404 が返る。404 は「このURLは存在しない」という意味で、転送ではない。

サーチコンソールには、発見済み未登録 6,162 / クロール済み未登録 767 / インデックス 2 と出ていた。約7,000のURLが行き先を失っていた。

03 / 本文

200 を返す実体を、全パスぶん置く

301 が返せないなら、200 を返すページを実在させるしかない。移転先のサイトマップから全パスを取り、同じパスに実体のある HTML を置いた。10,450ファイルになったが、1ファイル700バイト程度で合計8MBほどだ。

中身は3つだけ。canonical、即時の meta refresh、noindex,follow。大事なのは canonical と refresh が「そのページごとの移転先」を指していること。全部をトップページに飛ばすと、Googleは転送ではなく「中身の無いページ」として扱う。

即時の meta refresh は 301 と同じに扱われる。301 が返せない以上、これが上限になる。

04 / 本文

確認は、直したい相手と同じ見え方で取る

直したあと、200件を抜き取って確かめた。HTTP 200 が 200/200、canonical 一致が 200/200、refresh 一致が 200/200。

何のために直したのかで、確認の道具を変える。検索エンジンのために直したなら、curl でステータスだけを見る。リダイレクトを追う -L は付けない。追うと、また「飛んだから成功」に戻る。

ブラウザで開いて動いた、は成功の証拠にならない。ブラウザは親切すぎる。

コメント

この記事へのコメント

お名前だけで投稿できます。アカウント登録やログインは不要です。 いただいたコメントは確認のうえ公開します。