wordpress-to-nextjs-migration-seo.html
< BACK Catálogo de tarjetas vintage en una sala de archivo oscura con luz ámbar cálida y tarjetas de índice dispersas

Migrar WordPress a Next.js Sin Perder SEO

Hace tres años tomé el blog de un cliente -- 400 posts, 60k visitas orgánicas mensuales, ocho años de PageRank acumulado -- y lo migré a un flamante front-end en Next.js. En seis semanas habíamos perdido el 34% de ese tráfico. No porque el nuevo sitio fuera lento. No porque el contenido desapareciera. Porque fui negligente con cuatro cosas específicas que te voy a explicar en este post para que no repitas mi error.

WordPress headless con Next.js es genuinamente excelente para rendimiento y experiencia del desarrollador. Pero a Google no le importa tu puntuación de Lighthouse si tus etiquetas canónicas están mal, tu sitemap XML apunta al dominio antiguo y tus datos estructurados desaparecieron en algún lugar entre WPGraphQL y getStaticProps. La migración en sí es la parte peligrosa. Hacerlo bien depende principalmente de disciplina, no de magia.getStaticProps. The migration itself is the dangerous part. Getting it right is mostly about discipline, not magic.

---

Por Qué Esta Migración Rompe el SEO en Primer Lugar

Aquí está la cuestión que la mayoría de tutoriales pasan por alto: WordPress hace una enorme cantidad de trabajo SEO por ti sin que te des cuenta. Yoast o Rank Math genera tus meta tags. WordPress core maneja tu estructura de enlaces permanentes. Tu tema probablemente está generando algún tipo de marcado de esquema. Tu sitemap XML se regenera automáticamente cada vez que publicas.some kind of schema markup. Your XML sitemap auto-regenerates every time you publish.

Cuando extraes la capa de contenido hacia Next.js a través de la API WPGraphQL y la sirves desde un nuevo front-end, toda esa infraestructura se convierte en tu responsabilidad de replicar. Cada. Pieza. Única.WPGraphQL API and serve it from a new front-end, all of that infrastructure becomes your problem to replicate. Every. Single. Piece.

El otro problema es la estructura de URLs. La mayoría de sitios WordPress tienen /category/post-slug/ o /year/month/post-slug/ o simplemente /post-slug/. Next.js te da un lienzo en blanco para el enrutamiento. Ese lienzo en blanco es un cementerio de rankings si no lo planificas cuidadosamente./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.

Los Dos Modos de Fallo que Veo Constantemente

La primera es que equipos migran las URLs y siguen rompiendo cosas -- usualmente porque las redirecciones se aplican inconsistentemente o el nuevo sitemap se publica antes de que las redirecciones estén activas. La segunda es que equipos cambian intencionalmente la estructura de URLs (frecuentemente para limpiarla) y tratan el mapeo de redirecciones como una ocurrencia tardía. Ambas son corregibles. Ninguna es aceptable.

---

Audita Antes de Tocar Nada

No escribas una sola línea de código en Next.js antes de tener un inventario completo de URLs. Yo uso Screaming Frog -- rastreo del sitio WordPress en vivo, exporto cada URL indexable, y lo vuelco en una hoja de cálculo. Para un sitio de 400 páginas eso es quizá una hora de trabajo. Para un sitio de 4,000 páginas sigue siendo una hora, porque la herramienta lo hace automáticamente.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.

Lo que estás capturando:

  • Cada URL canónica actualmente indexada
  • El estado HTTP de cada una (identifica 404s y 301s que ya existen)
  • El título meta y la descripción para cada página
  • Qué páginas tienen datos estructurados (usa Rich Results Test o simplemente inspecciona el código fuente)
  • Enlaces internos entrantes -- para que sepas qué páginas enlazan a cuáles

También extrae tus 50 páginas principales de Google Search Console ordenadas por clics. Estas son las que no puedes permitirte equivocarte. Márcalas en la hoja de cálculo. Trátalas como dependencias en producción.

Seahawk tenía un cliente de e-commerce a finales de 2022 -- una tienda WooCommerce de 1,200 productos migrando a una configuración headless. Pasamos dos días completos en la auditoría antes de escribir código. El cliente pensó que estábamos perdiendo tiempo. Salvamos sus 90k sesiones orgánicas mensuales.

