WordPressサイトの本番DNS切替と、移行後に見つかった301の穴
切替の当日は、意外と何も起きない。
前のフェーズまでで新サイト側の準備は済んでいて、残っていたのは向き先を変える操作だけだった。だから怖いのは切替そのものではなく、切り替えたあとに「実は通っていなかったURL」が静かに残ることのほうだ。案の定、静かに残っていた。
www をゾーンに入れて、apex の301を実測するまで
まず進捗台帳と切替手順書を Claude Code に読ませて、Step 1 の実行内容を確定させた。ここを曖昧なまま触ると、あとで「何をやった状態なのか」が分からなくなる。
管理画面の操作はブラウザ越しに進めた。途中でログインページに飛ばされたり、ページの状態がスクリーンショットとテキストで食い違ったりして、そのたびに「今どの画面にいるか」をテキストで取り直してもらった。接続しているブラウザが1台だけであることも確認した。複数繋がっていると、操作した先と見ている先がずれる。
www 付きのサブドメインをゾーンに入れて続行すると、DNS確認画面に進んだ。リダイレクトのルールを作ろうとしたらカスタムフィルタ式のビルダーが出てきたので、GUIで積み木を並べるのはやめて、式を直接編集するモードで書いてもらった。1行の式にしておけば、あとから読み返して条件を確かめられる。
ルールがアクティブになったところで、apex から www への301を実測した。ここまでは想定どおり。
切替直後にひととおり殴ってみる
「たぶん大丈夫」は検証ではないので、切替直後に総当たりをかけた。
- 203記事の本番URL全件 → すべて200
- 301で寄せる対象の7記事と、ルール13本 → すべて最終的に200へ到達
- WordPress時代の
?p={ID}形式 210件 → 本番ドメインで巡回 - sitemap と noindex の状態
?p={ID} は旧サイトが吐いていた素のパーマリンク形式で、外部からのリンクやブックマークがここに残っている。新サイト側で受け止められないと、そのまま行き止まりになる。
画像も1枚ずつ突き合わせた。最初の巡回で欠けが出て、キャッシュをパージしたら71/72枚まで戻った。残り1枚のSVGだけが戻らないので、そこは個別に追いかけた。検証の途中でブラウザのタブが閉じられていて、新しいタブで開き直して再検証した場面もある。「さっき見たときは出ていた」は根拠にならない。
robots.txt を新しく作り、ビルド→sitemap生成→デプロイの順で流した。ついでに旧サーバー関連の作業メモが公開側に出ていないかを確認したところ、draft: true が効いて dist にそもそも生成されておらず、本番では404だった。露出なし。
デプロイ直後は、デプロイ固有URLと本番エイリアスの両方を叩いて切り分けた。片方だけ見ていると、「デプロイは成功したのに本番には出ていない」を見逃す。
Search Console にサイトマップを出し直す
サイトマップの再送信は、プロパティ未選択の画面に飛ばされるところから始まった。登録済みプロパティの一覧が空に見えたので、スクリーンショットで実際の表示を確認してもらった。DOMのテキストだけ見ていると、描画されているのに拾えていないケースがある。
送信は成功して、送信日が 2026/07/26 に更新された。ページレポートでインデックスの初期状況も記録した。サイトを一度落としているので、ここの数字は今日が底になるはずだ。
学習ゲートを通そうとしたが、今日はスキップして先に進めることにした。
セッション上限で一度止まる
上位ページの確認に入ったところでセッション上限に当たり、正午過ぎまで待たされた。裏で走らせていたレビュー用のワークフローも、記事メタの6バッチは完了していたが、専門レビュー3件だけが上限で落ちていた。
再開後は Opus 5 に切り替わっていたので、失敗した3件だけを再実行した。完了済みの分はキャッシュを再利用させたので、やり直しは3件分で済んだ。全部投げ直していたら、また上限まで走らされていたと思う。
「全部うまくいったのか」を確かめに行ったら、穴が出た
検索コンソールに記録のある上位ページが、新サイトでちゃんと表示されるか。まず上位10ページのHTTP状態を確認した。全件正常。
ただ、上位10件で「全部うまくいっている」と言い切るのは無理がある。記録のある全222ページ(203記事以外の旧URLを含む)を取り出して突き合わせにかかった。ここで手が止まる。表示件数を500行に切り替えても、UIに反映されない。何度やっても同じだった。
一覧が取れないなら、URLの形から攻めればいい。旧WordPress特有のURL体系——カテゴリ、タグ、フィード——が新サイトでどう扱われるかを直接テストした。
旧カテゴリの階層URLが404を返した。
台帳には301実装済みと書いてある。ならばルールの条件のほうが実際のURLとずれている。末尾スラッシュの有無で切り分けたら、そのとおりだった。
/category/parent/child → 301(効く)
/category/parent/child/ → 404(効かない)
WordPressが実際に吐いていたのはスラッシュ付きのほう。しかも新サイト側はスラッシュ付きが正規URLだ。つまり、旧サイトが世に出していた形のカテゴリURLだけが、まるごと落ちていた。
移行の欠陥としては1件。ただ、これを見つけるまでの経路が「上位10件OK → 全件見ようとしてUIに阻まれる → URLの形から攻める」だったのが今日のいちばんの収穫だった。一覧が取れないことに詰まっていたら、この穴は見つかっていない。
待ち時間にフォームを触っておく
修正の検証用に wrangler dev を起こしている間、手が空く。その間に本番ドメインでお問い合わせフォームを開いた。認証ウィジェットのホスト名設定に www 付きが入っていないと、切替後にフォームだけ静かに死ぬ。
開いてみたら、ウィジェットは www 付きでも正常に表示された。ここは無傷。
修正、そしてエッジ伝播に騙されかける
wrangler dev が上がってから、階層カテゴリのルールを直してローカルで検証した。スラッシュ付きが301になること、単一階層のカテゴリが壊れていないこと。リグレッションを確認してからデプロイした。
デプロイ後に本番を叩いたら、2つ引っかかった。片方は直したはずの階層カテゴリがまだ404を返す。もう片方は日本語slugのURLが通らない。
どちらも実際の欠陥ではなかった。
階層カテゴリのほうはエッジ伝播の過渡状態で、時間をおいて3回叩いたら3回とも301になった。日本語slugはURLエンコードして投げれば200で、素の日本語をそのまま渡していた curl 側の問題だった。「デプロイ直後の1回の結果を確定情報として扱わない」を、今日2回学んだことになる。
切り分けの結果は台帳に書いてコミットした。「404だったが伝播の過渡状態」「日本語slugはエンコード漏れ」まで残しておかないと、記録上は欠陥2件が未解決のまま残る。
1週間・2週間・1ヶ月のモニタリングを台帳に書く
移行の途中でサイトが一度落ちている。インデックスは減っているし、直近のアクセス数もかなり少ない。切替直後の数字を見て一喜一憂しても仕方がないので、観測の期間と見る対象を先に決めて移行計画の台帳に書き足した。
- 1週間:インデックス数が増える方向に向いているか、404が出ていないか
- 2週間:上位ページの表示とアクセスが戻り始めているか
- 1ヶ月:全体として上がっていく形になっているか
旧サーバーをいつ解約するかも、この観測結果とセットで判断することにした。まだ切らない。301が効いている前提が崩れたときに戻れる場所を、しばらく残しておく。
なお、タイトルとディスクリプションの一貫性——いわゆるAI SEOまで含めた改善方針については、この日別のレビューと計画立案を並行して走らせている。そちらは別の記事に分けた。
走らせっぱなしのプロセスを片付ける
今日の作業を終える前に、動いているものがないかを確認した。
wrangler dev の残骸が1つ残っていたので、ポート指定で止めた。ポートは解放されたのに workerd プロセスが3つ残っていて、素性を確認させたら2つは別プロジェクトのものだった。触らない。自分が今日起動した1つだけを止めた。
プロセス名だけ見て一括で殺すと、隣のプロジェクトを巻き込む。名前ではなく素性で判断する、という当たり前の作法を毎回やる。
今日の学び
- 「上位10件が通った」は「全部通った」ではない。 上位だけの確認で止めていたら、旧カテゴリURLの穴はそのまま残っていた
- 一覧が取れないときは、URLの形から攻める。 管理画面のUIが言うことを聞かない時点で諦めず、旧CMS特有のURL体系を列挙してテストするほうが速かった
- 末尾スラッシュは移行の鬼門。 旧サイトが実際に出していた形と、新サイトの正規形と、リダイレクトルールの条件——この3つが一致しているかを、形ごとに叩いて確かめる
- デプロイ直後の1回の結果を信じない。 404も200も、エッジの伝播が落ち着くまでは過渡状態を見ている可能性がある
- 切り分けの結果は台帳に残す。 「これはcurl側の問題だった」を書いておかないと、次に同じ404を見たときにまた同じ切り分けを一からやることになる