SEOを失わないCMS移行: 2026年完全ガイド
過去3年間で、40以上のサイトをWordPressからヘッドレスアーキテクチャに移行させました。完璧に進んだものもあります。つらい教訓を得たものもあります。オーガニックトラフィックを完全に保持する移行と、6ヶ月間ランキングが急落する移行の違いは、準備にあります。運ではなく。
これは、クライアントが「ヘッドレスに移行したい」と言ったときにSocial Animalで実際に使うプレイブックです。理論的ではありません。すべてのチェックリスト項目、すべてのリダイレクト戦略、すべての監視ステップは、実際に実行した移行から来ています。ほとんどはWordPressからNext.jsへですが、原理はあらゆるCMS間の移動に適用されます。
2026年の移行を計画している場合は、これをブックマークしてください。必要になります。
目次
- CMS移行がランキングを破壊する理由
- 移行前監査: 基礎
- 実際に機能する301リダイレクト戦略
- 正規タグ: 誤解されたセーフティネット
- サイトマップの保持と送信
- 技術的な移行チェックリスト
- WordPressからヘッドレスNext.jsへ: ステップバイステップ
- 移行後の監視
- 見た(そして犯した)共通の間違い
- FAQ

CMS移行がランキングを破壊する理由
Googleが気にするのはどのCMSを使用しているかではありません。URL、コンテンツ、ページ速度、内部リンク、構造化データを気にします。CMSを変更するとき、これらすべてを同時に破壊するリスクがあります。
通常、何が問題になるかを以下に示します:
- URL構造が変更される — WordPressは
/2024/03/my-post/または/category/subcategory/post-name/を使用します。新しいシステムはおそらく/blog/post-nameを使用します。これは数百または数千の壊れたURLです。 - 内部リンクが破れる — サイト内のあるページから別のページに指す内部リンクはすべて、古いURL構造用に構築されました。
- メタデータが消える — YoastまたはRankMathのSEOタイトル、メタディスクリプション、OGタグはヘッドレスCMSに自動的に転送されません。
- 構造化データが消える — プラグインのスキーママークアップは新しいフロントエンドに存在しません。
- ページ速度が変わる — 場合によっては改善されます(こんにちは、Next.js)。クライアント側レンダリングに注意しないと悪化することもあります。
2025年のAhrefsの研究によると、CMS移行を行うサイトの34%が、3ヶ月以上続く10%以上のトラフィック低下を経験しています。この問題を回避するサイトは運が良いのではなく、準備ができています。
移行前監査: 基礎
新しいプラットフォームで1行のコードを書く前に、現在のSEO状態の完全なスナップショットが必要です。これはオプションではありません。これをスキップすると、目隠しをして飛行しているようなものです。
すべてをクロールする
Screaming Frog、Sitebulb、またはAhrefs Site Auditを使用して、既存サイトの完全なクロールを取得します。必要なもの:
- すべてのURL(ページネーションページ、タグページ、著者ページを含む)
- すべてのURLのHTTPステータスコード
- すべての内部リンクとそのアンカーテキスト
- すべてのページのメタタイトルとディスクリプション
- すべてのページの正規タグ
- 多言語コンテンツがある場合はhreflangタグ
- ページごとの構造化データ
- 画像URLとaltテキスト
スプレッドシートにエクスポートします。これは移行バイブルです。
トップパフォーマーを文書化する
Google Search Consoleデータを過去16ヶ月間取得します。識別:
- オーガニッククリック数が上位100ページ
- インプレッション数が上位100ページ
- 高価値キーワードで位置1-10にランクされているページ
- 最もバックリンクが多いページ(AhrefsまたはSemrushを使用)
これらはVIPページです。最初にテストされ、最初に監視され、何か問題が発生した場合は最初に修正されます。
メトリクスをベースライン化する
移行の1週間前にこれらの数字を記録します:
| メトリック | ツール | 重要な理由 |
|---|---|---|
| インデックスされたページの総数 | Google Search Console | インデックス削除をすばやく検出 |
| オーガニックセッション/週 | GA4 | 主要な成功メトリック |
| 平均位置 | GSC | ランキング低下を検出 |
| Core Web Vitals | PageSpeed Insights | パフォーマンス比較 |
| 参照ドメインの合計 | Ahrefs/Semrush | バックリンクが解決されることを確認 |
| クロールエラー | GSC | 比較用ベースライン |
| 送信されたサイトマップページ数 対 インデックス済み | GSC | インデックス健全性を追跡 |
実際に機能する301リダイレクト戦略
これは移行が生きるか死ぬかの場所です。リダイレクトを「立ち上げ後に処理する何か」として扱う代理店を見てきました。これは一夜にしてトラフィックの40%を失う方法です。
ビルド前にすべてのURLをマップする
以下の列でリダイレクトマップスプレッドシートを作成します:
Old URL | New URL | Status Code | Priority | Notes
クロールのすべてのURLには宛先が必要です。はい、忘れていたそのタグページと著者アーカイブも含めて。
リダイレクト決定フレームワーク
| 古いページタイプ | 推奨アクション | リダイレクト先 |
|---|---|---|
| ブログ投稿(コンテンツを保持) | 301リダイレクト | 同じコンテンツの新しいURL |
| ブログ投稿(コンテンツを削除) | 最も関連のあるページへの301 | 関連ブログ投稿またはカテゴリ |
| カテゴリページ | 301リダイレクト | 同等の新しいカテゴリ/タグページ |
| タグページ(低価値) | カテゴリへの301 | 親カテゴリページ |
| 著者ページ | About/チームページへの301 | チームページまたはホームページ |
| ページネーションページ(/page/2/) | メインページへの301 | 親ページ(ページ1) |
| メディア/添付ファイルページ | 親投稿への301 | メディアを含む投稿 |
| 古いWordPressページ(/wp-admin、/xmlrpc.php) | 410 Gone | 該当なし |
| フィードURL(/feed/、/rss/) | 301または再作成 | 該当する場合は新しいフィードURL |
適切なレイヤーにリダイレクトを実装する
Next.js移行の場合、リダイレクトが存在するオプションがあります:
// next.config.js - 既知の静的リダイレクトに良い
module.exports = {
async redirects() {
return [
{
source: '/2024/03/my-old-post/',
destination: '/blog/my-old-post',
permanent: true, // 301
},
// パターンベースのリダイレクト
{
source: '/category/:slug',
destination: '/blog/category/:slug',
permanent: true,
},
]
},
}
大規模な移行(500以上のリダイレクト)の場合、通常はミドルウェアまたはエッジ関数を使用します:
// middleware.ts - 大規模なリダイレクトマップに適切
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import redirectMap from './redirects.json'
export function middleware(request: NextRequest) {
const path = request.nextUrl.pathname
const redirect = redirectMap[path]
if (redirect) {
return NextResponse.redirect(
new URL(redirect.destination, request.url),
redirect.permanent ? 301 : 302
)
}
}
export const config = {
matcher: [
// 古いWordPress URLパターンに一致
'/:year(\\d{4})/:month(\\d{2})/:slug*',
'/category/:path*',
'/tag/:path*',
'/author/:path*',
],
}
数千のリダイレクトを持つサイトの場合、CDN/エッジレベルでそれらを処理することを検討してください(Vercel Edge Config、Cloudflare Workers、またはNetlify redirectsファイル)。アプリケーションコードを膨らませないようにするためです。
すべてのリダイレクトをテストする
本気です。すべて。簡単なスクリプトを使用します:
# test-redirects.sh
while IFS=, read -r old_url new_url; do
status=$(curl -o /dev/null -s -w "%{http_code}" -L "$old_url")
final=$(curl -o /dev/null -s -w "%{url_effective}" -L "$old_url")
echo "$status | $old_url -> $final"
done < redirects.csv
立ち上げ前にステージング環境に対してこれを実行します。その後、立ち上げ直後に本番環境で再度実行します。

