tva
← Insights

WordPressからAstroへの移行後のSEO対策:リダイレクトチェーン、サイトマップ、GSCのクリーンアップ

WordPressからAstroへ移行すると、ビルドが速くなり、ページ表示も速くなり、ホスティングコストも下がります。しかし移行中にブログのURLが変わった場合――たとえば /post-slug/ から /insights/post-slug へ変わった場合――Googleがサイトを再クロールし終える数週間後になって初めて発覚するSEO上の問題が生じることがほぼ確実です。

Google Search Consoleからは「重複しています。Google がユーザーが指定したものとは異なる canonical を選択しました」や「見つかりません(404)の修正に失敗しました」というメールが届き始めます。パフォーマンスの高いページが不要なリダイレクトを経由することでリンクエクイティを失っている可能性もあります。また、気づかないうちに2つのサイトマップが互いに競合しているケースも珍しくありません。

このガイドでは、これらの問題を見つけて修正する方法を説明します。私たちも自社のWordPressからAstroへの移行後SEO対策の中でこれらすべての問題に直面し、その修正内容をここにまとめました。

必要なもの

  • サーバーへのSSHアクセス(nginx設定)
  • 対象プロパティのGoogle Search Consoleへのアクセス
  • ローカルにインストールされた curl
  • アナリティクスツール(当社ではセルフホスティングのPlausibleを使用)

この手順で解決できること

  • 複数ホップのリダイレクトチェーン(2回以上のリダイレクト)を単一の301リダイレクトに集約
  • 競合する複数のサイトマップを1つの自動生成ソースに統合
  • noindexページをサイトマップから除外
  • 古いGSCプロパティとWordPressの旧サイトマップを削除
  • 旧URLと新URLの構造間で生じるcanonicalの混乱を解消

ステップ1:リダイレクトチェーンの診断

主要なURLが何回リダイレクトを経由しているか確認しましょう。WordPressのURLにはトレーリングスラッシュがあり、AstroのURLにはない場合、2段階のチェーンが発生している可能性があります。1回目のリダイレクトでスラッシュが除去され、2回目で新しいパスプレフィックスが付与されるというパターンです。

curl -sL -w "Hops: %{num_redirects}, Final: %{http_code}, URL: %{url_effective}\n" \
  -o /dev/null "https://yourdomain.com/old-post-slug/"

出力に Hops: 2 と表示された場合はリダイレクトチェーンが存在します。トラフィック上位5ページについて同様に確認しましょう――失ったリンクエクイティの影響が最も大きいのはこれらのページだからです。

アナリティクスと照合することも重要です。同じ記事が複数のURLバリアント(スラッシュあり・なし・新プレフィックスあり)で表示されている場合、リダイレクトがトラフィックを正しく集約できていません。当社ではトップ記事がPlausibleで3種類のURLバリアントに分散していることが確認でき、それがチェーン問題の証拠となりました。

ステップ2:nginxを設定して単一ホップリダイレクトに修正する

nginxの標準的なトレーリングスラッシュ除去ルールは次のとおりです:

location ~ ^(.+)/$ { return 301 $1; }

これはトレーリングスラッシュを除去しますが、ブログのパス変更については考慮されていません。そのためリクエストは次のルールに渡され、/slug から /insights/slug へのリダイレクトが発生します。これで2ホップになります。

スラグがブログ記事と一致するかどうかを確認し、最終URLへ直接リダイレクトするブログ対応ルールに置き換えましょう:

# Blog slugs with trailing slash — single-hop to /insights/
location ~ ^/([^/]+)/$ {
    set $slug $1;
    if (-f /usr/share/nginx/html/insights/$slug/index.html) {
        return 301 https://yourdomain.com/insights/$slug;
    }
    return 301 https://yourdomain.com/$slug;
}
# Multi-segment paths — just strip the slash
location ~ ^(.+)/$ { return 301 $1; }

最初のルールはルートレベルのスラグ(旧WordPressブログURL)を処理します。/insights/ 配下に対応するページが存在するかどうかを確認し、そこへ直接リダイレクトします。ブログ以外のパスは汎用のスラッシュ除去ルールに流れます。デプロイ後は次のコマンドで確認してください:

curl -sL -w "Hops: %{num_redirects}\n" -o /dev/null \
  "https://yourdomain.com/your-top-post-slug/"
# Expected: Hops: 1

ステップ3:サイトマップの統合

