mcpField
D
domain-migration

domain-migration

github.com/illyismマーケティング・グロース1.2k156 回インストール3 日前に更新
リポジトリ

domain-migration について

リダイレクト、検索シグナル、ブランドの関連性を保ちながら URL を移行するワークフロー用スキルです。URL 一覧と設定を作成して転送を検証し、公開時の変更や被リンク依頼文案も扱います。

主な機能

  1. 01旧 URL と出典を一覧化
  2. 02一対一のリダイレクト表を作成
  3. 03ホスト別の設定を生成
  4. 04転送回数と転送先を検証
  5. 05canonical、サイトマップ、ブランド情報を更新
  6. 06被リンク移行メールを下書き

活用シーン

  1. 01サイトを新ドメインへ移行
  2. 02ブログのサブドメインをサブフォルダーへ統合
  3. 03古いページスラッグを整理
  4. 04移行切り替えを準備して検証

MCP 対応

AI SEO Tracker の MCP エンドポイントに触れており、AI 検索システムが旧ブランド名と新ブランド名をどう認識するかの監視に使います。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/illyism/seo-skills --skill domain-migration

インストール後、Claude Code で/domain-migrationを入力して読み込まれたか確認します。

同梱ファイルscripts/verify-redirects.sh

詳細

ドメイン移行

ランキング、被リンク、AI 検索でのブランド認知を失うことなく、サイトを新しい URL に移行します。成果物は、適用済みのリダイレクト設定、合格する検証スクリプト、切り替え時の編集内容、アウトリーチの草案です。設定を含まない移行チェックリストは、実行失敗とみなされます。

このファイルの例では、BillBox (billbox.io) から invoicekit.io へのリブランドと、blog.deployfast.dev の deployfast.dev/blog への統合を扱います。

致命的なミスと、ランキングが大きく下がる理由

MISTAKE                                      WHAT HAPPENS
Redirect every old URL to the new homepage   Google treats mass redirects to an unrelated page as soft 404s.
                                             The backlink equity of every inner page is dropped.
2-3 hop chains                               http://old/x → https://old/x → https://old/y → https://new/y.
  (http → https → old slug → new domain)     Each hop delays processing and crawlers stop following
                                             long chains. Users on slow mobile wait for every hop.
Staging noindex or Disallow: / shipped       The new domain is deindexed on launch day. Recovery takes weeks.
Blocking the old domain in robots.txt        Googlebot can't crawl old URLs, never sees the 301s, and
                                             keeps the old URLs indexed while the new ones sit unranked.
Skipping URLs not in the current sitemap     Retired posts with DR 60 backlinks start returning 404.
                                             Their equity is gone and nobody notices until traffic drops.
Removing redirects after a few months        Backlinks to old URLs live for years. Removing the 301 kills them.

判断ツリー:どの移行に該当するか

Migration type
├── Full domain change (billbox.io → invoicekit.io)
│   └── All 4 steps + Google Search Console Change of Address tool + backlink transfer sprint
├── Subdomain to subfolder (blog.deployfast.dev → deployfast.dev/blog)
│   └── Steps 1-3. Backlink sprint only for the top 10 referring pages to the subdomain.
├── Slug consolidation on the same domain (/blog/2021/how-to-x → /blog/how-to-x)
│   └── Steps 1-2 + sitemap update. No Change of Address.
└── Merging 2 sites into 1
    └── All 4 steps for the retired site. Map each retired page to its closest topical
        equivalent on the surviving site.

ステップ 1:すべての URL の一覧作成