正規タグ: 誤解されたセーフティネット
正規タグはリダイレクトの代替ではありません。しかし、これは移行中の防御の重要な層です。
すべてのページで自己参照正規タグ
新しいサイトのすべてのページは自己参照正規タグを持つべきです:
<link rel="canonical" href="https://yourdomain.com/blog/exact-current-url" />
App Routerを使用したNext.jsの場合:
// app/blog/[slug]/page.tsx
import { Metadata } from 'next'
export async function generateMetadata({ params }): Promise<Metadata> {
const post = await getPost(params.slug)
return {
alternates: {
canonical: `https://yourdomain.com/blog/${params.slug}`,
},
}
}
移行中の一般的な正規タグの間違い
- 末尾のスラッシュの不一致 —
/blog/postと/blog/post/はGoogleにとって異なるURLです。1つを選択し、もう1つをリダイレクトし、正規タグが一致することを確認してください。 - 正規タグ内のHTTP対HTTPS — 常にHTTPSを使用します。当たり前のように聞こえますが、これが間違っているのを見ました。
- 本番環境へのステージングURLのリーク — 正規タグが
staging.yourdomain.comを指している場合、Googleにステージングサイトをインデックスするよう指示しています。QA時にこれを複数回検出しました。 - ページネーションコンテンツに欠ける正規タグ — ブログリストをページネーションする場合、各ページに独自の正規タグが必要です。ページ1を指す正規タグではありません。
サイトマップの保持と送信
新しいサイトマップをすぐに生成する
新しいサイトマップは初日から用意する必要があります。Next.jsプロジェクトの場合、サイトマップを動的に生成します:
// app/sitemap.ts (Next.js 14+/15)
import { MetadataRoute } from 'next'
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const posts = await getAllPosts() // ヘッドレスCMSから
const blogEntries = posts.map((post) => ({
url: `https://yourdomain.com/blog/${post.slug}`,
lastModified: new Date(post.updatedAt),
changeFrequency: 'weekly' as const,
priority: 0.8,
}))
const staticPages = [
{
url: 'https://yourdomain.com',
lastModified: new Date(),
changeFrequency: 'daily' as const,
priority: 1,
},
// ... その他の静的ページ
]
return [...staticPages, ...blogEntries]
}
送信戦略
- 移行前: 古いサイトマップをダウンロードして保存する
- 移行後: Google Search Consoleで新しいサイトマップをすぐに送信する
- 古いサイトマップを一時的に保持: 最初の30日間、古いサイトマップURLが適切にリダイレクトされるようにして、Googleがチェーンを追うことができるようにします
- GoogleのURL Inspection ツールを使用: トップ50のVIPページをリクエストしてインデックスを手動でリクエストします
- 最初の2週間、Index Coverage レポートを毎日監視
robots.txtを忘れずに
新しいrobots.txtは以下が必要です:
- 以前に実行できたすべてをGooglebotでクロールできるようにする
- 新しいサイトマップの場所を指す
- Next.jsが必要とするJS/CSSファイルを誤ってブロックしない
User-agent: *
Allow: /
Sitemap: https://yourdomain.com/sitemap.xml
技術的な移行チェックリスト
これは実際に使用するチェックリストです。印刷して、ラミネートして、腕に入れ墨を入れてください。好きなことをしてください。
立ち上げ前(2-4週間前)
- 既存サイトの完全なサイトクロールをスプレッドシートにエクスポート
- トラフィックとバックリンク数で上位ページが特定される
- 完全なリダイレクトマップを作成してレビュー
- 新しいURL構造を確定(この後は変更なし)
- メタタイトルとディスクリプションを新しいCMSに移行
- 構造化データ(JSON-LD)を新しいサイトで実装
- Open GraphとTwitter Cardタグを実装
- 内部リンクを新しいURL構造に更新
- 画像altテキストを移行
- すべてのテンプレートで正規タグを確認
- hreflangタグを実装(多言語の場合)
- robots.txtを確認
- 新しいサイトマップが正しく生成されている
- 有用なナビゲーション付き404ページを作成
- ステージングでCore Web Vitalsが合格
- 分析とトラッキングコードをインストール
- 新しいドメイン/サブドメイン(変更中の場合)でGSCを確認
立ち上げ日
- DNSの変更が伝播
- SSLサーティフィケートがアクティブ
- すべてのリダイレクトがテストされて検証される
- 新しいサイトマップをGSCに送信
- トップ20ページの手動インデックスリクエスト
- スモークテスト: 50個のランダムな古いURLをスポットチェックして適切なリダイレクト
- 正規タグにステージングURLがないことを確認
- 本番ページに
noindexタグがないことを確認 - サーバーレスポンスタイムを確認(TTFB 200ms未満であること)
立ち上げ後(最初の30日間)
- GSCクロールエラーの毎日の監視
- 有機トラフィックのベースラインに対する週次比較
- インデックスカバレッジレポートの低下を監視
- GSCでのソフト404を確認
- バックリンクが正しく解決されていることを確認(トップ20をスポットチェック)
- フィールドデータでCore Web Vitalsを監視
- GSCに表示される新しい404に対処
WordPressからヘッドレスNext.jsへ: ステップバイステップ
これは最も一般的な移行パスです。ヘッドレスNext.jsでヘッドレスCMS開発プロジェクトに取り組むときにどのようにアプローチするかは次のとおりです。
ヘッドレスCMSを選択する
モノリシックなWordPressを離れますが、WPGraphQL経由でヘッドレスバックエンドとしてWordPressを保持するか、完全に別のものに移動するかもしれません。
| CMS | 最適 | コンテンツ移行の手間 | 価格(2026) |
|---|---|---|---|
| WordPress(WPGraphQL経由のヘッドレス) | WordPressに精通したチーム | 最小限 — コンテンツはそのまま | ホスティングコストのみ |
| Sanity | 構造化コンテンツ、開発者チーム | 中程度 — エクスポート/インポート必要 | 無料層、その後$99+/月 |
| Contentful | エンタープライズ、マルチチャネル | 中程度~高 | 無料層、その後$300+/月 |
| Strapi | 自己ホスト制御 | 中程度 | 無料(自己ホスト)または$29+/月クラウド |
| Payload CMS | Next.js固有、TypeScriptチーム | 中程度 | 無料(自己ホスト)または$35+/月クラウド |
WordPressをヘッドレスバックエンドとして使用する場合、コンテンツ移行の問題を完全に回避します。WPGraphQLを使用してこのように複数のサイトを構築しました。Next.js開発の専門知識を使用すると、編集チームはWordPress管理を保持し、フロントエンドは高速なNext.jsアプリです。
コンテンツ移行スクリプト
新しいCMSに移動する場合、移行スクリプトが必要になります。WordPressからコンテンツを取得するために使用する簡略版は次のとおりです:
// scripts/migrate-wp-to-sanity.ts
import WPAPI from 'wpapi'
import { createClient } from '@sanity/client'
const wp = new WPAPI({ endpoint: 'https://old-site.com/wp-json' })
const sanity = createClient({
projectId: 'your-project',
dataset: 'production',
token: process.env.SANITY_TOKEN,
apiVersion: '2026-01-01',
})
async function migratePosts() {
let page = 1
let hasMore = true
while (hasMore) {
const posts = await wp.posts().page(page).perPage(100)
for (const post of posts) {
await sanity.create({
_type: 'post',
title: post.title.rendered,
slug: { current: post.slug },
// WP HTMLをPortable TextまたはMDXに変換
body: convertHtmlToPortableText(post.content.rendered),
publishedAt: post.date,
// リダイレクトマップ生成用に古いURLを保持
legacyUrl: new URL(post.link).pathname,
seo: {
metaTitle: post.yoast_head_json?.title || post.title.rendered,
metaDescription: post.yoast_head_json?.description || '',
},
})
}
hasMore = posts._paging?.totalPages > page
page++
}
}
ほとんどの移行ガイドが見逃す重要な詳細: 古いURLを新しいCMSのフィールドとして保持します。 これでリダイレクト生成が簡単になり、コンテンツがどこから来たかの永続的な記録が得られます。
構造化データの移行
YoastなどのWordPressプラグインは構造化データを自動的に生成します。Next.jsでは、自分でそれを実装する必要があります:
// components/ArticleSchema.tsx
export function ArticleSchema({ post }) {
const schema = {
'@context': 'https://schema.org',
'@type': 'Article',
headline: post.title,
datePublished: post.publishedAt,
dateModified: post.updatedAt,
author: {
'@type': 'Person',
name: post.author.name,
},
publisher: {
'@type': 'Organization',
name: 'Your Company',
logo: {
'@type': 'ImageObject',
url: 'https://yourdomain.com/logo.png',
},
},
image: post.featuredImage?.url,
description: post.excerpt,
}
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
)
}
BreadcrumbList、FAQPage、およびWordPressサイトが生成していた他のスキーマタイプを忘れないでください。移行の前後にGoogleのRich Results Testで確認してください。
移行後の監視
移行後の最初の48時間が重要です。ここで何を見守るかは次のとおりです:
最初の48時間
- リアルタイムでサーバーログの404を監視します。すべての404は見逃されたリダイレクトです。
- GSC's URL Inspection ToolでVIPページを確認します。再度クロールされていますか?
- CDN/ホスティングの予期しないトラフィックスパイクまたはドロップを監視します。
最初の2週間
ランキングの変動はある程度は正常です。Googleはサイト全体を再度クロールして再処理する必要があります。正常でないもの:
- 5日以上持続する15%以上のトラフィック低下
- VIPページが3以上の位置を失う
- インデックスカバレッジが10%以上低下
これらのいずれかが表示された場合は、最初にリダイレクトを確認してください。次に、意図しないnoindexタグを確認します。その次に、コンテンツが実際にレンダリングされていることを確認します(Next.jsのSSR問題は空白のページをGooglebotに提供できます)。
最初の3ヶ月
以下を比較する週次の自動化されたレポートを設定します:
- オーガニックトラフィック週対週
- トップ50キーワードの平均位置
- インデックスされたページの数
- Core Web Vitalsスコア
我々の経験では、実行がよく行われた移行はトラフィックを2〜4週間以内にベースラインに回復させ、Next.jsのパフォーマンス上の利点のおかげで8週間以内にそれを超えることがよくあります。
見た(そして犯した)共通の間違い
URL構造とコンテンツを同時に変更する。 しないでください。コンテンツを現状のまま移行し、立ち上げて、Googleが定着するのを待ってから、後でコンテンツを最適化します。同時に多くの信号を変更すると、問題を診断することが不可能になります。
画像について忘れる。 画像がyourdomain.com/wp-content/uploads/から提供され、今はCDNで異なるURLを持つ場合、外部サイトのサイト内の画像へのすべてのリンクが破れています。それらのパスもリダイレクトします。
末尾のスラッシュを一貫して処理しない。 Next.jsにはtrailingSlash設定オプションがあります。trueまたはfalseを選択し、すべてのリダイレクト、正規タグ、サイトマップエントリが一致することを確認してください。
金曜日に立ち上げる。 ただしないでください。火曜日または水曜日の朝に立ち上げて、1週間全体を監視して問題を修正できるようにしてください。
Googleに移行について知らせない。 ドメインを変更する場合、GSCの変更アドレスツールを使用してください。同じドメインに留まっても、サイトマップを再送信し、Removals ツールを使用して、インデックス対象外にすべき古いURLをクリアしてください。
すべてこれに圧倒されているように感じている場合、それは理解できます — それは本当に複雑な仕事です。私たちのチームはこれらの移行を定期的に処理しており、あなたの特定の状況について話し合う準備ができています。
FAQ
Googleが301リダイレクトを認識するのにどのくらい時間がかかりますか?
Googleは通常、301リダイレクトを数日から2週間以内に検出して処理します。これはサイトをGooglebotがクロールする頻度によって異なります。多くのバックリンクを持つ高権威ページは傾向として高速に再度クロールされます。Google Search ConsoleでサイトマップをSubmitしてURL Inspection ツールを使用することで再度クロールをリクエストすることで、この処理をスピードアップできます。
301リダイレクトからリンク資産(リンクジュース)を失うことになりますか?
Googleは2016年以降、301リダイレクトが完全なリンク資産を渡すことを確認しています。リダイレクトの「PageRank税」はもうありません。ただし、リダイレクトチェーン(A → B → C)により、転送を遅くし、クロールバジェットの問題を引き起こすことがあります。可能な限りシングルホップリダイレクトを保つようにしてください。
移行中に301リダイレクトの代わりに302リダイレクトを使用できますか?
いいえ。移行に301(永続的)リダイレクトを使用してください。302はGoogleに移動が一時的であることを告げ、古いURLをインデックスに保持するべきであることを指示します。これは移行中にしたいことと直接矛盾しています。唯一の例外は、実際に元に戻すことを計画している場合です。ただし、CMSを移行する場合、戻りません。
Next.jsの301リダイレクトはいくつが多すぎますか?
Next.jsはnext.config.jsで約1,000エントリまでリダイレクトをうまく処理します。それ以上の場合は、ミドルウェア、エッジ関数を使用するか、CDNレベルでリダイレクトを処理する必要があります。Vercelの Edge Configは、数十万のリダイレクトをサブミリ秒のルックアップ時間で処理できます。自己ホスト型Next.jsの場合、ミドルウェアのRedisバックアップリダイレクトルックアップを検討してください。
WordPressタグと著者ページをリダイレクトすべきですか?
はい、ただし戦略的に。タグページが重要なトラフィックまたはバックリンクを持っていた場合、新しいサイト上の最も関連のあるコンテンツにそれらをリダイレクトします。トラフィックがゼロの(ほとんどのWordPressタグページである)シンコンテンツページの場合、親カテゴリまたはブログインデックスにそれらをリダイレクトします。著者ページは通常、このページまたはチームページにリダイレクトされるべきです。
移行後のGoogle Business Profileおよび他の引用にどうなりますか?
ドメインが同じままの場合、ほとんどの引用とGoogle Business Profileは影響を受けません。ただし、特定のURLがリストされている場合(サービスページなど)、それらが適切にリダイレクトされることを確認してください。移行後の最初の週の中に、Google Business Profile、ソーシャルメディアプロフィール、主要なディレクトリリストのURLを更新してください。
ヘッドレスWordPressまたは別のヘッドレスCMSに移行する方が良いですか?
チームに依存します。コンテンツ編集者がWordPressを愛し、あなたのコンテンツモデルがWordPressに適しているなら、WPGraphQL経由でWordPressをヘッドレスバックエンドとして使用することで、コンテンツ移行のリスク全体を排除します。WordPressの制限にぶつかっている場合、またはより最新の編集エクスペリエンスが必要な場合、Sanity、Payload CMS、またはContentfulは強力な代替品です。ヘッドレスCMS開発ページでオプションをさらに詳しく説明しています。
CMS移行中に多言語コンテンツを処理するにはどうすればよいですか?
多言語の移行は複雑さのもう1つのレイヤーを追加します。元の言語/地域の構造と全く同じhreflangタグを保持し、各言語バージョンを対応する新しいURLにリダイレクトし、新しいCMSが同じ言語/地域構造をサポートしていることを確認する必要があります。サブディレクトリ(/es/、/fr/)からサブドメインに切り替える場合、またはその逆の場合、これは基本的に各言語のドメイン変更であり、リダイレクトとGSC設定で追加の注意が必要です。