10年以上前に立ち上げた当社のWordPressサイト(nmbr.jp)のパーマリンク構造を、ようやく刷新した。
旧URL構造はこんな感じだった。
https://nmbr.jp/blog/2014/02/19124616_122.html
WordPressの初期設定として、年月日と時分秒、投稿IDが連結されたパス。長い、読めない、SNSでシェアしても見栄えが悪い。何より、各記事のスラッグが「タイトルの冒頭を切り出した日本語」になっていて、もしこのままパーマリンク構造だけ変えると以下のようになってしまう。
https://nmbr.jp/blog/ウェブアナリストが絶滅危惧種になっているんじ/
URLエンコードされると意味不明な文字列の羅列になる、という追加の問題もある。
ということで、ゴールはこうした。
https://nmbr.jp/blog/web-analyst-endangered-species/
/blog/%postname%/ 構造で、スラッグは英語(kebab-case)。旧URLは301リダイレクトで保護する。
本記事は、この移行作業の手順と、途中でハマったポイントの記録である。同じ作業を予定している方の参考になれば。
なお作業環境は以下のとおり。
- WordPress 6.6.5 (SWELLテーマ)
- エックスサーバー (一般プラン)
- リダイレクト管理プラグイン: 301 Redirects (WebFactory Ltd 製)
- 対象記事数: 44件
事前調査:思ったより複雑だった
作業前に把握すべきことが、ざっと洗い出すだけでこれだけあった。
1. データベースの紐付け確認
エックスサーバー上で複数のWordPressサイトを運用していたため、どのDBがnmbr.jpのものか確実に把握する必要があった。WordPress管理画面の 「ツール → サイトヘルス → 情報 → データベース」 で確認できる。
2. .htaccessの構成確認
サーバー上の .htaccess を確認したところ、nmbr.jpは /wp/ サブディレクトリにWordPress本体を置き、内部リライトでルート直下のように見せている構成 だと判明した。設定 → 一般の「WordPressアドレス(URL)」と「サイトアドレス(URL)」の値が異なる、というやつ。
これ自体は今回の作業を妨げるものではないが、 .htaccess を直接編集すると壊す危険があるため、すべてWordPress管理画面のGUI経由で完結させる方針にした。
3. 既存リダイレクトルールの形式確認
301 Redirectsプラグインには既に25件のルールが登録されていた(過去のサイトリニューアル時の名残)。エクスポート機能でCSVとして書き出してみると、以下の形式だった。
301,blog/2015/04/20164128.html,1776
3列目の数字「1776」は 投稿ID 。つまり既存ルールは、リダイレクト先をURLではなく投稿IDで指定していた。これに合わせる必要がある。
4. サーバーキャッシュの存在
エックスサーバーの「サーバーキャッシュ設定」が有効になっていた。本番作業後、キャッシュクリアが必要。
データ準備:44件のスラッグ対応表を作る
WordPress標準のXMLエクスポート(ツール → エクスポート)で全記事を書き出し、Pythonでパースして以下の対応表を作成した。
| post_date | title | old_url | new_slug | new_url |
|---|---|---|---|---|
| 2014-02-19 | ブログ始めます | https://nmbr.jp/blog/2014/02/19124616_122.html | blog-start | https://nmbr.jp/blog/blog-start/ |
| … | … | … | … | … |
スラッグの命名は kebab-case で、3〜6語程度の英単語に圧縮。同テーマの記事は接頭辞を揃えて識別しやすくした(例: Google Analytics系は ga- で始める、年シリーズには年を含める、など)。
ここで一つ重要な発見があった。旧URLの末尾 _122.html の数字部分が、そのままWordPressの投稿IDと一致していたのである。
blog/2014/02/19124616_122.html → 投稿ID: 122
これによって、リダイレクト先の指定がぐっと楽になった。各記事の投稿IDを取得するためにDBを叩く必要がなく、旧URL文字列から正規表現で抽出するだけで済んだ。
本番作業の手順
ここからは実際に本番に手を加えていく工程。
事前にやったこと
- データベースのバックアップ(エックスサーバーのMySQLバックアップ機能)
- WordPress標準のXMLエクスポート(念のための保険)
作業の手順は以下の順序が正解
- 全44件のスラッグを英語スラッグに書き換える(投稿一覧 → クイック編集)
- 設定 → パーマリンクで構造を /blog/%postname%/ に変更
- 301 Redirectsプラグインに44件のリダイレクトをCSVインポート
- エックスサーバーのサーバーキャッシュをクリア
- 動作確認
ポイントは1番。スラッグを書き換えても、現行のパーマリンク設定にはスラッグが含まれていないため、 URLは旧URLのまま で何も影響が出ない。これにより、44件分の地味なクイック編集作業を、本番サイトに何のリスクも与えずゆっくり進められる。
2〜4は連続して一気に行う。ここはサイトに直接影響が出るフェーズなので、深夜やアクセスが少ない時間帯の作業を推奨。
301 Redirectsプラグインにインポートした、リダイレクト定義CSVのサンプルはこんな形式である。
| Status | Request URL(旧URL・先頭スラッシュなし) | Redirect To(投稿ID) |
|---|---|---|
| 301 | blog/2014/02/19124616_122.html | 122 |
| 301 | blog/2014/02/20195634_153.html | 153 |
| 301 | blog/2014/02/21130304_125.html | 125 |
| 301 | blog/2014/03/18163938_279.html | 279 |
| … | … | … |
3列構成で、ヘッダーなし、CRLF改行、ASCIIエンコーディング。これは既存リダイレクト25件をエクスポートしたCSVの形式と同一にしている(プラグインの仕様にぴったり合わせるため)。
ハマった話:リダイレクトループに陥った
正解の手順を上に書いたが、最初は別の順序で進めて派手にハマった。共有しておく。
ビフォー/アフターを並べると、こうなる。
| 最初に試した順序(失敗) | 正しい順序(成功) | |
|---|---|---|
| 1 | スラッグ書き換え | スラッグ書き換え |
| 2 | 301 RedirectsにCSVインポート | パーマリンク変更 |
| 3 | パーマリンク変更 | 301 RedirectsにCSVインポート |
| 4 | (キャッシュクリア) | サーバーキャッシュクリア |
| 5 | (動作確認) | 動作確認 |
差は2と3の入れ替えだけ。ただこの一手の違いで、サイト全体が表示できなくなるか、何事もなく移行が完了するかが決まる。
最初に「リダイレクトを先に仕込んでおけば、パーマリンク変更時の404ゼロを実現できる」と考えたのが理由だった。論理は通っているように見えたが、見落としがあった。
CSVインポート直後、サイトを開くとブラウザに無慈悲な画面が出た。

