wordpress-to-nextjs-migration-seo.html
< BACK Alte Karteikasten in einem düsteren Archivraum mit warmem Bernsteinlicht und verstreuten Karteikartenaus

WordPress zu Next.js migrieren ohne SEO zu verlieren

Vor drei Jahren habe ich das Blog eines Kunden migriert -- 400 Beiträge, 60.000 monatliche organische Besuche, acht Jahre angesammelter PageRank -- und bin zu einem glänzenden Next.js Frontend übergegangen. Innerhalb von sechs Wochen hatten wir 34% dieses Traffics verloren. Nicht, weil die neue Website langsam war. Nicht, weil der Content verschwunden war. Weil ich bei vier spezifischen Dingen nachlässig war, die ich dir in diesem Beitrag zeige, damit du meinen Fehler nicht wiederholst.

Headless WordPress mit Next.js ist wirklich brillant für Performance und Developer Experience. Aber Google kümmert sich nicht um deinen Lighthouse Score, wenn deine Canonical Tags falsch sind, deine XML-Sitemap auf die alte Domain zeigt und deine strukturierten Daten irgendwo zwischen WPGraphQL und getStaticProps verdampft sind. Die Migration selbst ist der gefährliche Teil. Es richtig zu machen ist vor allem eine Frage der Disziplin, nicht der Magie.getStaticProps. The migration itself is the dangerous part. Getting it right is mostly about discipline, not magic.

---

Warum diese Migration SEO überhaupt zerbricht

Hier ist das Problem, das die meisten Tutorials übergehen: WordPress macht für dich eine Menge SEO-Schwerstarbeit, ohne dass du es merkst. Yoast oder Rank Math generiert deine Meta Tags. WordPress Core verwaltet deine Permalink-Struktur. Dein Theme gibt wahrscheinlich irgendwelche Schema-Markups aus. Deine XML-Sitemap wird jedes Mal automatisch neu generiert, wenn du etwas veröffentlichst.some kind of schema markup. Your XML sitemap auto-regenerates every time you publish.

Wenn du die Content-Schicht via WPGraphQL API in Next.js ziehst und sie von einem neuen Frontend aus servierst, wird die gesamte Infrastruktur zu deinem Problem, das du replizieren musst. Jedes. Einzelne. Teil.WPGraphQL API and serve it from a new front-end, all of that infrastructure becomes your problem to replicate. Every. Single. Piece.

Das andere Problem ist die URL-Struktur. Die meisten WordPress-Seiten haben /category/post-slug/ oder /year/month/post-slug/ oder einfach /post-slug/. Next.js gibt dir eine leere Leinwand für Routing. Diese leere Leinwand ist ein Ranking-Friedhof, wenn du sie nicht sorgfältig planst./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.

Die zwei Fehlermodi, die ich ständig sehe

Das Erste sind Teams, die die URLs auch migrieren und trotzdem Dinge kaputtmachen -- normalerweise, weil Redirects inkonsistent angewendet werden oder die neue Sitemap live geht, bevor die Redirects aktiv sind. Das Zweite sind Teams, die die URL-Struktur absichtlich ändern (oft um sie aufzuräumen) und die Redirect-Zuordnung als Nachgedanken behandeln. Beide sind behebbar. Keines ist akzeptabel.

---

Audit, bevor du irgendetwas anfasst

Schreib keine einzige Zeile Next.js-Code, bevor du ein vollständiges URL-Inventar hast. Ich nutze Screaming Frog -- crawle die Live-WordPress-Website, exportiere jede indexierbare URL und kippe sie in eine Tabellenkalkulation. Bei einer 400-Seiten-Website dauert das vielleicht eine Stunde. Bei einer 4.000-Seiten-Website dauert es immer noch nur eine Stunde, weil das Tool es automatisch macht.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.