---

Configurar WordPress como un CMS Headless Verdadero

Esta parte es en su mayor parte directa. Instala WPGraphQL y expone tu contenido a través de la API de GraphQL. Pero hay algunas cosas que vale la pena ser deliberado al respecto.

Mantén Yoast (o Rank Math) Ejecutándose en el Lado de WordPress

Aunque ya no sirvas WordPress como el front-end público, mantén tu plugin SEO activo. WPGraphQL for Yoast SEO (o la extensión equivalente de Rank Math) expone todos los meta SEO -- títulos, descripciones, URLs canónicas, datos OG, directivas robots -- directamente a través de la API GraphQL. Eso significa que puedes consultarlo desde Next.js y renderizarlo exactamente como Yoast lo pretendió.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.

Esta fue la lección de esa caída de tráfico de 2019 que mencioné. Asumí que podríamos regenerar títulos a partir del título de la publicación + nombre del sitio en Next.js. Podíamos. Pero Yoast había personalizado manualmente meta títulos para unos 80 de las publicaciones con mejor desempeño, y borramos todo eso. Ocho semanas para recuperarse.

Desactiva el Front-End de WordPress con Cuidado

Una vez que estés listo para dirigir tráfico a Next.js, NO quieres que WordPress sirva su propio front-end simultáneamente. Contenido duplicado a escala. La forma más limpia es establecer un robots.txt en tu instalación de WordPress para Disallow: / mientras tu sitio Next.js entra en vivo, y luego eventualmente bloquea la URL de WordPress completamente para que solo sea accesible internamente o a través de 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.

No te saltes el paso de robots.txt. He visto equipos bloquear WordPress a nivel de CDN y luego descubrir que Googlebot tenía una ruta en caché. Toma meses limpiar.

---

Replicar la Estructura de URLs Exactamente

Mi recomendación predeterminada sólida: mantén tus URLs idénticas. Mismo slug, misma estructura de enlace permanente, mismo comportamiento de barra diagonal final. Cuanto más reflejen las rutas de Next.js las rutas de WordPress, menos redirecciones necesitarás y menos riesgo llevarás.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.

Las rutas dinámicas de Next.js lo hacen fácil. Si tus posts de WordPress viven en /blog/[slug], crea pages/blog/[slug].js. Listo.dynamic routes make this easy. If your WordPress posts live at/blog/[slug], create pages/blog/[slug].js. Done.

Donde se complica es en archivos de categorías, páginas de autor, páginas de etiquetas y archivos paginados (/blog/page/2/). WordPress genera todos estos automáticamente. En Next.js los estás construyendo tú mismo. Muchos equipos depriorizan estos y luego se preguntan por qué la cobertura de rastreo disminuyó./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.

Aquí está mi checklist numerada para paridad de URLs:

  1. Posts/páginas individuales -- coincide el slug exactamente, incluyendo cualquier subcarpeta -- match the slug exactly, including any subfolder
  2. Archivos de categoría -- recrea /category/[slug]/ con getStaticPaths extrayendo todas las categorías de WPGraphQL -- recreate/category/[slug]/with getStaticPaths pulling all categories from WPGraphQL
  3. Archivos de etiquetas -- lo mismo que arriba, no los omitas si reciben tráfico orgánico -- same as above, don't skip these if they get organic traffic
  4. Archivos de autor -- revisa Search Console primero; si tienen cero clics, puedes hacer un 301 a la página de inicio -- check Search Console first; if they get zero clicks, you can 301 them to the homepage
  5. Archivos paginados -- /blog/page/[num]/ vale la pena preservar si tienes muchos posts -- /blog/page/[num]/is worth preserving if you have a lot of posts
  6. Páginas de adjuntos -- casi siempre haz un 301 de estas al post padre; son peso muerto para SEO en WordPress también -- almost always 301 these to the parent post; they're SEO dead weight in WordPress too
  7. URLs de feed -- /feed/ debe hacer 301 a tu nuevo feed RSS si tienes uno, o devolver 410 si no -- /feed/should 301 to your new RSS feed if you have one, or return 410 if not