サイトマップが複数存在しないか確認します。移行後によく見られるパターンとして、移行時に手動で作成した静的な sitemap.xml と、Astroの @astrojs/sitemap インテグレーションが自動生成する sitemap-index.xml が共存していることがあります。

# Check both
curl -sI "https://yourdomain.com/sitemap.xml" | head -1
curl -sI "https://yourdomain.com/sitemap-index.xml" | head -1

両方が200を返す場合、サイトマップが競合しています。robots.txt がどちらを参照しているか確認しましょう:

curl -s "https://yourdomain.com/robots.txt" | grep -i sitemap

対処法:public/ ディレクトリから静的な sitemap.xml を削除し、robots.txtsitemap-index.xml を参照するよう更新し、あとはAstroのインテグレーションにすべて任せましょう。新しい記事はビルドのたびに自動的に追加されます。

静的サイトマップに noindex ページが含まれていないかも確認してください。sitemap.xml<meta name="robots" content="noindex"> が設定された /legal/privacy-policy などのページが列挙されている場合、Googleに矛盾したシグナルを送ることになります。@astrojs/sitemap の自動生成サイトマップは、フィルタールールを設定することでこれらのページを正しく除外できます。

ステップ4:Google Search Consoleのクリーンアップ

GSCを開き、プロパティとサイトマップの2点を確認します。

プロパティ:ドメインプロパティ(sc-domain:yourdomain.com)とURLプレフィックスプロパティ(https://www.yourdomain.com/)の両方が登録されている場合、同じ問題について重複したアラートが届くことになります。どちらか一方に絞りましょう。サブドメインが独立したプロジェクトである場合、URLプレフィックスプロパティの方がすっきりします――本番トラフィックのみをレポートするためです。

サイトマップ:「インデックス登録」→「サイトマップ」を開きます。まだ登録されている古いWordPressのサイトマップ(post-sitemap.xmlpage-sitemap.xmlsitemap-post-type-product.xml など)をすべて削除し、新しい sitemap-index.xml だけを送信します。

404の確認:「インデックス登録」→「ページ」→「見つかりません(404)」を開き、どのURLが一覧表示されているか確認します。もはや存在しないWordPressの旧パス(WooCommerceの商品ページ、著者ページ、フィードURLなど)であれば、時間が経てば自然にインデックスから除外されます。リダイレクトされるべきブログ記事であれば、nginxのルールを更新する必要があります。リダイレクトを修正したら「修正を確認」をクリックして再クロールをリクエストしましょう。

ステップ5:全体の確認

修正をデプロイしたら、以下のチェックを実施してください:

# 1. Redirect chains resolved
curl -sL -w "Hops: %{num_redirects}, URL: %{url_effective}\n" \
  -o /dev/null "https://yourdomain.com/your-top-post/"
# Expected: Hops: 1, URL ends in /insights/your-top-post

# 2. robots.txt points to generated sitemap
curl -s "https://yourdomain.com/robots.txt" | grep sitemap
# Expected: sitemap-index.xml

# 3. Old static sitemap returns 404
curl -sI "https://yourdomain.com/sitemap.xml" | head -1
# Expected: 404

# 4. Generated sitemap returns 200
curl -sI "https://yourdomain.com/sitemap-index.xml" | head -1
# Expected: 200

# 5. Non-www redirects to www
curl -sI -o /dev/null -w "%{http_code} %{redirect_url}\n" \
  "https://yourdomain.com/insights"
# Expected: 301 https://www.yourdomain.com/insights

Googleが追いつくまでの時間

単一ホップのリダイレクトは新しいクロール時から即座に反映されます。サイトマップの変更は数日以内に反映されます。canonicalの混乱――Googleが新URLよりも旧URLを優先する状態――の解消にはもう少し時間がかかります。Googleは <link rel="canonical"> タグをディレクティブではなくヒントとして扱います。旧URLの方がバックリンクや過去のクリックデータが多い場合、Googleは数週間にわたって旧URLをcanonicalとして選び続けることがあります。

クリーンなリダイレクト、単一の権威あるサイトマップ、統合されたGSCプロパティの組み合わせにより、Googleに対して可能な限り明確なシグナルを送ることができます。当社の場合、これらの修正をデプロイしてから2週間以内に「canonicalの重複」に関する警告が減り始めました。

このような移行作業は、WordPressのパフォーマンス改善・移行支援の一環として私たちが日常的に手がけているものです。移行後のSEO問題でお困りの方は、お気軽にご相談ください


関連インサイト

関連記事