Das erfasst du:

  • Jede kanonische URL, die derzeit indexiert ist
  • Den HTTP-Status jeder URL (identifiziere 404er und 301er, die bereits existieren)
  • Der Meta-Title und die Meta-Beschreibung für jede Seite
  • Welche Seiten haben strukturierte Daten (nutzen Sie den Rich Results Test oder schauen Sie sich einfach den Quellcode an)
  • Interne eingehende Links -- damit du weißt, welche Seiten auf welche verlinken

Ziehen Sie auch Ihre Top 50 Seiten aus Google Search Console herunter, sortiert nach Klicks. Das sind diejenigen, bei denen Sie keinen Fehler machen dürfen. Markieren Sie diese im Spreadsheet. Behandeln Sie sie wie Produktionsabhängigkeiten.

Seahawk hatte Ende 2022 einen E-Commerce-Kunden -- ein 1.200-Produkt-WooCommerce-Store, der zu einer Headless-Lösung wechselt. Wir haben zwei volle Tage für das Audit aufgewendet, bevor wir Code geschrieben haben. Der Kunde dachte, wir verschwenden Zeit. Wir retteten seine 90.000 monatlichen organischen Sessions.

---

WordPress als echtes Headless CMS einrichten

Dieser Teil ist größtenteils unkompliziert. Installieren Sie WPGraphQL und stellen Sie Ihre Inhalte über die GraphQL API zur Verfügung. Es gibt aber ein paar Dinge, bei denen es sich lohnt, gezielt vorzugehen.

Halten Sie Yoast (oder Rank Math) auf der WordPress-Seite aktiv

Obwohl du WordPress nicht mehr als öffentliches Frontend bereitstellst, halte dein SEO-Plugin aktiv. WPGraphQL für Yoast SEO (oder die äquivalente Rank Math-Erweiterung) macht alle SEO-Meta -- Titles, Descriptions, Canonical URLs, OG-Daten, Robots-Direktiven -- direkt über die GraphQL API verfügbar. Das bedeutet, du kannst sie von Next.js aus abfragen und genau so rendern, wie Yoast es beabsichtigt hat.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.

Das war die Lektion aus jenem 2019 Traffic-Einbruch, den ich erwähnt habe. Ich war davon ausgegangen, dass wir Titel aus dem Post-Titel + Site-Namen in Next.js neu generieren könnten. Das konnten wir. Aber Yoast hatte bei etwa 80 der Top-Performing Posts Meta-Titel manuell angepasst, und wir haben all das gelöscht. Acht Wochen zur Wiederherstellung.

Deaktiviere das WordPress Front-End sorgfältig

Sobald du Traffic auf Next.js leiten willst, soll WordPress NICHT gleichzeitig sein eigenes Frontend servieren. Duplicate Content in großem Maßstab. Die sauberste Methode ist, eine robots.txt auf deiner WordPress-Installation auf Disallow: / zu setzen, während deine Next.js-Site live geht, und dann irgendwann die WordPress-URL ganz zu firewalln, damit sie nur intern oder via VPN erreichbar ist.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.

Überspringe nicht den robots.txt-Schritt. Ich habe Teams gesehen, die WordPress auf CDN-Ebene blockiert haben und dann festgestellt haben, dass Googlebot eine gecachte Route hatte. Das dauert Monate zu bereinigen.

---

Die URL-Struktur exakt replizieren

Meine klare Standardempfehlung: Behalte deine URLs identisch. Gleicher Slug, gleiche Permalink-Struktur, gleiches Trailing-Slash-Verhalten. Je näher deine Next.js-Routes die WordPress-Routes spiegeln, desto weniger Redirects brauchst du, und desto weniger Risiko trägst du.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 dynamic routes machen das einfach. Wenn deine WordPress-Posts unter /blog/[slug] leben, erstelle pages/blog/[slug].js. Fertig.dynamic routes make this easy. If your WordPress posts live at/blog/[slug], create pages/blog/[slug].js. Done.

