3年前、あるクライアントのブログ――400記事、月60万オーガニック訪問、8年蓄積されたPageRank――をピカピカのNext.jsフロントエンドに移行しました。6週間以内に、そのトラフィックの34%を失いました。新しいサイトが遅かったからではありません。コンテンツが消えたからでもありません。4つの具体的なことについて、私が不注意だったからです。このポストでそれらを解説するので、同じ失敗を繰り返さないでください。
Next.jsを使ったヘッドレスWordPressは、パフォーマンスとデベロッパー体験という点で本当に優れています。ですが、canonical タグが間違っていて、XMLサイトマップが古いドメインを指していて、構造化データがWPGraphQLとgetStaticPropsの間のどこかで消えてしまっていたら、Lighthouse スコアがいくら良くてもGoogleは気にしません。危険なのは、実はこの移行プロセス自体です。正しく実行するのに必要なのは、ほとんどの場合、魔法ではなく規律です。getStaticProps. The migration itself is the dangerous part. Getting it right is mostly about discipline, not magic.
---
最初にこの移行がSEOを壊してしまう理由
ほとんどのチュートリアルが触れない重要なポイントはこれです。WordPressは、あなたが気づかないうちに莫大なSEO上の重い仕事をあなたの代わりにやっているということです。YoastやRank Mathがメタタグを生成しています。WordPressコアがパーマリンク構造を処理しています。あなたのテーマはおそらく何らかのスキーママークアップを出力しています。XMLサイトマップは、あなたが公開するたびに自動的に再生成されます。some kind of schema markup. Your XML sitemap auto-regenerates every time you publish.
WPGraphQL APIを経由してNext.jsにコンテンツレイヤーを引き込んで、新しいフロントエンドから配信する場合、そのインフラのすべてがあなたが複製しなければならない問題になります。すべてです。本当にすべてです。WPGraphQL API and serve it from a new front-end, all of that infrastructure becomes your problem to replicate. Every. Single. Piece.
もう一つの問題がURL構造です。ほとんどのWordPressサイトは/category/post-slug/、または/year/month/post-slug/、あるいは単に/post-slug/といった構造を持っています。Next.jsはルーティングについて白紙の状態を提供します。その白紙の状態は、慎重に計画しなければランク低下の墓場になります。/category/post-slug/or/year/month/post-slug/or just/post-slug/. Next.js gives you a blank canvas for routing. That blank canvas is a ranking graveyard if you don't plan it carefully.
私が常に目にしている2つの失敗パターン
1つ目は、URLも移行するチームがそれでも物を壊すケースです――通常、リダイレクトが一貫性なく適用されるか、新しいサイトマップがリダイレクトより先にライブになるせいです。2つ目は、URLスキーマを意図的に変更するチーム(クリーンアップのためのことが多い)で、リダイレクトマッピングを後付けのように扱うケースです。どちらも修正可能です。どちらも受け入れられません。
---
何かに触れる前に監査を行う
完全なURL在庫がないうちに、Next.jsのコード1行も書かないでください。私はScreaming Frogを使用します――ライブのWordPressサイトをクロールし、すべてのインデックス可能なURLをエクスポートして、スプレッドシートにダンプします。400ページのサイトであれば、おそらく1時間の作業です。4,000ページのサイトでも、ツールが自動的にやるので、やはり1時間です。Screaming Frog -- crawl the live WordPress site, export every indexable URL, and dump it into a spreadsheet. For a 400-page site that's maybe an hour of work. For a 4,000-page site it's still just an hour, because the tool does it automatically.
キャプチャしているもの:
- 現在インデックスされているすべての正規URL
- 各URLのHTTPステータス(既に存在する404と301を特定)
- すべてのページのメタタイトルと説明
- 構造化データを持つページ(Rich Results Testを使用するか、ソースを検査するだけ)
- インバウンド内部リンク――どのページがどのページにリンクしているかを知るため
Google Search Consoleから上位50ページをクリック数でソートして取得します。これらは間違えられないページです。スプレッドシートにフラグを付けます。本番環境の依存関係のように扱ってください。
Seahawkは2022年後期にあるeコマースクライアントがいました――1,200商品のWooCommerceストアがヘッドレス化へ移行。コードを書く前に、2日間まるごと監査に費やしました。クライアントは時間の無駄だと思いました。月9万オーガニックセッションを救いました。
---
WordPressを真のヘッドレスCMSとして設定する
この部分は大部分が単純です。WPGraphQLをインストールしてGraphQL APIを通じてコンテンツを公開するだけです。ただし、意図的に検討する価値のある点がいくつかあります。
WordPress側でYoast(またはRank Math)を実行し続ける
WordPressをパブリックフロントエンドとして配信しなくなっても、SEOプラグインは有効なままにしておいてください。WPGraphQL for Yoast SEO(または同等のRank Math拡張)はSEOメタ――タイトル、説明、canonical URL、OGデータ、robots指示――すべてをGraphQL APIで直接公開します。つまりNext.jsから照会でき、Yoastの意図したとおりレンダリングできます。WPGraphQL for Yoast SEO(or the equivalent Rank Math extension) exposes all the SEO meta -- titles, descriptions, canonical URLs, OG data, robots directives -- directly through the GraphQL API. That means you can query it from Next.js and render it exactly as Yoast intended.
これは、先ほど述べた2019年のトラフィック低下から得た教訓だ。Next.jsでポストタイトル + サイト名からタイトルを再生成できると考えていた。実際にできた。だが、Yoastが上位パフォーマンスのポストの約80個に対してメタタイトルを手動でカスタマイズしており、我々はそれをすべて削除してしまった。回復に8週間かかった。
WordPress フロントエンドを慎重に無効化する
Next.jsへのトラフィックをポイントする準備ができたら、WordPressが同時に自身のフロントエンドを配信していてはいけません。大規模な重複コンテンツになります。最もシンプルなやり方は、WordPressインストールのrobots.txtでDisallow: /を設定してNext.jsサイトを本番運用に移す、その後、eventually WordPressのURLをファイアウォールで完全に遮断してVPNまたは内部アクセスのみにすることです。robots.txt on your WordPress install to Disallow: /while your Next.js site goes live, then eventually firewall the WordPress URL entirely so it's only accessible internally or via VPN.
robots.txt のステップをスキップするな。CDNレベルでWordPressをブロックした後、Googlebot がキャッシュされたルートを持っていたことに気付くチームを見てきた。クリーンアップに数ヶ月かかる。
---
URL構造を完全に複製する
強い推奨デフォルト:URL を同じにしておく。同じスラッグ、同じパーマリンク構造、同じトレーリングスラッシュの動作。Next.js のルートが WordPress のルートをどれだけ正確にミラーリングするかが、必要なリダイレクト数と抱えるリスクを左右する。keep your URLs identical. Same slug, same permalink structure, same trailing slash behaviour. The closer the Next.js routes mirror the WordPress routes, the fewer redirects you need, and the less risk you carry.
Next.jsのダイナミックルートはこれを簡単にします。WordPressのポストが/blog/[slug]にあれば、pages/blog/[slug].jsを作成します。それで完了です。dynamic routes make this easy. If your WordPress posts live at/blog/[slug], create pages/blog/[slug].js. Done.
複雑になるのはカテゴリーアーカイブ、著者ページ、タグページ、ページネーションアーカイブ(/blog/page/2/)だ。WordPress はこれらすべてを自動生成する。Next.js では自分でビルドしている。多くのチームはこれらを後回しにして、その後クロールカバレッジが低下した理由に首をかしげている。/blog/page/2/). WordPress generates all of these automatically. In Next.js you're building them yourself. A lot of teams deprioritise these and then wonder why crawl coverage dropped.
ここが URL パリティのための番号付きチェックリストだ:
- 個別記事/ページ――サブフォルダを含め、スラッグを正確に一致させる -- match the slug exactly, including any subfolder
- カテゴリアーカイブ――/category/[slug]/を再作成し、getStaticPathsでWPGraphQLからすべてのカテゴリを引き出す -- recreate
/category/[slug]/withgetStaticPathspulling all categories from WPGraphQL - タグアーカイブ -- 上記と同じ。オーガニックトラフィックが発生していれば、スキップしないこと -- same as above, don't skip these if they get organic traffic
- 著者アーカイブ -- Search Console で確認してから。クリック数がゼロなら、ホームページへ 301 リダイレクトできる -- check Search Console first; if they get zero clicks, you can 301 them to the homepage
- ページネーション付きアーカイブ -- /blog/page/[num]/ は投稿が大量にある場合は保持する価値がある --
/blog/page/[num]/is worth preserving if you have a lot of posts - アタッチメントページ -- ほぼ常に親投稿へ 301 リダイレクト。WordPress でも SEO 的には無駄になる -- almost always 301 these to the parent post; they're SEO dead weight in WordPress too
- フィード URL -- /feed/ は新しい RSS フィードがあれば 301 リダイレクト、なければ 410 を返す --
/feed/should 301 to your new RSS feed if you have one, or return 410 if not
---
リダイレクト — みんなが過小評価する部分
URL を変更する場合 -- 個人的には反対だが、時には必要 -- リダイレクトマップは本番公開前に構築し、ステージング環境でテストする必要があるare changing any URLs -- which I'd push back on, but sometimes it's necessary -- your redirect map needs to be built before launch and tested in a staging environment.
Next.js ではリダイレクトは next.config.js に記述する。小規模サイト(リダイレクト 200 件未満)なら問題ない。それ以上なら JSON ファイルに記述してインポートするか、ミドルウェアで動的に処理する。Vercel のエッジミドルウェアは大規模なリダイレクトテーブルに最適。ページ描画前に実行されるため、レイテンシペナルティはゼロ。next.config.js. For small sites (under 200 redirects) that's fine. For anything larger, put them in a JSON file and import it, or use middleware to handle them dynamically.Vercel's edge middleware is excellent for large redirect tables because it runs before the page is rendered -- zero latency penalty.
next.config.jsでのフォーマットは:next.config.js:
``redirects: [ { source: '/old-slug', destination: '/new-slug', permanent: true } ]``redirects: [ { source: '/old-slug', destination: '/new-slug', permanent: true } ]``
permanent: true は 301 を送信する。URL の実際の変更にはすべて使用すること。302(一時的)は本当に戻す予定がある場合以外は使わないこと -- Google はこの 2 つを大きく異なるものとして扱う sends a 301. Use it for all genuine URL changes. Don't use 302 (temporary) unless you actually intend to revert it -- Google treats them very differently.
本番環境にデプロイする前にすべてのリダイレクトをテストします。私はスプレッドシートをループして各古いURLをcurlで確認し、301レスポンスが正しい宛先に返されているかをチェックする簡単なbashスクリプトを使用します。作成に10分かかりますが、本番環境後のトラブル対応に何時間も浪費することを防ぎます。
---
Next.jsのメタタグ、Canonical URL、構造化データ
ここはほとんどのマイグレーションで静かに得点を失う場所です。コンテンツは存在し、URLは機能していますが、SEOシグナルが間違っています。
メタタグ
next-seo を使う。これが標準。WPGraphQL Yoast からクエリしたデータを渡す。_app.js は DefaultSeo 設定を取得し、各ページは page-specific なオーバーライドを含む NextSeo コンポーネントを取得する。title、description、OG title、OG image、canonical URL、robots ディレクティブを Yoast GraphQL レスポンスから直接取得 -- 自分で作り直さないことnext-seo. It's the standard. Pass it the data you've queried from WPGraphQL Yoast. Your_app.js gets a DefaultSeo config, and each page gets a NextSeo component with the page-specific overrides. Take the title, description, OG title, OG image, canonical URL, and robots directives directly from the Yoast GraphQL response -- don't reinvent them.
ひとつ多くの人が引っかかるのはカノニカルURLだ。WordPressではYoastが自動的にカノニカルを設定する。Next.jsではカノニカルを明示的に渡す必要がある。忘れると、Next.jsはカノニカルタグなしでページをレンダリングし、ページネーションやフィルタなどでクエリ文字列があると、予想より早く重複コンテンツの問題に直面する。
構造化データ
WordPress テーマとプラグインはしばしば JSON-LD を自動的に出力します。ヘッドレスではそれは消えます。再構築する必要があります。記事の場合は Article スキーマを使用してください。製品の場合は Product を使用してください。ローカルビジネスの場合は LocalBusiness を使用してください。これらを props を受け取り <script type="application/ld+json"> タグを返す React コンポーネントとして記述します。スキーマタイプごとに 1 つのコンポーネント、アプリ全体で再利用します。Article schema. For products,Product. For local businesses,LocalBusiness. I write these as React components that accept props and return a<script type="application/ld+json">tag. One component per schema type, reused across the app.
マイグレーション前に Rich Results Test で以前にあったすべてのスキーマタイプを確認してください。ドキュメント化してください。それらを再作成してください。同じツールで新しいスキーマを launch 後にテストしてください。before migration. Document them. Recreate them. Test the new ones with the same tool post-launch.
XMLサイトマップ
静的サイトマップは使わない。動的に生成する。小規模サイトなら /sitemap.xml ルートで getServerSideProps を使う。数千投稿を持つ大規模サイトなら、カスタムスクリプトでビルド時にサイトマップを生成して public/ フォルダに出力する。Vercel はデプロイのたびにこれを実行 -- サイトマップは常に最新状態getServerSideProps on a/sitemap.xml route works. For large sites with thousands of posts, generate the sitemap at build time via a custom script and output it to the public/folder. Vercel runs this at every deployment -- your sitemap is always current.
新しいサイトが本番環境で公開される初日に新しいサイトマップURLをGoogle Search Consoleに送信する。3日目ではなく。初日だ。
---
ローンチ後の監視(90日間のウィンドウ)
マイグレーションはローンチで終わりではありません。ランキングが安定するまで続きます。Googleのドキュメンテーションによると、クローリング予算とサイト権威に応じて数週間から数ヶ月かかる可能性があります。
毎営業日、最初の1ヶ月間でチェックすること:
- Google Search Console → Coverage レポートで新しい 404 または除外されるべきではない「Excluded」URL を確認してください。 for new 404s or 'Excluded' URLs that shouldn't be excluded
- Search Console → Performance -- 上位50ページのクリック数とインプレッション数を週ごとに比較してください -- compare clicks and impressions week-on-week for your top 50 pages
- 新しいサイトを Screaming Frog で再クロールして、内部 404 または誤って設定された canonical タグを検出してください。 of the new site to catch any internal 404s or misconfigured canonical tags
- Core Web Vitals -- 確かにNext.jsサイトは高速化されるはずですが、Lighthouseではなくフィールドデータ(CrUX)で検証してください -- yes, the Next.js site should be faster, but verify it in the field data (CrUX), not just Lighthouse
最初の2〜3週間で大きなドロップが見られても、すぐにパニックにならないこと。Google が再クロールして再インデックスする中で、短期的な変動はほぼ必ず発生する。注視すべきは4週目を過ぎての持続的なドロップだ。それが何か構造的に問題があるというシグナルになる。
2022年後期に遡りますが、e-commerceプロジェクトとは別のプロジェクトで、SaaS ブログのNext.jsマイグレーションを実施しました。2週目にインプレッションが20%低下しました。原因は動的に生成されたサイトマップがWPGraphQLクエリを適切にフィルタリングしていなかったため、noindexページを含んでいたのです。4時間で修正しました。ランキングは3週間で回復しました。監視システムが問題を拡大する前に検出できました。noindex pages because we hadn't filtered the WPGraphQL query properly. Fixed it in four hours. Rankings recovered in three weeks. The monitoring caught it before it compounded.
---
FAQ
WordPress から Next.js へのマイグレーションはどのくらい時間がかかる?
正直なところ、投稿数よりもサイトの複雑さに左右されます。クリーンなURLを持つ100ページのブロシュアサイトなら、2~3週間で適切に完成させられます。2,000個の投稿、カスタム投稿タイプ、ACFフィールド、WooCommerce統合を備えたブログなら、SEO作業を開発と並行して適切に行う場合、最低でも6~8週間のプロジェクト期間が必要です。誰かが週末の案件だと言っても信じないでください。
Next.jsではPages RouterかApp Routerどちらを使うべきですか?
2024年半ばの現在、新規プロジェクトはApp Routerをデフォルトにしています。ただしあなたのチームがPages Routerに慣れていて、これが時間に縛られたマイグレーションなら、知っているものを使用してください。SEOへの影響は最小限です。どちらも静的生成、サーバーサイドレンダリング、動的ルーティングをサポートしています。next-seoパッケージもApp Routerサポートを備えています。next-seo package has App Router support now too.
WordPressホスティングから完全に移行する必要がありますか?
いいえ。WordPressは既存のホストWP Engine、Kinsta、Cloudways、その他お好みのものに残し、純粋にコンテンツAPIとして機能させることができます。Next.jsフロントエンドはVercelまたはNetlifyにデプロイされます。この2つはHTTPで通信します。実際のところ、クライアントの中には、編集チームが既に知っているWordPress管理画面を保持できるため、このアプローチを好む者もいます。Netlify. The two communicate via HTTP. Some clients actually prefer this because the editorial team keeps the WordPress admin they already know.
SEOに影響するWordPressプラグイン、例えばRedirectionで管理されるリダイレクトはどうしたらいいですか?
マイグレーション前にエクスポートしてください。Redirectionプラグインにはcsv形式でのエクスポート機能があります。すべての既存リダイレクトを取得して、next.config.jsまたはエッジミドルウェアに追加してください。自動的に引き継がれると仮定しないでください。引き継がれません。なぜなら、それらはWordPressデータベースに存在し、Next.jsには存在を知る術がないからです。Redirection plugin has a CSV export. Take all those existing redirects and add them to your next.config.js or edge middleware. Don't assume they'll carry over automatically -- they won't, because they live in the WordPress database and Next.js has no idea they exist.
どんなことをしてもGoogleのランキングは下がりますか?
ほぼ常に短期的な変動があります。URLに変更がなく、適切なリダイレクト(必要な場合)、メタデータと構造化データの複製、サイトマップの再送信を伴う実行が良い場合、4週間から6週間以内に安定すべきです。数ヶ月続いた低下はすべて、マイグレーション自体が原因ではなく、特定の技術的エラーによるものでした。
---
マイグレーションが難しい部分ではありません。難しいのは、Next.jsコードを書く前に、監査、リダイレクトマッピング、スキーマ再作成など、退屈で華やかさのないステップをすべて実行する規律です。その順序を正しく理解すれば、高速なフロントエンドとあなたが開始したのと同じランキング、あるいはおそらくより良いランキングで乗り切ることができます。Core Web Vitalsの改善が反映されれば、さらに良くなります。Core Web Vitals improvements feed through.
