Claudeでサイトリニューアルの301対応表を作る — 旧URLの突き合わせから転送漏れの検証まで
旧サイトのURL一覧と新サイトのURL一覧をClaudeで突き合わせ、301の対応表にする手順です。転送漏れ・チェーン・不要な転送をcurlで機械的に検証する部分は、手元で動くスクリプト付きで示します。
対応づけはClaudeに、転送の合否判定はcurlのスクリプトに分ける
サイトをリニューアルしてURLが変わるとき、旧URLから新URLへの301の対応表が要ります。数百から数千行を人が目で突き合わせると、必ずどこかで取り違えます。分け方はこうです。
- 旧URLと新URLの対応づけの下書きは、CSVを渡したClaudeが作る
- 転送が実際に正しく動くかの判定は、curlを回すスクリプトが行う
- 対応づけの採否と、廃止ページの扱いは人が決める
Claudeが出した対応表は、あくまで下書きです。サーバーに設定して初めて意味を持つので、設定後に旧URLを実際に叩いて確かめる工程まで含めて、1つの作業と考えてください。
この記事では、対応表の列設計、突き合わせの進め方、転送漏れの検証スクリプト、公開後の見守りまでを順に扱います。タイトルやmeta descriptionの一括下書きはClaudeでメタディスクリプションとtitleを一括で下書きして検査する、公開後の流入の確認はClaude CodeでGA4とSearch Consoleを突き合わせる手順にあります。
対応表は4列で足りる — 旧URL・新URL・種別・メモ
最初に決めるのは表の形です。列が多いほどClaudeの出力がぶれるので、最小限に絞ります。
old_url,new_url,rule,note
https://example.com/blog/2019/05/hello,https://example.com/articles/hello,one-to-one,
https://example.com/news/a,https://example.com/news,merge,一覧に統合
https://example.com/campaign/2018,,gone,終了したキャンペーンruleは3種類に固定します。
| rule | 意味 | 期待する応答 |
|---|---|---|
| one-to-one | 意味1対1で移る | 期待する応答旧URLが301で新URLを指し、新URLが200 |
| merge | 意味複数ページが1つに統合される | 期待する応答同上(複数の旧URLが同じ新URLを指す) |
| gone | 意味対応する移転先がない | 期待する応答404か410(転送しない) |
goneを表に入れておく理由は、転送先が見つからない旧URLを、とりあえずトップページへ送る誘惑が生じるためです。Googleのサイト移転ガイドは、多数の旧URLを無関係な単一のURL(新サイトのトップページなど)へ転送しないよう求めています。ユーザーが混乱し、ソフト404として扱われることがあるためです。一方で、複数ページを1つの新ページに統合したのなら、旧URLをその統合先へ転送してかまいません。mergeとgoneを分けておけば、この線引きを表の上で判断できます。
旧URLの一覧を先に固める
突き合わせの精度は、旧URLの一覧が網羅されているかで決まります。入手先は、Googleのガイドが次のように挙げています。
- サイトマップ(重要なURLはSearch Consoleへ送信済みであることが多い)
- サーバーログやアクセス解析で、トラフィックの多いURL
- Search Consoleの「サイトへのリンク」で、内部・外部リンクが付いているページ
- CMSが出力する、コンテンツのあるURLの一覧
- サーバーログで、直近に1回でも訪問のあったURL(季節変動を考えて期間を選ぶ)
画像・動画・JavaScript・CSSなど、埋め込まれたコンテンツのURLも、他のページと同じ扱いで移す対象に含めるとされています。HTMLページだけの一覧で対応表を作ると、画像のURLが丸ごと漏れます。
これらを1つのCSVに集め、old_urlの列で重複を除いてから、Claudeに渡します。
Claudeへの渡し方 — 旧URLと新URLのCSVに規則を添える
Claudeのチャット画面(Web・デスクトップ)で使うなら、コード実行とファイル作成の機能を有効にします。公式ヘルプによれば、この機能はFree・Pro・Max・Team・Enterpriseのどのプランでも使え、CSVやTSVのアップロードと分析に対応します。アップロードもダウンロードも、1ファイルあたり最大30MBです。数万行のURL一覧でも、通常はCSVとして収まります。
渡すものは2つのCSVと、規則の文章です。プロンプトは例えば次のような形にします。
添付の old_urls.csv(旧サイトのURL一覧、列: url, 月間PV)と
new_urls.csv(新サイトのURL一覧、列: url, title)を突き合わせて、
旧URLごとに転送先を決め、map.csv を出力してください。
列は old_url,new_url,rule,note の4つ。
rule は one-to-one / merge / gone のどれか。
規則:
- 末尾スラッシュとクエリ文字列を除いたパスが一致するものは one-to-one
- パスが違っても、titleと内容から同じページと判断できるものは one-to-one とし、
note に判断の根拠を1行で書く
- 自信がない行は new_url を空にして rule を review にし、候補を note に最大3つ書く
- トップページや一覧へ「とりあえず」送る行は作らないポイントは最後の2行です。確信がない行をreviewとして出させると、Claudeが無理に埋めた誤った対応が、確信のある行に紛れ込みません。後で人が見るのは、reviewの行と、noteに根拠が書かれた行に絞れます。
出力の確認では、old_urlの件数が入力と一致するか、new_urlがすべてnew_urls.csvに実在するかを数えます。後者は、Googleのガイドが「新サイトに存在しないURLへ転送している例をよく見る」と指摘する誤りそのものです。Claudeに任せず、次のスクリプトで確かめます。
import csv
new_urls = {r["url"] for r in csv.DictReader(open("new_urls.csv", encoding="utf-8"))}
old_urls = [r["url"] for r in csv.DictReader(open("old_urls.csv", encoding="utf-8"))]
rows = list(csv.DictReader(open("map.csv", encoding="utf-8")))
mapped = {r["old_url"] for r in rows}
print("旧URLの件数:", len(old_urls), "/ 対応表の行数:", len(rows))
print("対応表にない旧URL:", sorted(set(old_urls) - mapped)[:20])
print("対応表だけにある旧URL:", sorted(mapped - set(old_urls))[:20])
for r in rows:
if r["rule"] in ("one-to-one", "merge") and r["new_url"] not in new_urls:
print("新サイトに存在しない転送先:", r["old_url"], "->", r["new_url"])
if r["rule"] == "review":
print("要判断:", r["old_url"], r["note"])「対応表にない旧URL」が1件でも出たら、それが転送漏れの候補です。Claudeが出力の途中で行を飛ばすことは、行数が多いほど起きやすくなります。数えて確かめる工程は省けません。
curlで転送を検証する — 設定後に旧URLを実際に叩く
対応表をサーバーに設定したら、旧URLを1本ずつ叩いて結果を表にします。ここはClaudeの画面ではなく、手元のターミナルかClaude Codeで実行します。理由は、claude.aiのコード実行環境が自分のサイトへ接続できるとは限らないためです。公式ヘルプでは、Team・Enterpriseの組織はネットワークアクセスをオーナーが制御し、許可するドメインを個別に指定できます。既定値の説明も、Availabilityの節では「無効」、設定の節では「パッケージマネージャーのみ許可」と書かれていて、ページ内で揃っていません。自分の組織でどうなっているかは、管理者に確認してください。
検証スクリプトは次の形です。1回目のcurlで最初の応答(転送の1段目)を、2回目のcurlで最終到達点とホップ数を取ります。
cat > verify.sh <<'SH'
#!/usr/bin/env bash
# 使い方: ./verify.sh map.csv > report.csv
echo "old_url,expected,first,location,final,hops,verdict"
tail -n +2 "$1" | while IFS=, read -r old new rule _; do
read -r s1 loc <<< "$(curl -s -o /dev/null \
-w '%{http_code} %{redirect_url}' "$old")"
read -r sf hops url <<< "$(curl -s -o /dev/null -L --max-redirs 10 \
-w '%{http_code} %{num_redirects} %{url_effective}' "$old")"
v=NG
if [ "$rule" = gone ]; then
case "$s1" in 404|410) v=OK;; esac
elif [[ "$s1" =~ ^30[18]$ && "$loc" = "$new" \
&& "$sf" = 200 && "$hops" = 1 ]]; then
v=OK
fi
echo "$old,$new,$s1,$loc,$sf,$hops,$v"
sleep 0.2
done
SH
chmod +x verify.sh && ./verify.sh map.csv > report.csv
grep -c ',NG$' report.csv判定の基準は、Googleのガイドに沿っています。
- 1段目が301か308であること(Googleは恒久的なサーバー側転送を勧め、301と308を例に挙げています)
- 1段目の転送先が、対応表の
new_urlと一致すること - 最終応答が200で、ホップ数が1であること。Googlebotは最大10ホップまで追いますが、最終到達先へ直接転送するよう勧められています。チェーンが避けられない場合も、3回以内、できれば5回未満に抑えるのが目安です
sleep 0.2を入れているのは、数千行を一気に叩いてサーバーに負荷をかけないためです。移転後はGoogleのクロールも増えるので、サーバーの処理能力に余裕があるかも合わせて見てください。
Claude Codeで実行するなら、report.csvのNG行を読ませて原因別に分類させる使い方ができます。たとえば次のように頼みます。
report.csv の NG 行を、次の4つに分類して件数と代表例を出してください。
1. 転送されていない(first が 200 や 404)
2. 転送先が対応表と違う(location != expected)
3. チェーンになっている(hops が 2 以上)
4. 転送先が 200 でない
分類したら、直す順序を提案してください。まだサーバー設定は変更しないでください。最後の一文が大事です。検証の段階では読み取りだけにして、設定の書き換えは分類を人が見てから頼みます。
落とし穴
curlが通っても、新サイトの側に残りものがある
転送が正しくても、移行中だけ付けたnoindexやrobots.txtのブロックが新サイトに残っていると、新URLはインデックスされません。Googleのガイドは、移行のためだけに必要だったこれらを外し忘れないよう注意しています。robots.txtがない場合は、200で何かを返すのではなく404を返す必要があります。あわせて、新サイトの各ページに、自分自身を指すrel="canonical"があるかも確認します。
公開前後にやることの順序
転送そのもの以外にも、順番を守ると事故が減る作業があります。Googleのガイドに沿って並べると次のとおりです。
転送開始の前後で行うこと
- 1
新サイトの準備を終える
新URLごとに自己参照のrel="canonical"を付け、hreflangがあれば新URLに更新します。内部リンクは旧URLから新URLへ書き換えます。対応表は内部リンクの置換にも使えます。
- 2
新サイトのサイトマップを用意する
対応表の新URLだけを載せたサイトマップを作っておきます。転送の開始後にSearch Consoleへ送信します。
- 3
転送を有効にしてcurlで検証する
小さなサイトや中規模のサイトは、全URLを同時に移すよう勧められています。大規模サイトは、セクションごとに分けて、問題を見つけやすくする選択もできます。
- 4
ドメインやサブドメインが変わるときだけ、アドレス変更を送信する
同じドメイン内でパスだけが変わる移転や、HTTPからHTTPS、wwwの有無の切り替えでは、このツールは要りません。
- 5
リンクを更新する
内部リンクに加え、外部サイトからの被リンク、SNSのプロフィールリンク、広告の遷移先も、可能な限り新URLに直します。
転送は、できるだけ長く残します。Googleは一般に最低1年を目安にしており、ユーザーの側から見れば無期限に残すことも考えてよいとしています。ただし転送は表示が遅くなるので、自社のリンクや、流入の多い外部リンクは新URLに直す努力が要ります。
公開後の確認 — 順位の揺れは移転中の通常動作
移転が始まったら、新旧両方のサイトでユーザーとクロールの動きを見ます。旧サイトの流入が減り、新サイトが増える形が望ましい姿です。Googleは、小さなサイトから中規模のサイトでは、大半のページの移動に数週間かかり、大きなサイトはそれ以上かかると説明しています。検索での表示が一時的に上下するのも通常だとされているので、数日の揺れで転送を作り直す必要はありません。
見るべき点は次のとおりです。
- Search Consoleで「見つかりません」が異常に増えていないか。転送先のURLが誤っていると、ここに出ます
- インデックスの状況に、移行中に急増したエラーがないか
- サイトマップが新URLに更新されているか
流入が伸びないページを探す作業は、Claude CodeでGA4とSearch Consoleを突き合わせる手順と同じ流れで進められます。Search ConsoleのCSVをClaudeに渡して優先順位をつける方法は、ClaudeにSearch ConsoleのCSVを渡してリライト優先度を決めるで扱っています。
作業量と使用上限
ファイルの作成やコード実行を使う作業は、通常のチャットより使用上限を消費しやすいと、公式ヘルプに書かれています。数千行の突き合わせを1回の会話で何度もやり直すと、上限に当たりやすくなります。対策は、突き合わせをパスの一致のように機械的にできる部分(Pythonで済む)と、内容を読まないと決められない部分(Claudeに渡す)に分け、Claudeへ渡す行を減らすことです。
たとえば、パスが一致する行は前述のスクリプトで先に確定させ、残りだけをClaudeに渡せば、reviewの行が絞られます。MCPのコネクタを有効にしている組織では、ネットワークの設定にかかわらずMCP経由の通信は残る、とも公式ヘルプにあります。サイトの内部データを渡すときは、どのコネクタが有効かも確かめてください。
まとめ
対応表づくりの難所は、突き合わせそのものより、確信のない行を確信のある行と混ぜないことです。Claudeにはreviewを出させる約束をして下書きを任せ、件数の照合と転送の合否はスクリプトで確かめます。
転送を開始したあとは、対応表が正しいかどうかを、旧URLを叩く以外の方法で知る手段はほぼありません。report.csvでNGが0件になり、Search Consoleの「見つかりません」が増えていないことを、移転後の最初の数週間は繰り返し確認してください。