Wo es unordentlich wird, sind Kategorie-Archive, Autor-Seiten, Tag-Seiten und paginierte Archive (/blog/page/2/). WordPress generiert alle diese automatisch. In Next.js baust du sie selbst. Viele Teams deprioritisieren diese und wundern sich dann, warum die Crawl-Abdeckung gesunken ist./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.

Hier ist meine nummerierte Checkliste für URL-Parität:

  1. Einzelne Beiträge/Seiten -- match den Slug genau, einschließlich aller Unterordner -- match the slug exactly, including any subfolder
  2. Category Archives -- erstelle /category/[slug]/ neu mit getStaticPaths, das alle Categories von WPGraphQL abruft -- recreate/category/[slug]/with getStaticPaths pulling all categories from WPGraphQL
  3. Tag-Archive -- genauso wie oben, überspringe diese nicht, wenn sie organischen Traffic generieren -- same as above, don't skip these if they get organic traffic
  4. Autoren-Archive -- prüfe zuerst die Search Console; wenn sie null Klicks bekommen, kannst du sie mit 301 zur Startseite umleiten -- check Search Console first; if they get zero clicks, you can 301 them to the homepage
  5. Paginierte Archive -- /blog/page/[num]/ ist es wert, erhalten zu bleiben, wenn du viele Beiträge hast -- /blog/page/[num]/is worth preserving if you have a lot of posts
  6. Anhang-Seiten -- leite diese fast immer mit 301 zum übergeordneten Beitrag um; sie sind in WordPress auch SEO-Ballast -- almost always 301 these to the parent post; they're SEO dead weight in WordPress too
  7. Feed-URLs -- /feed/ sollte mit 301 zu deinem neuen RSS-Feed umgeleitet werden, falls vorhanden, oder 410 zurückgeben, falls nicht -- /feed/should 301 to your new RSS feed if you have one, or return 410 if not

---

Redirects: Der Teil, den jeder unterschätzt

Falls du URLs änderst -- wogegen ich argumentieren würde, aber manchmal ist es notwendig -- muss deine Redirect-Map vor dem Launch erstellt und in einer Staging-Umgebung getestet werdenare 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.

In Next.js befinden sich Redirects in next.config.js. Für kleine Seiten (unter 200 Redirects) ist das in Ordnung. Für größere, lege sie in eine JSON-Datei und importiere sie, oder nutze Middleware, um sie dynamisch zu handhaben. Vercels Edge Middleware ist hervorragend für große Redirect-Tabellen, weil sie vor dem Rendering der Seite ausgeführt wird -- keine Latenz-Einbußennext.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.

Das Format in 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 sendet eine 301. Nutze es für alle echten URL-Änderungen. Verwende 302 (temporär) nicht, es sei denn, du beabsichtigst tatsächlich, es rückgängig zu machen -- Google behandelt sie völlig unterschiedlich 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.

Testen Sie jeden Redirect vor dem Launch. Ich verwende ein einfaches Bash-Skript, das die Tabelle durchläuft und jeden alten URL mit curl aufruft, um auf eine 301-Antwort zum richtigen Ziel zu prüfen. Dauert zehn Minuten zu schreiben, erspart Stunden Panik nach dem Launch.

---

Meta Tags, Canonical URLs und Structured Data in Next.js

Hier verlieren die meisten Migrationen still Punkte. Der Inhalt ist da, die URLs funktionieren, aber die SEO-Signale sind falsch.

Meta Tags

Nutze next-seo. Das ist der Standard. Übergebe ihm die Daten, die du aus WPGraphQL Yoast abgefragt hast. Deine _app.js bekommt eine DefaultSeo-Konfiguration, und jede Seite bekommt eine NextSeo-Komponente mit den seitenspezifischen Überschreibungen. Nimm Titel, Beschreibung, OG-Titel, OG-Bild, Canonical-URL und Robots-Direktiven direkt aus der Yoast GraphQL-Response -- erfinde sie nicht neunext-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.

