Si Google sigue mostrando tu página en francés a usuarios ingleses (o tu página de producto en español a compradores alemanes), no tienes un “problema con Google”. Tienes un problema de señales. Y hreflang es una de las señales más fuertes que puedes enviar—cuando está correcta. Cuando está mal, es básicamente un megáfono que grita contradicciones al índice.
WordPress multilingüe empeora esto: los plugins inyectan etiquetas, los temas sobrescriben los encabezados, las cachés sirven HTML obsoleto, los CDNs normalizan encabezados, y de pronto tu mapa de idiomas cuidadosamente diseñado se vuelve una novela de “elige tu propia aventura”. A Google no le gustan esas situaciones.
Qué hace realmente hreflang (y qué no hace)
hreflang no es un truco para mejorar el posicionamiento. No es un interruptor mágico para “posicionarme en Alemania”. Es una señal de desambiguación que le dice a Google: “Estas URL son páginas equivalentes en diferentes idiomas o variantes regionales. Por favor, muestra la correcta al usuario adecuado.”
En términos operativos: hreflang es una tabla de enrutamiento para los resultados de búsqueda. Si la tabla de enrutamiento es inconsistente, los paquetes siguen fluyendo—solo que al lugar equivocado.
Lo que hreflang influye
- Segmentación por idioma/región en los resultados: ayuda a Google a elegir la variante correcta.
- Manejo de contenido duplicado entre locales: reduce la probabilidad de que Google trate las traducciones como duplicados que compiten entre sí.
- Higiene del índice: ayuda a agrupar variantes en un conjunto ordenado.
Lo que hreflang no hace
- No reemplaza la calidad de la traducción. El contenido basura de máquina sigue rindiendo como contenido basura de máquina.
- No anula el canonical. Canonical es una señal de consolidación más fuerte; si canonical entra en conflicto con hreflang, Google suele seguir el canonical y hacer caso omiso de hreflang.
- No soluciona problemas de geolocalización/IP. Si tu servidor redirige según IP o Accept-Language sin URLs estables, hreflang no te salvará.
Consejo con opinión: si trabajas en multilingüe, necesitas URLs estables y rastreables para cada locale. Si no tienes eso, deja de tocar etiquetas y rediseña primero la estrategia de URLs.
Una cita para tener en la mesa, porque se aplica dolorosamente bien a las señales SEO:
John Allspaw (idea parafraseada): “La fiabilidad viene de diseñar sistemas que esperan fallos—y los manejan con gracia.”
hreflang es ingeniería de fiabilidad para la segmentación en buscadores. Diseñas pensando en el modo de fallo donde Google se confunde, porque Google se confundirá.
Hechos interesantes y contexto histórico
Un poco de contexto ayuda, porque los problemas de hreflang rara vez son “solo un bug de plugin”. Normalmente son decisiones antiguas de la web que chocan con el comportamiento moderno del indexado.
- hreflang existe desde antes que la mayoría de plugins multilingües de WordPress. Se popularizó a principios de la década de 2010, cuando sitios globales se dieron cuenta de que solo canonical no podía manejar bien las variantes por idioma.
- Google y otros motores implementaron hreflang de forma diferente al principio. Ese legado explica por qué aún ves informes raros de “funciona en Bing, falla en Google”.
- “x-default” se introdujo como una válvula de escape. Es para una página selectora genérica o fallback, no para “no sé qué poner aquí”.
- hreflang es una pista, no una directiva. Aunque esté perfecto, Google puede elegir una URL distinta si otras señales discrepan (canonicals, enlaces internos, sitemaps, redirecciones).
- Las etiquetas de retorno son obligatorias en la práctica. La especificación se puede leer de forma ambigua, pero Google espera enlace recíproco entre alternates (A apunta a B, B apunta a A).
- Los códigos de locale son estrictos. “en-UK” está mal; “en-GB” es correcto. Estos errores pequeños causan un caos desproporcionado.
- Los sitemaps XML también pueden llevar hreflang. Esto es útil cuando el HTML está cacheado o templado de forma inconsistente, pero introduce un segundo lugar donde pueden romperse las cosas.
- WordPress históricamente no fue construido para URLs multilingües. Multisite, locales basados en directorios y traducciones basadas en plugins se añaden a un core que asume un sitio = un idioma.
Guía rápida de diagnóstico
Si estás de guardia por incendios SEO (felicidades, te has unido a un club especial), necesitas un camino corto hacia la verdad. Aquí está la forma más rápida de encontrar el cuello de botella sin leer 40 páginas de la interfaz de Search Console.
Primero: determina si Google está viendo el HTML equivocado
- Obtén el HTML de la página como un cliente tipo bot e inspecciona las etiquetas hreflang.
- Compara el HTML servido con y sin cookies, y con distintos encabezados Accept-Language.
- Verifica que las cachés no estén sirviendo el locale equivocado (encabezados Vary, reglas del CDN, claves de caché de página completa).
Segundo: comprueba canonical y redirecciones (las “señales fuertes”)
- Confirma que cada URL de locale tenga canonical a sí misma (o canonical al objetivo de locale correcto) de forma consistente.
- Confirma que no exista una cadena de redirecciones que colapse locales a una sola URL.
- Confirma que la normalización de slash final y de parámetros no cree duplicados sin hreflang correspondiente.
Tercero: valida la reciprocidad y la completitud
- Para cada variante de idioma: que estén presentes todas las alternates, códigos correctos, URLs absolutas correctas.
- Cada alternate debe devolver el enlace de vuelta (etiquetas de retorno).
- x-default existe solo cuando realmente tienes una experiencia por defecto.
Cuarto: compara sitemaps vs HTML
- Si usas hreflang en sitemaps, confirma que coincida exactamente con el HTML.
- Elige unas pocas URLs representativas; no intentes inspeccionar 10.000 líneas a ojo.
Quinto: confirma el comportamiento de agrupamiento de Google
- Busca síntomas como “Duplicado, Google eligió un canonical distinto al del usuario”.
- Revisa resultados indexados por locale. ¿Están indexadas las páginas correctas? ¿O se están plegando en una sola?
Broma #1: depurar hreflang es como DNS—eventualmente descubres que no era “Google”, eras tú, hace seis semanas, después de una cerveza.
Modos de fallo: cómo se rompe hreflang en WordPress
1) El plugin genera hreflang y el tema también genera hreflang
Este es el clásico problema de “dos fuentes de verdad”. Obtienes etiquetas duplicadas link rel="alternate", a veces con URLs diferentes. Google no elige educadamente la mejor; trata el conjunto como poco fiable.
Qué hacer: elige exactamente un generador: WPML/Polylang/MultilingualPress/tu plugin SEO personalizado. Desactiva todos los demás puntos de inyección de hreflang (tema, funciones personalizadas, módulos del plugin SEO).
2) El canonical apunta al locale equivocado
Si tu página en inglés tiene canonical a la página principal del idioma por defecto, le has dicho a Google “son lo mismo, consolida”. hreflang intenta decir “son variantes diferentes”. Canonical suele ganar.
3) Redirecciones automáticas basadas en el idioma del navegador
Las redirecciones por idioma del navegador parecen “amigables para el usuario” hasta que te das cuenta de que bloquean el rastreo, rompen las URLs estables y hacen que Googlebot vea contenido distinto según los encabezados. Si debes hacerlo, hazlo de forma suave (banner/sugerencia) y mantén accesibles las URLs de locale.
4) Las claves de caché no varían por locale
Las cachés de página completa y los CDNs a menudo cachean solo por URL. Si tu selección de idioma se basa en cookies o encabezados, puedes servir HTML en alemán en una URL en inglés—con etiquetas hreflang en alemán. Eso no es “multilingüe”. Es ruleta.
5) Desajustes en slash final y normalización de URL
Si hreflang apunta a /fr/page pero el canonical es /fr/page/, estás fabricando duplicados. Lo mismo con http/https, www/no-www, mayúsculas/minúsculas y parámetros de consulta como etiquetas de seguimiento.
6) Faltan etiquetas de retorno desde un locale
Un patrón común: inglés lista alternates para todos los idiomas, pero una página traducida falta las alternates por completo (sobrescritura de plantilla, noindex o contenido construido con un template de tipo de post diferente). Eso rompe el clúster.
7) Códigos de idioma-región incorrectos
“en-UK” es el mayor fracaso. También “es-LA” (no es una región válida) y “cn” (China es “CN”, el idioma es “zh”). Google no te corregirá la tarea.
8) Estás mezclando modelos de traducción
Locales por directorio (/en/, /fr/) más dominios separados más parámetros. No lo hagas. Elige un modelo y ejecútalo con limpieza, porque cualquier híbrido se convierte en una carrera de debugging.
Tareas prácticas: comandos, salidas y decisiones (12+)
Estos son los controles básicos que puedes ejecutar desde una terminal. No reemplazarán Search Console, pero te dirán qué están realmente sirviendo tus servidores. Cada tarea incluye: comando, salida de ejemplo, qué significa y qué decisión tomar.
Tarea 1: Obtener HTML y extraer etiquetas hreflang
cr0x@server:~$ curl -sS -A "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" https://example.com/en/product/widget/ | grep -i 'rel="alternate"'
<link rel="alternate" hreflang="en" href="https://example.com/en/product/widget/" />
<link rel="alternate" hreflang="fr" href="https://example.com/fr/produit/widget/" />
<link rel="alternate" hreflang="de" href="https://example.com/de/produkt/widget/" />
<link rel="alternate" hreflang="x-default" href="https://example.com/product/widget/" />
Qué significa: hreflang existe en el HTML de esta página. Buen comienzo.
Decisión: Si faltan etiquetas o están obviamente incorrectas, corrige la generación en la fuente (plugin/tema). Si se ven bien, continúa con las comprobaciones de reciprocidad y canonical.
Tarea 2: Verificar canonical en cada página de locale
cr0x@server:~$ curl -sS https://example.com/fr/produit/widget/ | grep -i 'rel="canonical"'
<link rel="canonical" href="https://example.com/en/product/widget/" />
Qué significa: La página en francés tiene canonical hacia inglés. Eso le dice a Google que consolide el francés en inglés.
Decisión: Corrige el canonical para que sea autorreferencial por locale (o canonicals hacia la URL de locale correcta). Luego revalida hreflang.
Tarea 3: Comprobar comportamiento de redirecciones (¿se colapsan los locales?)
cr0x@server:~$ curl -sS -I https://example.com/de/produkt/widget/ | sed -n '1,10p'
HTTP/2 301
date: Sat, 27 Dec 2025 10:11:12 GMT
location: https://example.com/en/product/widget/
cache-control: max-age=3600
Qué significa: La URL en alemán redirige a inglés. hreflang no puede funcionar si el objetivo no permanece en su sitio.
Decisión: Elimina o acota las redirecciones. Cada URL de locale debe devolver 200 con el contenido del locale.
Tarea 4: Detectar problemas de cambio de idioma basado en cookies
cr0x@server:~$ curl -sS -I https://example.com/product/widget/ | grep -i 'set-cookie'
set-cookie: pll_language=fr; path=/; secure; HttpOnly
Qué significa: La URL “por defecto” está estableciendo una cookie de idioma. Eso puede estar bien, pero es una señal de alerta para caché y consistencia con bots.
Decisión: Asegura que los bots sigan recibiendo hreflang y canonical consistentes, y que la caché varíe apropiadamente (o evita el locale basado en cookie en URLs compartidas).
Tarea 5: Comparar salida con distintos encabezados Accept-Language
cr0x@server:~$ curl -sS -H "Accept-Language: de-DE,de;q=0.9" https://example.com/en/product/widget/ | grep -i 'html lang=' | head -n 1
<html lang="de-DE">
Qué significa: Pediste /en/ pero obtuviste HTML en alemán. Ese es un fallo grave: la URL y el idioma no deben discrepar.
Decisión: Desactiva el cambio de idioma impulsado por encabezados para las URLs de locale; reserva eso para una página selectora, o solo para la raíz con el x-default apropiado.
Tarea 6: Comprobar encabezado Vary (corrección de caché)
cr0x@server:~$ curl -sS -I https://example.com/en/product/widget/ | grep -i '^vary:'
Vary: Accept-Encoding
Qué significa: La caché no varía por cookies ni por Accept-Language. Si tu sitio cambia idioma según cualquiera de esos, tu caché puede mezclar idiomas.
Decisión: O deja de variar contenido por cookie/encabezado para la misma URL, o añade comportamiento Vary correcto y segmentación de caché (a menudo difícil con CDNs).
Tarea 7: Confirmar que el sitemap contiene las URLs de locale esperadas
cr0x@server:~$ curl -sS https://example.com/sitemap_index.xml | grep -Eo '<loc>[^<]+' | head
<loc>https://example.com/page-sitemap.xml
<loc>https://example.com/product-sitemap.xml
<loc>https://example.com/fr/page-sitemap.xml
<loc>https://example.com/de/page-sitemap.xml
Qué significa: Tienes entradas de sitemap por locale (bien). Ahora verifica que contengan las URLs correctas y las extensiones hreflang si se usan.
Decisión: Si el sitemap carece de URLs de locale, corrige la configuración del plugin SEO; no confíes en el descubrimiento.
Tarea 8: Extraer anotaciones hreflang desde un sitemap (si existe)
cr0x@server:~$ curl -sS https://example.com/product-sitemap.xml | grep -i 'xhtml:link' | head -n 6
<xhtml:link rel="alternate" hreflang="en" href="https://example.com/en/product/widget/" />
<xhtml:link rel="alternate" hreflang="fr" href="https://example.com/fr/produit/widget/" />
<xhtml:link rel="alternate" hreflang="de" href="https://example.com/de/produkt/widget/" />
Qué significa: Existe hreflang a nivel de sitemap. Excelente—salvo que discrepe con el HTML.
Decisión: Haz que HTML y sitemap coincidan. Elige una fuente canónica del mapeo de URLs (normalmente el plugin de traducción) y alimenta ambas salidas desde él.
Tarea 9: Comprobar múltiples generadores de hreflang (etiquetas duplicadas)
cr0x@server:~$ curl -sS https://example.com/en/product/widget/ | grep -ic 'rel="alternate"'
12
Qué significa: Doce etiquetas alternate es sospechoso a menos que realmente tengas muchas variantes. A menudo son bloques duplicados.
Decisión: Mira la sección head e identifica qué componente emite cada bloque. Desactiva el emisor extra.
Tarea 10: Confirmar que el estado HTTP es 200 para todos los alternates
cr0x@server:~$ for u in \
https://example.com/en/product/widget/ \
https://example.com/fr/produit/widget/ \
https://example.com/de/produkt/widget/ ; do
printf "%s " "$u"
curl -sS -o /dev/null -w "%{http_code}\n" "$u"
done
https://example.com/en/product/widget/ 200
https://example.com/fr/produit/widget/ 200
https://example.com/de/produkt/widget/ 404
Qué significa: Un alternate está roto (404). Eso rompe el clúster y causa síntomas de “sin etiquetas de retorno” / “hreflang inválido”.
Decisión: Repara la URL de traducción faltante o elimínala del hreflang hasta que exista. No anuncies endpoints muertos.
Tarea 11: Validar los códigos de idioma-región usados en el sitio
cr0x@server:~$ curl -sS https://example.com/en/product/widget/ | grep -Eo 'hreflang="[^"]+"' | sort -u
hreflang="de-DE"
hreflang="en-UK"
hreflang="fr-FR"
hreflang="x-default"
Qué significa: “en-UK” es inválido. Usa “en-GB”. También decide si realmente necesitas variantes regionales; si no, mantente con solo idioma (en, fr, de).
Decisión: Normaliza los códigos en todo el sitio. En los plugins de WordPress normalmente es una configuración por idioma.
Tarea 12: Detectar rápidamente mismatch canonical/hreflang
cr0x@server:~$ curl -sS https://example.com/fr/produit/widget/ | awk 'BEGIN{IGNORECASE=1} /rel="canonical"/{print} /rel="alternate"/{print}'
<link rel="canonical" href="https://example.com/en/product/widget/" />
<link rel="alternate" hreflang="fr" href="https://example.com/fr/produit/widget/" />
<link rel="alternate" hreflang="en" href="https://example.com/en/product/widget/" />
Qué significa: La página afirma ser francesa, pero el canonical dice “trátame como inglés”. Eso es un conflicto.
Decisión: Corrige las reglas de canonical. Para páginas multilingües, el patrón seguro por defecto es canonical autorreferencial por locale.
Tarea 13: Confirmar que directivas robots no bloquean un locale
cr0x@server:~$ curl -sS https://example.com/de/produkt/widget/ | grep -i 'meta name="robots"' || echo "no meta robots tag found"
<meta name="robots" content="noindex,follow" />
Qué significa: Le estás diciendo a Google que no indexe la página alemana. hreflang no puede mostrar una página que no está indexada.
Decisión: Elimina el noindex accidental de las páginas de locale en producción; mantén noindex solo en staging.
Tarea 14: Verificar que robots.txt no bloquee rutas de locale
cr0x@server:~$ curl -sS https://example.com/robots.txt | sed -n '1,120p'
User-agent: *
Disallow: /wp-admin/
Disallow: /de/
Sitemap: https://example.com/sitemap_index.xml
Qué significa: /de/ está bloqueado. Eso es un autogol.
Decisión: Elimina el disallow para locales en producción. El re-rastreo llevará tiempo, pero primero debes dejar de bloquearlos.
Tarea 15: Encontrar hostnames mezclados (www vs non-www) en alternates
cr0x@server:~$ curl -sS https://example.com/en/product/widget/ | grep -i 'hreflang' | grep -Eo 'https?://[^"]+' | sort -u
https://example.com/en/product/widget/
https://www.example.com/fr/produit/widget/
Qué significa: Las alternates mezclan hostnames. Eso crea identidades de URL duplicadas y hace que los clústeres sean inestables.
Decisión: Normaliza la configuración del sitio en WordPress y aplica redirecciones para que hreflang use siempre el host canónico.
Errores comunes: síntoma → causa raíz → solución
1) Síntoma: Los resultados muestran la página en el idioma equivocado a muchos usuarios
Causa raíz: Canonical apunta a un “idioma principal”, colapsando todos los locales. O las redirecciones fuerzan a los usuarios a un único locale.
Solución: Canonical autorreferencial por locale. Elimina redirecciones que colapsen locales. Asegura que cada URL de locale devuelva 200 y sea indexable.
2) Síntoma: Search Console informa “No return tags”
Causa raíz: Una o más alternates no enlazan de vuelta (plantilla sin etiquetas, 404 o noindex). A veces solo fallan tipos de post específicos.
Solución: Asegura que el mapeo de traducciones esté completo. Confirma que cada variante de locale emita el conjunto completo de alternates, incluyéndose a sí misma.
3) Síntoma: “Unknown language code” o “invalid hreflang”
Causa raíz: Códigos ISO equivocados (“en-UK”), regiones falsas (“es-LA”) o usar guiones bajos (“en_US”) en lugar de guiones.
Solución: Normaliza a etiquetas válidas estilo BCP 47 usadas por Google: idioma-región con guion, región en mayúsculas (en-GB), o solo idioma (en).
4) Síntoma: Las etiquetas hreflang están presentes, pero Google las ignora
Causa raíz: Señales fuertes en conflicto: mismatch de canonical, enlaces internos inconsistentes, hosts mezclados o desacuerdo sitemap vs HTML.
Solución: Alinea canonical + hreflang + enlaces internos + sitemaps. Google confía más en la consistencia que en una sola etiqueta.
5) Síntoma: Un locale indexa bien; otros casi no indexan
Causa raíz: robots.txt Disallow, meta noindex o bloqueos del servidor (reglas WAF) aplicadas solo a ciertas rutas.
Solución: Verifica robots y encabezados por locale, no solo “a nivel de sitio”. Elimina los bloqueos y luego solicita reindexación para páginas clave.
6) Síntoma: Las alternates llevan a cadenas 301/302
Causa raíz: El plugin emite URLs no canónicas (http vs https, falta slash) o el CDN impone redirecciones después.
Solución: Haz que las URLs en hreflang sean URLs finales de destino (200). Corrige “Site URL”, ajustes de permalinks de WordPress y reglas de redirección en el borde.
7) Síntoma: Los usuarios rebotan porque los dejan en el locale equivocado al hacer clic
Causa raíz: La redirección por idioma del navegador se activa tras aterrizar desde búsqueda, enviando a los usuarios a otro lugar (a veces la home). Eso rompe la intención y la atribución en analítica.
Solución: Evita redirecciones forzadas. Usa un banner: “Parece que prefieres español—¿quieres cambiar?” con una elección persistente.
8) Síntoma: Muchos avisos “Duplicate, Google chose different canonical than user”
Causa raíz: Páginas similares entre locales con canonicals apuntando incorrectamente, o contenido idéntico entre “traducciones” (copias perezosas) que hacen que Google consolide.
Solución: Corrige el canonical. Asegura que las traducciones estén realmente traducidas. Si el contenido es intencionalmente idéntico entre regiones, considera si realmente necesitas URLs separadas.
Listas de verificación / plan paso a paso
Paso 1: Elige y documenta tu modelo de URL
- Un dominio, directorios:
/en/,/fr/(común para WordPress). - Dominios separados:
example.fr,example.de(separación fuerte, más trabajo operativo). - Subdominios:
fr.example.com(punto intermedio).
Hacer: elige uno y mantenlo.
Evitar: mezclar directorios, parámetros y dominios separados “porque marketing lo pidió”. Marketing pide muchas cosas.
Paso 2: Haz que los canonicals sean aburridos
- Cada página de locale debería normalmente tener un canonical autorreferencial.
- Si tienes variantes regionales que son duplicados reales, la canonicalización puede consolidarlas—pero entonces hreflang debe coincidir con esa lógica cuidadosamente.
Paso 3: Genera hreflang desde un mapeo autoritativo
- El mapeo del plugin de traducción (IDs de post enlazados entre idiomas) es la fuente de verdad habitual.
- No edites hreflang por página en producción a mano a menos que disfrutes de un trabajo infinito.
Paso 4: Haz cumplir la consistencia en el borde
- Forza https y un solo hostname (www o no-www).
- Normaliza slashes finales al estilo de permalinks de WordPress.
- Asegura que hreflang use las URLs normalizadas.
Paso 5: Prevén el envenenamiento de caché entre idiomas
- Si el locale varía por ruta de URL, el cacheo es sencillo.
- Si el locale varía por cookie/encabezado, debes variar correctamente las claves de caché—o servirás HTML mezclado en la misma URL.
Paso 6: Valida reciprocidad en un conjunto de muestra
- Elige 20 URLs entre plantillas: home, categoría, producto, post de blog, landing page.
- Para cada una, confirma: alternates completas, etiquetas de retorno presentes, objetivos 200, canonicals sensatas.
Paso 7: Decide cómo usar x-default
- Usa x-default cuando exista una página selectora de idioma o una landing genérica no ligada a un locale.
- No uses x-default como “la página en inglés”, salvo que el inglés sea realmente tu experiencia global por defecto.
Broma #2: x-default no es un cubo de basura. Si lo tratas así, Google reciclará tu tráfico en otro lado.
Paso 8: Implementa cambios con seguridad
- Cambia una cosa a la vez: lógica de canonical primero, luego hreflang, luego sitemaps.
- Purge caches tras el despliegue (caché de la app, caché de objeto si aplica, CDN).
- Re-rastrea un conjunto de prueba con tus comprobaciones desde la terminal antes de celebrar.
Tres micro-historias empresariales desde el frente
Micro-historia 1: El incidente causado por una suposición errónea
Asumieron que Google “lo entendería”. La empresa tenía un sitio WordPress multilingüe: inglés, francés, alemán. La implementación era visualmente lo suficientemente limpia. Los usuarios podían cambiar de idioma. El panel ejecutivo mostraba tráfico internacional. Todos se relajaron.
Luego un equipo regional se quejó de que el tráfico alemán en búsqueda se vino abajo. El equipo SEO abrió Search Console y vio un pantano: las páginas alemanas estaban indexadas, pero seguían apareciendo para búsquedas en inglés, y las páginas en inglés estaban rankeando en Alemania. hreflang estaba presente, así que la suposición fue: “hreflang funciona”.
No funcionaba. El canonical en cada página traducida apuntaba al original en inglés porque alguien configuró el plugin SEO con “canonicalizar traducciones al original”. Esa configuración suena ordenada. También es catastrófica si tu objetivo es la segmentación por idioma. Google hizo exactamente lo que le dijeron: consolidar señales al inglés, y luego ocasionalmente mostró la página alemana porque el contenido parecía relevante.
La solución fue dolorosamente poco glamorosa: hacer canonicals autorreferenciales, regenerar hreflang desde los mapeos de traducción, purgar cachés y reenviar sitemaps. Las posiciones se estabilizaron en semanas. No de la noche a la mañana—porque los sistemas de indexado son distribuidos y pacientes de la peor manera.
La lección: si canonical y hreflang discrepan, canonical suele ganar. No “asumas que Google entenderá”. Google es una máquina que premia la consistencia, no el optimismo.
Micro-historia 2: La optimización que salió mal
Otra organización quería mejorar el rendimiento global. Pusieron un CDN frente a WordPress y activaron “cachea todo”. El tiempo hasta el primer byte mejoró al instante. Todos celebraron. Luego soporte al cliente empezó a recibir quejas extrañas: usuarios en España veían páginas en alemán. Alemanes veían cadenas de UI en inglés. El equipo de marca afirmaba que el sitio se veía “aleatorio”.
El sitio usaba una cookie para almacenar la preferencia de idioma. El CDN cacheaba HTML solo por URL. Así que el primer visitante que golpeara /product/widget/ en alemán llenaría la caché con HTML en alemán. El siguiente visitante—independientemente del idioma—recibía esa página cacheada. Con el hreflang alemán. En la URL en inglés.
Los bots de búsqueda rastrearon una mezcla de versiones según el timing. Algunas páginas terminaron indexadas con señales de idioma equivocadas y los clústeres hreflang se volvieron inconsistentes. Search Console reportó errores de return tag y “alternate page with proper canonical” de forma inconsistente. Nada encajaba porque el sistema ya no era determinista.
La “optimización” se revirtió: la caché se reconfiguró para variar por cookie en el pequeño conjunto de URLs donde existía locale basado en cookie, y migraron a URLs por ruta para el resto. El rendimiento siguió bueno y la aleatoriedad cesó.
La lección: la caché es un amplificador. Si tu selector de idioma no forma parte de la clave de caché, no estás operando multilingüe—estás operando una lotería de idiomas.
Micro-historia 3: La práctica aburrida pero correcta que salvó el día
Un equipo enterprise hizo algo que parece dolorosamente lento en una reunión: escribieron un “Contrato de URLs de Locale” de una página. Documentó los códigos de idioma permitidos, patrones de URL, reglas de canonical y quién era responsable de generar hreflang. También incluyeron un pequeño script de prueba ejecutado en CI que obtenía 10 páginas representativas por locale y comprobaba: estado 200, canonical autorreferencial, presencia de todas las alternates y ausencia de hostnames mezclados.
Meses después, una actualización de tema cambió la plantilla del encabezado y eliminó el hook del plugin que inyectaba las etiquetas hreflang—pero solo para un tipo de post personalizado usado por campañas. El equipo de campañas hubiera lanzado un conjunto de landing multilingües sin hreflang y con canonicals inconsistentes, justo en búsquedas pagadas y orgánicas.
La comprobación de CI lo detectó el mismo día. El lanzamiento fue bloqueado. La gente se quejó, porque bloquear releases es impopular hasta que te salva de explicar variaciones de ingresos a la dirección. La solución fue un parche pequeño al tema: restaurar el hook, confirmar la salida y desplegar.
La lección: las comprobaciones aburridas previenen dramas caros. hreflang no es una configuración única; es un contrato que debes mantener.
Cómo pensar en hreflang en WordPress: decisiones de arquitectura que reducen el dolor
Locales basados en directorios son lo menos sorprendente operativamente
Para WordPress, los locales por ruta (/en/, /fr/) suelen ser el punto óptimo: caché sencilla, separación clara y menos complicaciones cross-domain. Los dominios separados también van bien, pero son operativamente más pesados: certificados, redirecciones, propiedades de Search Console y más puntos de posible mala configuración.
Un sistema de mapeo de traducción, un sistema SEO, una estrategia de caché
Si tomas algo de esto: evita responsabilidades superpuestas. WPML/Polylang mantiene relaciones de traducción. Un plugin SEO puede emitir canonicals y sitemaps. Tu tema puede emitir meta tags. Tu CDN puede reescribir encabezados. Si dos de estas capas “ayudan” con hreflang, obtendrás duplicación o conflicto.
No confíes en la detección automática de idioma para crawlers
La detección de idioma para humanos es una característica UX. Para bots, es fuente de no determinismo. Mantén URLs de locale estables. Ofrece un switcher. Si debes detectar, hazlo solo en la URL raíz y mantén las URLs de locale deterministas y rastreables.
Validación operativa: cómo luce “correcto”
Un clúster hreflang correcto (mínimo viable)
- Cada URL de locale devuelve 200.
- Cada URL de locale incluye
rel="alternate"para todas las variantes, incluyéndose a sí misma. - Cada URL de locale incluye un canonical que coincide con la URL prevista para indexación de ese locale.
- Todos los objetivos alternates son canonicals finales (no redirigen, no están bloqueados, no tienen noindex).
- Los códigos de idioma/región son válidos y consistentes.
- Los enlaces internos mayoritariamente apuntan a páginas del mismo locale (no enlaces masivos a inglés).
Cuándo usar solo idioma vs idioma-región
Si no tienes diferencias regionales significativas, no las inventes. Usa en, fr, de. Las variantes regionales (en-GB, en-US) son para diferencias reales: precios, términos legales, ortografía, restricciones de envío o contenido verdaderamente regional.
Opinión: la segmentación por región es costosa. Si no puedes articular la diferencia en una frase, probablemente estás creando URLs innecesarias que compiten entre sí.
Preguntas frecuentes (FAQ)
1) ¿Necesito hreflang si solo tengo un idioma pero varios países?
Si el contenido es realmente el mismo y solo quieres una página en inglés a nivel mundial, no crees múltiples URLs por país. Si sí tienes URLs separadas (precios, envío, términos legales), entonces sí: hreflang con variantes por región puede ayudar.
2) ¿Pongo hreflang en HTML, en sitemaps o en ambos?
Elige un método a menos que tengas una razón operativa fuerte. HTML es directo y fácil de auditar. Los sitemaps son útiles si el HTML es difícil de controlar o está muy cacheado. Si haces ambos, deben coincidir exactamente, o crearás señales divididas.
3) ¿Cuál es la relación entre hreflang y canonical?
Canonical le dice a Google qué URL es la preferida para indexación. hreflang le dice cómo elegir entre equivalentes para distintos locales. Si canonical colapsa variantes en una URL, hreflang pierde gran parte de su valor.
4) ¿x-default es obligatorio?
No. Es opcional. Úsalo cuando haya una página de fallback neutral (como un selector de idioma) o cuando la experiencia raíz no sea un locale específico. No lo incluyas “porque sí”. Las mejores prácticas sin contexto son cómo se generan incidentes.
5) ¿Puedo usar hreflang con plugins de traducción automática?
Técnicamente sí, pero no confundas “traducido” con “útil”. Google aún puede decidir que las páginas son de baja calidad o demasiado similares y consolidarlas. Hreflang no rescatará contenido pobre.
6) ¿Por qué Search Console muestra errores hreflang pero el tráfico parece estar bien?
Porque la web es desordenada y Google compensa—hasta que deja de compensar. Los errores suelen indicar fragilidad: una actualización de tema, un cambio de caché o una migración pueden convertir “más o menos bien” en “idioma equivocado por todas partes”. Arréglalo cuando sea una advertencia, no cuando sea una caída.
7) ¿Necesito traducir los slugs para que hreflang funcione?
No. Los slugs pueden permanecer iguales entre locales. Lo importante es que cada locale tenga una URL estable y un mapeo hreflang correcto. Traducir slugs puede mejorar UX y CTR en algunos mercados, pero también aumenta el riesgo en migraciones.
8) ¿Cuánto tarda Google en reflejar correcciones de hreflang?
Espera desde días hasta semanas según la frecuencia de rastreo y el tamaño del sitio. Puedes acelerar el descubrimiento con sitemaps actualizados y enlaces internos. No puedes forzar una reagrupación instantánea. Si alguien promete instantáneo, te está vendiendo una sensación.
9) ¿Qué pasa si una traducción no existe para una página?
No incluyas un alternate hreflang para una página que no existe. O bien omite ese idioma para esa URL, o dirige a los usuarios a una página fallback apropiada por locale—con cuidado. Los alternates falsos crean errores de return tag y malos agrupamientos.
10) ¿WordPress multisite facilita hreflang?
A veces. Puede hacer más limpia la separación de locales (sitios separados por idioma), pero añade complejidad operativa (despliegues, plugins, gestión de usuarios, mapeo cross-site). “Facilitar” depende de la habilidad de tu equipo para operarlo.
Conclusión: siguientes pasos que realmente mueven la aguja
Los errores hreflang en WordPress multilingüe rara vez son una sola etiqueta rota. Normalmente son una falla de consistencia entre capas: salida del plugin, lógica de canonical, redirecciones, caché y generación de sitemaps. Trátalo como un incidente de producción: establece una fuente de verdad, elimina señales en conflicto y valida el comportamiento desde el exterior.
Pasos prácticos siguientes (hazlos en orden)
- Elige 10 URLs representativas entre plantillas y locales. Ejecuta las comprobaciones de comandos anteriores y guarda las salidas.
- Corrige primero los conflictos de canonical. Si canonical está mal, hreflang nunca será estable.
- Asegura que cada URL de locale sea determinista: sin redirecciones forzadas, sin cambios de idioma en las rutas de locale.
- Haz que la generación de hreflang sea de una sola fuente (un plugin/módulo), luego purga las cachés.
- Normaliza códigos y hosts (en-GB no en-UK; https solo; www vs non-www).
- Alinea sitemap y HTML si publicas hreflang en ambos.
- Configura una pequeña comprobación automatizada (CI o cron) para detectar regresiones tras actualizaciones de tema/plugin.
Si haces esos pasos, Google seguirá siendo Google—lento, distribuido, ocasionalmente misterioso—pero tu sistema dejará de alimentarle contradicciones. Ahí es cuando la segmentación por idioma empieza a comportarse como ingeniería en lugar de folklore.