このページは動作していません
nmbr.jp でリダイレクトが繰り返し行われました。
ERR_TOO_MANY_REDIRECTS
リダイレクトループ。原因は冷静に考えれば自明だった。
- 旧URL blog/2014/02/19124616_122.html にアクセス
- 301 Redirectsプラグインが「投稿ID 122 の現在のURLにリダイレクトせよ」と判断
- 投稿ID 122 の現在のURLは…パーマリンク変更前なので、 同じ blog/2014/02/19124616_122.html
- そのURLにアクセスすると、またリダイレクトが発動 → 無限ループ
投稿ID指定リダイレクトは、リダイレクト先が「投稿IDが解決する現在のURL」になる。そして「投稿IDが解決するURL」はパーマリンク設定に依存する。 パーマリンク変更前は、解決結果が旧URL自身になってしまうため、ループが発生する。
復旧は単純で、追加した44件をすべて削除すればよかった。1件ずつDeleteボタンで削除し、サイトの動作確認をして無事復旧。バックアップに手を出す事態には至らずほっとした。
教訓としては明快で、 投稿ID指定の301リダイレクトは、パーマリンク変更後に登録する 。これだけ。
後処理: Search Console へのサイトマップ送信
本番反映後、Google Search Consoleで該当プロパティを開き、サイトマップ(sitemap.xml)を再送信した。Googleが新URLを認識するまでには数日〜1週間ほどかかるが、サイトマップ送信で多少早まる。
旧URLについては、301リダイレクトされている限り、Googleが自動的に「恒久的に移動した」と認識してくれる。明示的な申請は不要。
Claudeに依頼した内容まとめ
本作業ではAnthropicのClaude(AIアシスタント)に多くの工程を任せた。何をAIに依頼し、何が成果物として出てきたかを一覧にしておく。
| フェーズ | Claudeに依頼した内容 | 成果物 |
|---|---|---|
| 事前調査 | .htaccess の中身を渡し、サイトの構成を解説してもらう | サブディレクトリ構成だと特定 |
| 事前調査 | 既存リダイレクトのエクスポートCSVから、登録形式を特定してもらう | 「投稿ID指定方式」だと判明 |
| データ準備 | WordPress XML から、公開済み44記事の情報を抽出してもらう | 記事一覧CSV(タイトル+旧URL+投稿ID) |
| データ準備 | 各記事に英語スラッグ案を考えてもらう | 44件分のスラッグ案 |
| データ準備 | 旧URLの末尾の数字が投稿IDだと気づいてもらい、抽出する | 投稿ID付きの対応表 |
| データ準備 | 301 Redirects 用のCSVを生成してもらう | インポート用CSV(44行) |
| 手順設計 | 全体の作業手順と、本番反映時の順序を整理してもらう | 手順書 |
| 失敗復旧 | リダイレクトループの原因分析 | 「投稿ID指定はパーマリンク変更後に登録すべき」という気づき |
| 後処理 | Search Console へのサイトマップ送信手順 | 手順説明 |
ファイル生成の作業は、いずれもこちらが情報(XMLや既存CSV)を渡し、Claudeが Python スクリプトで処理して出力したものを受け取る、という流れで進めた。書き出された44行のCSVを目視で確認したうえで、本番に投入している。
AIアシスタントとの協業について
最後に。本作業はAnthropicのClaudeと対話しながら進めた。
調査・準備フェーズの効率化は劇的だった。 .htaccess の中身を見せて構成を即座に解読、エクスポートCSVから既存リダイレクトの形式を特定、44件分のスラッグ案とCSVを数十秒で生成する、といった作業はAIなしでは半日以上かかったはず。今回の作業全体の所要時間は、調査も含めて1〜2時間程度に収まった。
ただし、リダイレクトループ事件は、まさにAI協業の落とし穴だった。 「投稿ID指定の方が将来安全(スラッグ変更にも自動追従するから)」という判断はAI側からの提案で、論理的には正しかった。だが「パーマリンク変更前に登録するとループする」という前提条件をAIも私も見落としていた。
結果、 AIの提案を信じて実行した結果、本番サイトの全記事が表示できなくなる という瞬間が発生した。バックアップは取っていたので最悪の事態にはならなかったが、肝は冷えた。
ここから得た教訓は3つ。
- AIとの協業は、調査と準備のスピードを大幅に上げる。これは間違いなく恩恵
- しかしAIの提案は「論理的に正しいが、前提条件を見落としている」可能性が常にある。本番反映前に自分の頭で再検証する工程を必ず挟む
- バックアップは必ず取る。AIが「絶対大丈夫」と言っても
最後の点は、自分でやる作業でも当然のことなのだが、AIと組むと「AIが大丈夫と言ったから」と無意識に省略してしまう誘惑がある。今回は手順としてバックアップ取得を最初に組み込んでいたから救われた。
WordPressのパーマリンク変更は、サイト運営者なら一度は検討するテーマだろう。AIアシスタントを活用すれば早く進むが、各所での確認は欠かせない。本記事が、これから同じ作業をされる方の参考になれば幸いである。

コメント