Eine Sache, die Menschen Probleme bereitet: Canonical URLs. In WordPress setzt Yoast Canonicals automatisch. In Next.js musst du das Canonical explizit übergeben. Wenn du das vergisst, rendert Next.js Seiten ohne Canonical-Tag, und wenn du irgendwo Query-Strings hast (Pagination, Filter), bekommst du schneller Duplicate-Content-Probleme, als du erwartest.

Strukturierte Daten

WordPress Themes und Plugins geben JSON-LD oft automatisch aus. Das verschwindet bei Headless. Du musst es neu aufbauen. Für Artikel nutze das Article-Schema. Für Produkte Product. Für lokale Unternehmen LocalBusiness. Ich schreibe diese als React-Komponenten, die Props akzeptieren und einen <script type="application/ld+json">-Tag zurückgeben. Eine Komponente pro Schema-Typ, wiederverwendet in der ganzen App.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.

Überprüfe jeden Schema-Typ, den du vorher im Rich Results Test hattest, vor der Migration. Dokumentiere sie. Erstelle sie neu. Teste die neuen mit dem gleichen Tool nach dem Launch.before migration. Document them. Recreate them. Test the new ones with the same tool post-launch.

Die XML Sitemap

Verwende keine statische Sitemap. Generiere sie dynamisch. Für kleine Seiten funktioniert getServerSideProps auf einer /sitemap.xml-Route. Für große Seiten mit Tausenden von Beiträgen generiere die Sitemap zur Build-Zeit über ein benutzerdefiniertes Skript und gib sie im public/-Ordner aus. Vercel führt dies bei jedem Deployment aus -- deine Sitemap ist immer aktuellgetServerSideProps 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.

Reiche die neue Sitemap-URL am ersten Tag nach dem Launch in der Google Search Console ein. Nicht am dritten Tag. Am ersten Tag.

---

Monitoring nach dem Launch (Das 90-Tage-Fenster)

Die Migration endet nicht beim Launch. Sie endet, wenn sich deine Rankings stabilisiert haben -- was laut Googles Dokumentation je nach Crawl-Budget und Domain-Autorität zwischen wenigen Wochen und mehreren Monaten dauern kann.

Was ich jeden Wochentag im ersten Monat überprüfe:

  • Google Search Console → Coverage Report auf neue 404s oder 'Excluded'-URLs, die nicht ausgeschlossen sein sollten for new 404s or 'Excluded' URLs that shouldn't be excluded
  • Search Console → Performance -- vergleiche Clicks und Impressionen Woche für Woche für deine Top 50 Seiten -- compare clicks and impressions week-on-week for your top 50 pages
  • Screaming Frog Re-Crawl der neuen Site, um interne 404s oder falsch konfigurierte Canonical Tags zu fangen of the new site to catch any internal 404s or misconfigured canonical tags
  • Core Web Vitals -- ja, die Next.js-Website sollte schneller sein, aber verifiziere das in den Field-Daten (CrUX), nicht nur in Lighthouse -- yes, the Next.js site should be faster, but verify it in the field data (CrUX), not just Lighthouse

Wenn du in den ersten zwei bis drei Wochen einen signifikanten Rückgang siehst, gerät nicht gleich in Panik. Es gibt fast immer kurzfristige Schwankungen, während Google erneut crawlt und neu indexiert. Worauf du achten musst, sind anhaltende Rückgänge nach Woche vier. Das ist das Signal, dass etwas strukturell nicht stimmt.

Ende 2022 -- ein anderes Projekt als das E-Commerce-Projekt -- haben wir eine Next.js-Migration für einen SaaS-Blog durchgeführt und einen Rückgang der Impressionen um 20% in der zweiten Woche gesehen. Es stellte sich heraus, dass unsere dynamisch generierte Sitemap noindex-Seiten enthielt, weil wir die WPGraphQL-Abfrage nicht richtig gefiltert hatten. Wir haben das in vier Stunden behoben. Die Rankings haben sich in drei Wochen erholt. Das Monitoring hat das Problem erkannt, bevor es sich verschärft hat.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