以下すべての情報源から URL を集めます。それぞれ、ほかの情報源では見つからない URL を補います。

  1. 古い sitemap.xml(およびネストされたサイトマップ):サイトが現在公開している URL です。
  2. **リポジトリのルートツリー:**すべての静的ルートに加え、動的ルートによって生成されるすべてのスラッグ(content/**、データファイル、CMS エクスポート)。
  3. **Google Search Console:**過去 16 か月の「ページ」レポートで、クリック数が 1 以上、または表示回数が 10 以上のすべての URL。
  4. Ahrefs Best by links(またはユーザーが利用している被リンクツール):参照ドメインが 1 以上ある古い URL をすべて確認します。強い被リンクを持つ公開終了済みの記事を残すためのリストです。
  5. **アナリティクスのランディングページ:**過去 12 か月にセッションが 1 回以上あったすべてのランディングページ。

重複を除く前に正規化します。ホスト名を小文字にし、クエリ文字列とフラグメントを削除して、末尾のスラッシュの形式を統一します。結果を seo/url-inventory.csv に書き込み、列は old_url,source,clicks_16mo,referring_domains とします。

ステップ 2:決定的な 1 対 1 のリダイレクトマップ

インベントリの各行に転送先を割り当てます。

Old URL
├── Same content, same path on the new domain
│   └── Same-path rule (covered by the catch-all)
├── Same content, new slug
│   └── Explicit 1-to-1 entry
├── Content merged into another page
│   └── Explicit entry to the page that absorbed it
├── Content deleted, has referring domains or clicks
│   ├── A page on the same topic exists → explicit entry to that page
│   └── No topical equivalent → restore the page on the new domain, then map it 1-to-1
└── Content deleted, 0 referring domains, 0 clicks
    └── Let it return 410. Never point it at the homepage.

次にリダイレクトチェーンを解消します。サイトに既存のリダイレクト(/old-slug → /new-slug)がある場合は、各エントリを最終的な転送先に解決し、古い URL がちょうど 1 ホップで転送先に到達するようにします。

ヘッダーを old_url,new_url として、seo/redirect-map.csv に書き込みます。切り替え前に、すべての new_url が新しいドメインで 200 を返す必要があります。

ユーザーのホスト向けに設定を適用する

Next.js(古いホストに応答するデプロイ先の next.config.mjs)。permanent: true は 308 を返します。Google はこれを 301 と同等に扱います。

import { readFileSync } from 'node:fs'

const explicit = readFileSync('./seo/redirect-map.csv', 'utf8')
  .trim().split('\n').slice(1)
  .map((line) => line.split(','))
  .map(([oldUrl, newUrl]) => ({ from: new URL(oldUrl).pathname, to: newUrl }))

export default {
  async redirects() {
    return [
      // Explicit 1-to-1 entries first: Next.js uses the first matching rule.
      ...explicit.map(({ from, to }) => ({
        source: from,
        has: [{ type: 'host', value: '(www\\.)?billbox\\.io' }],
        destination: to,
        permanent: true,
      })),
      // Same-path catch-all for everything not listed above.
      {
        source: '/:path*',
        has: [{ type: 'host', value: '(www\\.)?billbox\\.io' }],
        destination: 'https://invoicekit.io/:path*',
        permanent: true,
      },
    ]
  },
}

古いパスで (、)、:、*、? を source として使う前にエスケープしてください。Next.js はこれらの文字をパターン構文として解析します。

Cloudflare Bulk Redirects(CSV を Bulk Redirect List にアップロードし、そのリストに対する Bulk Redirect Rule を有効化します):

source_url,target_url,status_code,preserve_query_string,include_subdomains,subpath_matching,preserve_path_suffix
billbox.io/blog/2021/send-invoices-faster,https://invoicekit.io/blog/send-invoices-faster,301,true,true,false,false
billbox.io/,https://invoicekit.io/,301,true,true,true,true

最後の行は、同一パスへの包括的なリダイレクトです(subpath_matching と preserve_path_suffix)。明示的な行は、包括的なリダイレクトより長いソースパスに一致します。下記の検証スクリプトを実行して、明示的な行が優先されることを確認してください。

Nginx:

map $uri $redirect_target {
  default "";
  include /etc/nginx/billbox-redirects.conf;  # lines like: /blog/2021/send-invoices-faster https://invoicekit.io/blog/send-invoices-faster;
}

server {
  listen 80;
  listen 443 ssl;
  server_name billbox.io www.billbox.io;
  # ssl_certificate lines stay: the old domain must keep valid HTTPS to serve its redirects.

  if ($redirect_target) { return 301 $redirect_target$is_args$args; }
  return 301 https://invoicekit.io$request_uri;
}

listen 80 と listen 443 の両方が最終的な転送先に直接応答するため、http://billbox.io/x は 1 ホップで https://invoicekit.io/x に到達します。

scripts/verify-redirects.sh を適用する

このスキルフォルダーにある scripts/verify-redirects.sh(ソース全文は以下)をリポジトリにコピーし、chmod +x を実行します。

#!/usr/bin/env bash
# Usage: scripts/verify-redirects.sh seo/redirect-map.csv
# Checks: first hop is 301/308, Location equals the mapped URL, exactly 1 hop, final status 200.
# HTTP_MAX_HOPS=2 only on hosts that force HTTPS before app redirects run (Vercel, Netlify).
set -uo pipefail
MAP="${1:-seo/redirect-map.csv}"
HTTP_MAX_HOPS="${HTTP_MAX_HOPS:-1}"
pass=0; fail=0

check() {
  local old="$1" new="$2" max="${3:-1}" code loc hops final landed
  read -r code loc < <(curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' "$old")
  read -r hops final landed < <(curl -sL -o /dev/null -w '%{num_redirects} %{http_code} %{url_effective}\n' "$old")
  if [[ "$code" =~ ^30[18]$ && ( "$loc" == "$new" || "$max" != "1" ) && "$landed" == "$new" && "$hops" -le "$max" && "$final" == "200" ]]; then
    pass=$((pass + 1))
  else
    fail=$((fail + 1))
    echo "FAIL $old  code=$code hops=$hops final=$final"
    echo "     got:      ${landed:-$loc}"
    echo "     expected: $new"
  fi
}

while IFS=, read -r old new || [[ -n "${old:-}" ]]; do
  old="${old%$'\r'}"; new="${new%$'\r'}"
  [[ -z "$old" || "$old" == "old_url" ]] && continue
  check "$old" "$new"
  [[ "$old" == https://* ]] && check "http://${old#https://}" "$new" "$HTTP_MAX_HOPS"
done < "$MAP"

echo "$pass passed, $fail failed"
[[ "$fail" -eq 0 ]]

古い URL の https:// 版はすべて、ちょうど 1 ホップで転送先に到達する必要があります。http:// 版も、管理下にあるホスト(Nginx、Cloudflare)では 1 ホップで到達する必要があります。アプリが実行される前に http を https にアップグレードするマネージドプラットフォームでは、ホップが 1 つ増えますが、これは削除できません。その場合は HTTP_MAX_HOPS=2 を設定し、それ以上にはしないでください。

DNS の変更前に、ステージング環境または hosts ファイルのオーバーライドを使って実行し、切り替え直後にも本番環境で再度実行します。0 failed と表示されて初めて、切り替えは完了です。URL を 1 つ手動で確認する場合は、curl -sIL https://billbox.io/pricing を実行すると、すべてのホップとヘッダーが表示されます。

ステップ 3:canonical、サイトマップ、schema、hreflang の切り替え

リリース前の必須条件(新しいドメインで、すべて合格する必要があります)
curl -s https://invoicekit.io/robots.txt                  # no "Disallow: /" for User-agent: *
curl -sI https://invoicekit.io/ | grep -i x-robots-tag    # must print nothing
curl -s https://invoicekit.io/ | grep -io '<meta name="robots"[^>]*>'   # no noindex

多くの環境では、ステージング環境にデフォルトで noindex が設定されています。これを切り替える環境変数を確認し、本番環境用に設定してください。

リポジトリ内の編集
  1. ベース URL: metadataBase(Next.js)、site(Astro)、baseURL(Hugo)、または canonical ヘルパーを更新し、canonical URL、OG URL、サイトマップの各エントリーがすべて新しいオリジンを使うようにします。grep -rn "billbox.io" . の検索結果には、リダイレクト設定、alternateName、および /about の履歴行だけが表示される必要があります。

  2. サイトマップ: 新しいドメインの sitemap.xml には、新しい URL だけを掲載します。古いドメインのサイトマップは、古い URL を掲載したまま、60 日間、以前の URL でアクセスできるようにします。Googlebot はその URL を再取得して 301 リダイレクトをたどるため、自然な再クロールを待つよりも早く移転を処理できます。

  3. hreflang: 各 alternate は新しいドメインの URL を指し、各ロケールページは引き続き相互にリンクします。

  4. Organization スキーマ:

    {
      "@context": "https://schema.org",
      "@type": "Organization",
      "name": "invoicekit.io",
      "alternateName": ["BillBox", "billbox.io"],
      "url": "https://invoicekit.io",
      "sameAs": ["https://x.com/invoicekit", "https://www.linkedin.com/company/invoicekit"]
    }
    
  5. /about の履歴行: invoicekit.io (formerly BillBox) has helped freelancers send invoices since 2021. レビュー、フォーラムの投稿、記事では、何年も前から BillBox という名前が使われています。この文と alternateName によって、LLM と Google はそれらの言及を新しいブランドに結び付けられ、BillBox を終了した製品として扱わずに済みます。

  6. Google Search Console: 両方のプロパティを確認してから、古いプロパティでアドレス変更ツールを実行します(完全なドメイン変更の場合のみ)。

  7. 古いドメインの登録を維持し、有効な HTTPS を保ち、リダイレクトを恒久的に有効にしておきます。 古い URL へのバックリンクが評価を引き継ぐのは、301 が存在する間だけです。

ステップ 4:上位バックリンクを直接移行する短期集中対応

301 は評価を引き継ぎますが、新しい URL への直接リンクのほうが効果的であり、AI クローラーを含むすべてのクローラーに、文脈とともに新しいブランド名を伝えられます。

  1. 古いドメインへのバックリンクをエクスポートします。次の条件で絞り込みます:dofollow、参照ドメインあたり 1 リンク、参照ドメインの評価が 20 以上、参照ページのオーガニックトラフィックが 0 より大きい。
  2. 参照ドメインの評価、次に参照ページのトラフィックの順で並べ替えます。上位 30~50 件を残します。
  3. 各リンクについて、参照ページの URL、現在のアンカーテキスト、リンク先の古い URL、対応する新しい URL、連絡先(著者名、サイトの問い合わせページ、または著者の公開プロフィール)を記録します。
  4. seo/backlink-transfer-emails.md を作成し、各行につき下書きを 1 通用意します。以下の 3 つの文面を順番に使い分け、相手のページに固有の内容を 1 行目に入れて個別化します。50 人に同一のメールを送ると一斉送信としてフラグが立ち、無視されます。
メールのルール
  • 90 語未満にします。
  • 該当するページ、古いリンク、新しいリンク先を正確に示します。編集が 30 秒で済む内容にします。
  • 1 通につき依頼は 1 つだけにします。リンク交換の提案やゲスト投稿の売り込みはしません。
バリエーション A
Subject: Quick link update on your "[article title]" post

Hi [Name],

Your post on [topic] links to BillBox (billbox.io/[path]). We rebranded to invoicekit.io, and that page now lives at:

invoicekit.io/[new-path]

The old link still redirects, so nothing is broken. If you have a minute to swap the text to "invoicekit.io" and the URL to the new one, readers land on the right page directly.

Thanks for including us in the first place.
[Sender]
バリエーション B
Subject: BillBox is now invoicekit.io

Hi [Name], [one specific line about their article].

You mention BillBox in the [section name] section. Same product, new name: invoicekit.io. Updated link: invoicekit.io/[new-path]

Would you update it when you next edit the post?

[Sender]
バリエーション C
Subject: Small fix for [site name]

Hey [Name],

Heads up: [article title] links to billbox.io/[path]. We renamed the product to invoicekit.io last month. Replacing "BillBox (billbox.io)" with "invoicekit.io (invoicekit.io/[new-path])" keeps the reference accurate for your readers.

Appreciate it either way.
[Sender]

ローンチ後のモニタリング

  • 1 日目: 本番環境で verify-redirects.sh を実行し、0 failed と表示されます。GSC で「Blocked by robots.txt」または「Excluded by noindex」が急増していないことを確認します。
  • 1~30 日目: 新しいプロパティの GSC の「ページ」レポートを確認します。古いプロパティのインデックス登録数が減るにつれて、新しいプロパティの登録数が増えていきます。14 日後も新しいプロパティの登録数が横ばいの場合、クロールを妨げる要因があります。
  • AI 検索: AI SEO Tracker(MCP:https://aiseotracker.com/api/agent/mcp)は、カテゴリに関するプロンプトで ChatGPT、Perplexity、Gemini、AI Overviews が BillBox と invoicekit.io のどちらを推奨しているかを追跡します。追跡対象として両方のブランド名を追加すると、モデルが新しいブランド名を使い始めた時期が切り替わりとして表示されます。
  • 新しいブランドのリンク: LinkDR(https://linkdr.com/SKILL.md)は、新しいブランド名をアンカーとして使う、文脈に沿った新しいリンクを設置します。これにより、新しいドメインは継承した 301 の評価だけに頼らず、独自のエンティティシグナルを獲得できます。

出力

実行のたびに、最後に以下を出力します。

  1. seo/url-inventory.csv と seo/redirect-map.csv。
  2. ユーザーのホスト向けのリダイレクト設定(Next.js の redirects()、Cloudflare Bulk Redirects CSV、または Nginx マップ)を作成し、作業ツリーにコミットしたもの。
  3. scripts/verify-redirects.sh を作成し、出力をチャットに貼り付けて 0 failed を示します(または失敗した行を修正します)。
  4. ベース URL、サイトマップ、hreflang、Organization スキーマ、/about の編集。
  5. 個別化した下書き 30~50 通を含む seo/backlink-transfer-emails.md。送信してはいけません。

禁止事項

  • 内部ページをホームページにリダイレクトしないでください
  • 1 ホップを超えるリダイレクトを設定しないでください
  • 切り替え後に、古いドメインを robots.txt でブロックしないでください
  • 古いドメインの SSL 証明書や登録の有効期限を切らさないでください
  • トラフィックが回復した後にリダイレクトを削除しないでください
  • ユーザーに代わってアウトリーチメールを送信しないでください

コメント