---

Redirecciones: La Parte Que Todos Subestiman

Si estás cambiando cualquier URL -- lo cual yo cuestionaría, pero a veces es necesario -- tu mapa de redirecciones debe construirse antes del lanzamiento y probarse en un entorno de staging.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.

En Next.js, las redirecciones viven en next.config.js. Para sitios pequeños (menos de 200 redirecciones) eso está bien. Para cualquier cosa más grande, ponlas en un archivo JSON e impórtalo, o usa middleware para manejarlas dinámicamente. El edge middleware de Vercel es excelente para tablas de redirecciones grandes porque se ejecuta antes de que la página se renderice -- cero penalización de latencia.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.

El formato en 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 envía un 301. Úsalo para todos los cambios de URL genuinos. No uses 302 (temporal) a menos que realmente tengas intención de revertirlo -- Google los trata muy diferente. 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.

Prueba cada redirect antes del lanzamiento. Uso un script bash simple que recorre la hoja de cálculo y ejecuta curl en cada URL antigua verificando una respuesta 301 al destino correcto. Toma diez minutos escribirlo, ahorra horas de pánico post-lanzamiento.

---

Meta Tags, URLs Canónicas y Datos Estructurados en Next.js

Aquí es donde la mayoría de migraciones pierden puntos en silencio. El contenido está ahí, las URLs funcionan, pero las señales SEO están mal.

Meta Tags

Usa next-seo. Es el estándar. Pásale los datos que consultaste de WPGraphQL Yoast. Tu app.js recibe una configuración DefaultSeo, y cada página recibe un componente NextSeo con los overrides específicos de la página. Toma el título, descripción, título OG, imagen OG, URL canónica, y directivas robots directamente de la respuesta GraphQL de Yoast -- no reinventes la rueda.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.

Una cosa que causa problemas: las URLs canónicas. En WordPress, Yoast las configura automáticamente. En Next.js necesitas pasar la canónica explícitamente. Si se te olvida, Next.js renderizará páginas sin etiqueta canónica, y si tienes query strings en cualquier lado (paginación, filtros), terminarás con problemas de contenido duplicado más rápido de lo que esperas.

Datos Estructurados

Los temas y plugins de WordPress a menudo generan JSON-LD automáticamente. Eso desaparece en headless. Necesitas reconstruirlo. Para artículos, usa el schema Article. Para productos, Product. Para negocios locales, LocalBusiness. Yo escribo estos como componentes React que aceptan props y retornan una etiqueta <script type="application/ld+json">. Un componente por tipo de schema, reutilizado en toda la 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.

Verifica cada tipo de schema que tenías previamente en la Rich Results Test antes de la migración. Documéntalo. Recréalo. Prueba los nuevos con la misma herramienta después del lanzamiento.before migration. Document them. Recreate them. Test the new ones with the same tool post-launch.

El Sitemap XML

No uses un sitemap estático. Genéralo dinámicamente. Para sitios pequeños, getServerSideProps en una ruta /sitemap.xml funciona. Para sitios grandes con miles de posts, genera el sitemap al momento de la compilación mediante un script personalizado y envíalo a la carpeta public/. Vercel ejecuta esto en cada despliegue -- tu sitemap siempre está actualizado.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.

Envía la nueva URL del sitemap a Google Search Console el primer día que el sitio nuevo esté en vivo. No el tercer día. El primer día.

---

Monitoreo Post-Lanzamiento (La Ventana de 90 Días)

La migración no termina en el lanzamiento. Termina cuando tus rankings se han estabilizado — lo que la documentación de Google sugiere que puede tomar desde algunas semanas hasta varios meses dependiendo del crawl budget y la autoridad del sitio.