Wie lange dauert eine WordPress-zu-Next.js-Migration?

Ehrlich gesagt hängt es mehr von der Komplexität der Website ab als von der Anzahl der Beiträge. Eine 100-Seiten-Broschüren-Website mit sauberen URLs lässt sich in zwei bis drei Wochen ordnungsgemäß umsetzen. Ein 2.000-Beiträge-Blog mit benutzerdefinierten Post-Typen, ACF-Feldern und WooCommerce-Integration ist ein Projekt von mindestens sechs bis acht Wochen, wenn du die SEO-Arbeit ordnungsgemäß neben der Entwicklung machst. Lass dir von niemandem erzählen, dass das ein Wochenend-Job ist.

Soll ich den Pages Router oder App Router in Next.js verwenden?

Seit Mitte 2024 nutze ich standardmäßig den App Router für neue Projekte. Aber wenn dein Team sich mit dem Pages Router besser auskennt und diese Migration zeitkritisch ist, verwende das, was ihr kennt. Die SEO-Auswirkungen sind minimal -- beide unterstützen statische Generierung, serverseitiges Rendering und dynamische Routen. Das next-seo-Paket hat jetzt auch App-Router-Unterstützung.next-seo package has App Router support now too.

Muss ich mich ganz von WordPress-Hosting verabschieden?

Nein. WordPress kann auf seinem bestehenden Host bleiben -- WP Engine, Kinsta, Cloudways, was auch immer du nutzt -- und fungiert rein als Content-API. Das Next.js Frontend wird auf Vercel oder Netlify deployed. Die beiden kommunizieren via HTTP. Manche Kunden bevorzugen das sogar, weil das Editorial-Team die WordPress-Admin-Oberfläche behält, die sie bereits kennen.Netlify. The two communicate via HTTP. Some clients actually prefer this because the editorial team keeps the WordPress admin they already know.

Was ist mit WordPress-Plugins, die SEO beeinflussen -- wie Redirects, die in Redirection verwaltet werden?

Exportiere sie vor der Migration. Das Redirection-Plugin hat einen CSV-Export. Nimm alle diese bestehenden Redirects und füge sie zu deiner next.config.js oder zu Edge-Middleware hinzu. Gehe nicht davon aus, dass sie automatisch übernommen werden -- das passiert nicht, weil sie in der WordPress-Datenbank gespeichert sind und Next.js davon nichts weiß.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.

Wird mein Google-Ranking auf jeden Fall sinken?

Es gibt fast immer etwas kurzfristige Volatilität. Eine gut ausgeführte Migration ohne URL-Änderungen, mit angemessenen Redirects (falls nötig), replizierter Meta und strukturierten Daten und einer neu eingereichten Sitemap sollte sich in vier bis sechs Wochen stabilisieren. Die Rückgänge, die ich über Monate hinweg gesehen habe, waren alle auf spezifische technische Fehler zurückzuführen -- nicht auf die Migration selbst.

---

Die Migration ist nicht die schwierige Part. Die schwierige Part ist die Disziplin, jeden langweiligen, unglamourösen Schritt zu tun -- das Audit, das Redirect-Mapping, die Schema-Rekonstruktion -- bevor du irgendwelchen cleveren Next.js-Code schreibst. Wenn du diese Reihenfolge richtig hinbekommst, wirst du auf der anderen Seite mit einem schnelleren Frontend und denselben Rankings herauskommen, mit denen du angefangen hast. Möglicherweise sogar mit besseren, sobald sich die Core-Web-Vitals-Verbesserungen auswirken.Core Web Vitals improvements feed through.

< BACK