Lo que reviso cada día de la semana durante el primer mes:

  • Google Search Console → Reporte de cobertura para nuevos 404s o URLs 'Excluidas' que no deberían estarlo. for new 404s or 'Excluded' URLs that shouldn't be excluded
  • Search Console → Performance -- compara clics e impresiones semana a semana para tus 50 páginas principales -- compare clicks and impressions week-on-week for your top 50 pages
  • Re-rastreo de Screaming Frog del sitio nuevo para detectar cualquier 404 interno o etiquetas canónicas mal configuradas. of the new site to catch any internal 404s or misconfigured canonical tags
  • Core Web Vitals -- sí, el sitio Next.js debería ser más rápido, pero verifica los datos de campo (CrUX), no solo Lighthouse -- yes, the Next.js site should be faster, but verify it in the field data (CrUX), not just Lighthouse

Si ves una caída significativa en las primeras dos o tres semanas, no entres en pánico de inmediato. Casi siempre hay una fluctuación a corto plazo mientras Google recrawlea y reindexea. Lo que buscas son caídas sostenidas después de la semana cuatro. Esa es la señal de que algo estructural está mal.

A fines de 2022 -- proyecto diferente del de e-commerce -- lanzamos una migración Next.js para un blog SaaS y vimos una caída del 20% en impresiones en la segunda semana. Resultó que nuestro sitemap generado dinámicamente estaba incluyendo páginas con noindex porque no habíamos filtrado correctamente la consulta de WPGraphQL. Lo arreglamos en cuatro horas. Los rankings se recuperaron en tres semanas. El monitoreo lo detectó antes de que se agravara.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

¿Cuánto tiempo toma una migración de WordPress a Next.js?

Honestamente, depende más de la complejidad del sitio que de la cantidad de posts. Un sitio de 100 páginas tipo brochure con URLs limpias se puede hacer correctamente en dos o tres semanas. Un blog de 2,000 posts con tipos de post personalizados, campos ACF e integración WooCommerce es un proyecto de mínimo seis a ocho semanas si haces el trabajo de SEO correctamente junto con el desarrollo. No dejes que nadie te diga que es un trabajo de fin de semana.

¿Debo usar el Pages Router o el App Router en Next.js?

A partir de mediados de 2024 estoy optando por el App Router para proyectos nuevos. Pero si tu equipo se siente más cómodo con el Pages Router y esta es una migración sensible al tiempo, usa lo que conoces. Las implicaciones SEO son mínimas -- ambos soportan generación estática, renderizado del lado del servidor, y rutas dinámicas. El paquete next-seo ya tiene soporte para App Router también.next-seo package has App Router support now too.

¿Necesito dejar de usar WordPress hosting completamente?

No. WordPress puede quedarse en su host existente -- WP Engine, Kinsta, Cloudways, lo que sea que estés usando -- y actuar únicamente como API de contenido. El front-end Next.js se despliega en Vercel o Netlify. Los dos se comunican vía HTTP. Algunos clientes incluso prefieren esto porque el equipo editorial mantiene el admin de WordPress que ya conocen.Netlify. The two communicate via HTTP. Some clients actually prefer this because the editorial team keeps the WordPress admin they already know.

¿Qué hay con los plugins de WordPress que afectan SEO -- como redirecciones manejadas en Redirection?

Expórtalos antes de migrar. El plugin Redirection tiene una exportación CSV. Toma todas esas redirecciones existentes y añádelas a tu next.config.js o edge middleware. No asumas que se transferirán automáticamente -- no lo harán, porque viven en la base de datos de WordPress y Next.js no sabe que existen.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.

¿Mi ranking en Google bajará de todas formas?

Casi siempre hay cierta volatilidad a corto plazo. Una migración bien ejecutada sin cambios de URL, redirecciones apropiadas (donde sea necesario), meta y datos estructurados replicados, y un sitemap reenviado debería estabilizarse en cuatro a seis semanas. Los descensos que he visto que duraron meses fueron todos causados por errores técnicos específicos -- no por la migración en sí.

---

La migración no es la parte difícil. La parte difícil es la disciplina de hacer cada paso aburrido e inglorio -- la auditoría, el mapeo de redirecciones, la recreación del schema -- antes de escribir cualquier código Next.js ingenioso. Si consigues ese orden correcto saldrás del otro lado con un front-end más rápido y los mismos rankings con los que empezaste. Posiblemente mejores, una vez que las mejoras de Core Web Vitals se materialicen.Core Web Vitals improvements feed through.

< BACK