Cómo implementar Hreflang (paso a paso)

Código funcional para los tres métodos de hreflang — etiquetas en el head HTML, cabeceras HTTP Link y anotaciones en sitemap XML — además de las reglas de sintaxis, la automatización del CMS a escala y el flujo de validación para confirmar que se publicó correctamente.

Publicado por primera vez: 2 jul 2026 · Última actualización: 22 ago 2026 · Avanzado
Idiomas
1 señal de evidencia en esta página

Hay exactamente tres formas de añadir hreflang: etiquetas HTML <link> en el head, cabeceras de respuesta HTTP Link (para archivos que no son HTML, como los PDF) o entradas <xhtml:link> en un sitemap XML (la mejor opción a escala). Elige una; Google considera equivalentes las tres y combinarlas no aporta ningún beneficio. Todos los métodos obedecen las mismas dos reglas innegociables: autorreferencia (cada página se enumera a sí misma) y reciprocidad (si A apunta a B, B debe apuntar a A o Google ignora la pareja). Los códigos son el idioma ISO 639-1 más la región ISO 3166-1 alpha-2 opcional; x-default es la alternativa. Genéralo todo desde una única fuente de verdad y valida después el head renderizado, no solo «Ver código fuente»: en mi estudio de 374 756 dominios, más del 67 % de las configuraciones de hreflang tenían al menos un problema.

TL;DR — Tres métodos, elige uno: etiquetas <link> HTML en el <head>, cabeceras HTTP Link: (la única opción para archivos que no son HTML, como los PDF) o entradas <xhtml:link> en un sitemap XML (la mejor opción a escala: un archivo generado por máquina y fácil de comprobar). Google dice que los tres son equivalentes y que no hay beneficio en combinarlos. Cada método respeta la autorreferencia y la reciprocidad, usa URL absolutas y códigos ISO 639-1 de idioma más el código regional ISO 3166-1 alpha-2 opcional. Genera todo desde una única fuente de verdad: el hreflang mantenido a mano se deteriora. Después valida el <head> renderizado, rastrea todo el clúster para comprobar la reciprocidad y vuelve a comprobarlo tras cada cambio de URL. No redirijas automáticamente a los rastreadores por geolocalización.

Antes de escribir una línea de código: tres decisiones

1. Qué método usar. Google deja claro que la elección depende de la comodidad, no del rendimiento: “The three methods are equivalent from Google’s perspective and you can choose the method that’s the most convenient for your site.” (traducción) «Los tres métodos son equivalentes desde la perspectiva de Google y puedes elegir el que sea más cómodo para tu sitio». Mi regla aproximada: Evidence for this claim Google supports equivalent HTML, HTTP-header, and sitemap methods for declaring localized versions; HTTP headers can be used for non-HTML files such as PDFs. Scope: Google Search hreflang implementation methods. Confidence: high · Verified: Google: Localized versions

  • Un puñado de URL, un sitio estático o sencillo y pocos idiomas → etiquetas <link> HTML.
  • Recursos que no son HTML (PDF, documentos) → cabeceras HTTP Link: (no tienes otra opción: un PDF no tiene <head>).
  • Muchos idiomas, un pipeline de sitemap existente o una configuración headless/JAMstack → sitemap XML, generado mediante código.

La lente Decision Trees recorre esto como un diagrama de flujo real.

2. Una única fuente de verdad. Elijas el método que elijas, las anotaciones deben generarse desde un solo lugar: una tabla de idiomas/traducciones en tu base de datos, un campo de relación del CMS o, para sitios pequeños, una única hoja de cálculo. El peor antipatrón de hreflang es mantener las etiquetas a mano en cada página. En cuanto la plantilla de un idioma diverge, desaparecen los enlaces de retorno y se descartan parejas.

3. No combines métodos. Puedes ejecutar los tres, pero Google dice que no aporta ningún beneficio y cada método adicional es otra superficie donde las tres copias pueden discrepar. Evidence for this claim Google requires fully qualified alternate URLs and reciprocal links, and recommends including each page itself in its alternate set. Scope: Google Search hreflang rules shared by all delivery methods. Confidence: high · Verified: Google: Hreflang guidelines

La sintaxis, literalmente de Google, es:

<link rel="alternate" hreflang="lang_code" href="url_of_page" />

Un conjunto completo y funcional para un clúster multilingüe y multirregional con alternativa:

<link rel="alternate" hreflang="en-us" href="https://example.com/us/" />
<link rel="alternate" hreflang="en-gb" href="https://example.com/uk/" />
<link rel="alternate" hreflang="de" href="https://example.com/de/" />
<link rel="alternate" hreflang="x-default" href="https://example.com/" />

Ese bloque exacto va en cada página del clúster (la de EE. UU., la del Reino Unido, la alemana y la página de inicio); cada una incluye su propia línea autorreferente. Eso es lo que satisface la reciprocidad.

La ubicación es una regla estricta. Google dice: “The <link> tags must be inside a well-formed <head> section of the HTML.” (traducción) «Las etiquetas <link> deben estar dentro de una sección <head> bien formada del HTML». Y su propio consejo para solucionar problemas es: “If in doubt, paste code from your rendered page into an HTML validator to ensure that the links are inside the <head> element.” (traducción) «Si tienes dudas, pega el código de tu página renderizada en un validador HTML para asegurarte de que los enlaces están dentro del elemento <head>».

Esto importa más de lo que parece, por un modo de fallo que muchas guías escritas omiten: las etiquetas hreflang pueden salir del <head> y acabar en el <body>, donde son inválidas. En mi presentación de Pubcon Vegas 2019 lo señalé directamente: las etiquetas no pueden vivir legítimamente en el body (eso permitiría que un sitio secuestrara las alternativas de otro), pero una etiqueta <p> mal formada o inyectada, o un iframe, puede cerrar prematuramente el <head>, de modo que todo lo que viene después —incluido tu hreflang— se renderiza dentro del <body>. La etiqueta está técnicamente presente en el código fuente, pero es inválida en silencio. La forma más rápida de depurarlo son los puntos de interrupción del DOM del navegador: observa dónde aterrizan realmente las etiquetas en el DOM renderizado y después vuelve al marcado que rompió el <head>.

Cuándo tienen sentido las etiquetas HTML: sitios pequeños o medianos con un número de idiomas manejable, donde el bloque <link> por página no se dispare. En un sitio con docenas de idiomas, cada página lleva un bloque grande de marcado; por eso los sitios grandes suelen apoyarse en el método del sitemap.

No mezcles hreflang con otros atributos alternate en el mismo elemento <link>. La indicación de Google es explícita: un <link rel="alternate"> que lleve hreflang no debe llevar también un atributo alternativo no relacionado como media; si necesitas tanto una alternativa de idioma/región como una alternativa de consulta de medios para la misma URL, son dos elementos <link> separados, no uno combinado. Mezclarlos es una forma fácil de acabar con una etiqueta que Google no pueda interpretar como ninguna de las dos cosas.

La misma información, enviada en la respuesta HTTP en lugar del HTML. La sintaxis es:

Link: <https://example.com/file.pdf>; rel="alternate"; hreflang="en",
      <https://de-ch.example.com/file.pdf>; rel="alternate"; hreflang="de-ch"

Fíjate en los corchetes angulares alrededor de cada URL, los atributos separados por punto y coma y la coma que separa cada alternativa. Cada URL de la cabecera se añade separada por comas.

Cuándo lo necesitas: recursos que no son HTML. Un PDF, un .doc o una imagen servida directamente no tiene <head> donde colocar etiquetas <link>, así que la cabecera es la única forma de asociarles hreflang.

Consideraciones de configuración: estableces estas cabeceras en la capa del servidor o CDN (una directiva Header de Apache, un add_header de Nginx, una regla de cabeceras de respuesta de Cloudflare/Fastly/CloudFront o la respuesta de tu aplicación). Como la infraestructura establece la cabecera en lugar del marcado de cada documento, es fácil romper la reciprocidad: normalmente la cabecera del PDF inglés y la del PDF alemán se configuran por separado, así que te corresponde asegurarte de que cada una enumera el conjunto completo, incluida ella misma. Haz que la generación de cabeceras dependa de la misma tabla de idiomas que tu HTML o sitemap.

El invariante que debes conservar: cada respuesta alternativa lleva el mismo conjunto completo, todas las veces. No basta con que la cabecera del PDF inglés enumere la alternativa alemana; la respuesta del PDF alemán tiene que devolver exactamente el mismo conjunto (ella misma y todas las demás alternativas), en cada respuesta, no solo en la primera que encuentre un rastreador. Trata la cabecera como una salida generada, no como algo que configuras una vez y olvidas.

A escala, normalmente es la opción adecuada: todo el clúster vive en uno o varios archivos generados por máquina, no hincha el <head> de cada página y, como todo el grafo de relaciones está en un solo lugar, es con diferencia el método más fácil de comprobar. La sintaxis es:

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
  xmlns:xhtml="http://www.w3.org/1999/xhtml">
  <url>
    <loc>https://www.example.com/english/page.html</loc>
    <xhtml:link rel="alternate" hreflang="de"
                href="https://www.example.de/deutsch/page.html"/>
    <xhtml:link rel="alternate" hreflang="en"
                href="https://www.example.com/english/page.html"/>
  </url>
  <url>
    <loc>https://www.example.de/deutsch/page.html</loc>
    <xhtml:link rel="alternate" hreflang="de"
                href="https://www.example.de/deutsch/page.html"/>
    <xhtml:link rel="alternate" hreflang="en"
                href="https://www.example.com/english/page.html"/>
  </url>
</urlset>

Dos aspectos que suelen causar problemas en el método del sitemap:

  1. La declaración del espacio de nombres es obligatoria. El xmlns:xhtml="http://www.w3.org/1999/xhtml" del elemento <urlset> no es decoración opcional: omítelo y cada <xhtml:link> del archivo será inválido.
  2. Cada bloque <url> debe estar completo por sí mismo. Observa que los dos bloques <url> de arriba enumeran las dos alternativas, incluido su propio <loc>. Cada entrada <url> lleva el conjunto completo (autorreferencia y todas las alternativas). En un sitemap, la reciprocidad significa simplemente que «el bloque de cada URL enumera todas las URL del clúster, incluida ella misma».

Conviene conocer dos comportamientos para no complicar de más el generador: a Google no le importa el orden de los hijos <xhtml:link> dentro de un bloque <url>; no pierdas tiempo ordenándolos. Además, esas anotaciones <xhtml:link> no cuentan para el límite de 50 000 URL por archivo de sitemap, porque son hijas de una entrada <url>, no entradas <url> independientes.

Generación programática. El propósito del método del sitemap es que sea un subproducto de los datos de traducción de tu propio CMS. Si tu CMS ya sabe que /english/page.html y /deutsch/page.html son traducciones equivalentes, el generador del sitemap debe recorrer esa tabla de relaciones y emitir los bloques <xhtml:link> en el momento de compilar o de solicitar el sitemap. Así, hreflang no puede desincronizarse de la realidad: se regenera desde la fuente de verdad cada vez, y añadir un idioma es un cambio de datos, no una edición manual en cientos de páginas.

Para equipos sin recursos de desarrollo, construí una plantilla ligera de Google Sheets en mi guía de hreflang de Ahrefs: una pestaña Setup (elige un idioma predeterminado y hasta cuatro variantes), una pestaña URLs (pega las URL de cada idioma en columnas) y una pestaña Results que genera automáticamente el bloque XML del sitemap. Es la idea de «una única fuente de verdad» hecha realidad para sitios demasiado pequeños como para justificar una integración real con el CMS.

Las reglas que se aplican independientemente del método

Son independientes del método y no negociables.

  • Autorreferencia. Cada página (o cada bloque <url>, o cada cabecera) se enumera a sí misma. Mueller lo presenta como una buena práctica opcional, pero estaba ausente en el 18,0 % de los dominios de mi estudio: automatízalo, no cuesta nada.
  • Reciprocidad. “Each language version must list itself as well as all other language versions.” (traducción) «Cada versión lingüística debe enumerarse a sí misma y a todas las demás versiones lingüísticas». Y la regla de aplicación: “If two pages don’t both point to each other, the tags will be ignored. This is so that someone on another site can’t arbitrarily create a tag naming itself as an alternative version of one of your pages.” (traducción) «Si dos páginas no apuntan ambas la una a la otra, las etiquetas se ignorarán. Así se evita que alguien de otro sitio cree arbitrariamente una etiqueta que lo nombre como versión alternativa de una de tus páginas». Un solo enlace de retorno ausente descarta la pareja.
  • URL absolutas y completamente cualificadas. “Alternate URLs must be fully-qualified, including the transport method (http/https)” (traducción) «Las URL alternativas deben estar completamente cualificadas, incluido el método de transporte (http/https)»: https://example.com/foo, nunca //example.com/foo ni /foo. Y la URL debe coincidir con la forma exacta que Google indexa: protocolo, www, barra final y mayúsculas deben coincidir, o fallará la coincidencia del enlace de retorno.

Introducir correctamente los códigos

“The first code of the hreflang attribute is the language code (in ISO 639-1 format) followed by an optional second code that represents the region code (in ISO 3166-1 Alpha 2 format).” (traducción) «El primer código del atributo hreflang es el código de idioma (en formato ISO 639-1), seguido de un segundo código opcional que representa el código regional (en formato ISO 3166-1 Alpha 2)». Combínalos con un guion: en-US. Puedes orientar por un idioma sin región (es = español en cualquier lugar), pero no puedes orientar solo por región: siempre va primero un idioma.

Los errores que veo con más frecuencia (y que también vi en el conjunto de datos del estudio) son:

  • en-UK en lugar de en-GB: uk es ucraniano y el código regional del Reino Unido es gb.
  • jp en lugar de ja para japonés, y cn en lugar de zh para chino.
  • Códigos de tres letras (ger, eng) cuando se exige ISO 639-1 de dos letras.
  • Usar EU, UN o UK como códigos regionales: ninguno es un destino ISO 3166-1 alpha-2 válido.

x-default es el valor reservado para la alternativa: un selector de idioma o una página de inicio que redirige automáticamente y sirve a los usuarios que no coinciden con ninguno de tus idiomas explícitos:

<link rel="alternate" href="https://example.com/" hreflang="x-default" />

No es obligatorio. Fue el elemento que más faltaba en mi estudio (el 56,3 % de los dominios lo omitía), pero un x-default ausente no rompe el clúster como lo haría una etiqueta recíproca ausente: Google simplemente recurre a su propia detección de idioma/región para los usuarios sin coincidencia. Añádelo de todos modos: es una casilla de comprobación, no un elemento que rompa el clúster. (Hay un subtema específico sobre x-default en este clúster.)

Implementación a escala: enfoques para CMS y plataformas

WordPress. Yoast SEO no genera hreflang por sí solo. Para emitir etiquetas necesitas un plugin multilingüe: WPML o Polylang. WPML genera automáticamente hreflang para cada página que tiene traducciones, añade un x-default que apunta a la versión en el idioma predeterminado y, de forma predeterminada, inyecta las anotaciones en el sitemap XML. Hay un ajuste en WPML → Languages → SEO Options («Display alternative languages in the HEAD section») si quieres la salida en etiquetas del head en lugar del sitemap o además de él. (Consulta la documentación de WPML sobre su uso con Yoast.)

Shopify. Shopify Markets genera automáticamente etiquetas hreflang enlazadas mutuamente una vez que has configurado los mercados y los idiomas y el contenido está publicado y enlazado en la navegación; así elimina por diseño el modo de fallo más habitual (los enlaces recíprocos ausentes). La pega: las etiquetas automáticas de Markets suelen ser solo de idioma (fr, de) en lugar de idioma-región (fr-FR, fr-CA), lo que se queda corto para marcas que necesitan especificidad regional: francés para Francia, Canadá o Bélgica. Para eso debes pasar a etiquetas <link> manuales en theme.liquid (la documentación de Shopify sobre hreflang muestra el patrón) o a una aplicación; ten cuidado, porque mezclar las etiquetas automáticas de Markets con etiquetas manuales o de una aplicación es una fuente documentada de conflictos. Elige una sola opción.

Personalizado / headless / empresarial. Genera las anotaciones a partir de tu tabla de relaciones de traducción en el momento de compilar o servir, como se describe arriba en la sección del sitemap. Es el mismo principio de «una única fuente de verdad»: hreflang se convierte en una salida calculada a partir de los datos que tu CMS ya conserva, no en un artefacto mantenido a mano que pueda deteriorarse.

Errores de implementación que rompen el clúster

Redirigir automáticamente por geolocalización/IP. Este es un fallo independiente de los errores de sintaxis y es peor. Si rediriges a los visitantes, especialmente a los rastreadores, a una versión según su ubicación percibida, puedes desindexar clústeres regionales completos, porque Googlebot rastrea principalmente desde EE. UU. Como dije en esa presentación de Pubcon: una redirección geográfica «redirigiría los motores de búsqueda al lugar desde el que rastrean. Google, por ejemplo, rastrea principalmente desde EE. UU., así que desindexaríamos de hecho todas las páginas geográficas». También existe un ángulo regulatorio: posible exposición a las normas de la UE contra el geobloqueo. El patrón correcto es redireccionar a usuarios, nunca a rastreadores: detecta y, opcionalmente, redirige a los visitantes humanos, pero permite siempre que los bots lleguen directamente a todas las variantes de URL y deja que hreflang sea la señal de enrutamiento. La guía multirregional de Google recomienda un banner de sugerencia no intrusivo en lugar de la redirección automática por este motivo.

Apuntar hreflang a URL secundarias, redirigidas o excluidas de la indexación. Si cambia la URL de un idioma, se añade la redirección, pero hreflang sigue apuntando a la URL antigua, tu clúster ahora referencia una 301 o una 404 (el 16,9 % de los dominios de mi estudio hacía referencia a páginas rotas o redirigidas). Del mismo modo, cada variante debe declararse a sí misma como URL principal; apuntar hreflang a una URL cuya versión principal queda fuera del clúster o a una página excluida de la indexación rompe el enlace de retorno (el 8,0 % apuntaba a URL secundarias).

Formatos de URL incoherentes. La URL de hreflang y la URL indexada deben ser idénticas byte a byte en su forma: barra final, www, protocolo y mayúsculas incluidos. Un desajuste provoca un fallo de reciprocidad silencioso.

Validar la implementación después del lanzamiento

Mira la fuente renderizada, no solo la fuente original. Si tu hreflang se inyecta mediante JavaScript del lado del cliente, curl o Ctrl+U («Ver código fuente») no mostrará nada, pero las etiquetas existirán en el DOM renderizado. Confírmalo con Inspección de URL de GSC → «Probar URL publicada» → «Ver página probada», o con un rastreador capaz de renderizar. Esta es la razón más habitual por la que alguien dice «faltan mis etiquetas» cuando en realidad funcionan (o al revés: están presentes en el código fuente, pero fallan porque se renderizan en el <body>).

Rastrea todo el clúster, no compruebes una sola URL. La reciprocidad es una relación entre páginas, así que comprobar una página no dice casi nada. Ejecuta un rastreador en todo el clúster —la auditoría de hreflang de Screaming Frog o Ahrefs Site Audit— para detectar etiquetas de retorno ausentes, destinos no canónicos y referencias rotas a escala. La pestaña Hreflangs de Ahrefs Site Audit dibuja el clúster como un grafo con los enlaces rotos en rojo, lo que es mucho más fácil de razonar que un CSV.

Verifica las SERP reales con &hl= y &gl=. Añade los parámetros de idioma del host (&hl=) y geolocalización (&gl=) a una URL de búsqueda de Google para previsualizar cómo se ven realmente los resultados de un idioma, en lugar de adivinar según tu propia ubicación.

La validación no se hace una sola vez. Los idiomas nuevos, los cambios de URL/redirección y la configuración de desarrollo o staging que se filtra a producción son causas recurrentes de roturas tras el lanzamiento. Integra las comprobaciones de hreflang en pruebas de regresión y rastreos periódicos, no solo en una revisión de calidad el día del lanzamiento. Mi formulación en las charlas es: «cualquier cantidad de cosas puede romperse, desde el enmascaramiento hasta elementos que se arrastran de entornos de desarrollo/pruebas/staging».

Mitos que conviene retirar

  • «Los sitemaps se procesan más rápido que las etiquetas HTML». Falso. Ambos se resuelven durante el rastreo; lo he desmentido directamente. La ventaja del sitemap es el mantenimiento y la comprobación, no la velocidad.
  • «Yandex no admite hreflang en sitemaps». Falso: la documentación de Yandex confirma que admite hreflang en sitemaps.
  • «Usa los tres métodos para obtener una señal adicional». No aporta ningún beneficio según Google y multiplica el riesgo de incoherencias.
  • «Un x-default ausente rompe el clúster». Falso: es opcional; Google recurre a su propia detección.
  • «Un hreflang incorrecto provoca una penalización». Falso: es una sugerencia, no una directiva. Un hreflang roto se ignora, no se penaliza.

Qué leer después

Este artículo es la guía práctica detallada del hub de hreflang: el hub explica qué es hreflang, por qué importa la reciprocidad y qué hace Bing en su lugar. El subtema x-default profundiza en el valor alternativo. Para la estrategia que aquí se implementa, consulta el pilar de SEO internacional: hreflang es la capa técnica, no un sustituto de una localización genuina.

Add an expert note

Pin an expert quote

New person? Create their unclaimed profile at /admin/experts/ → Pin a quote first.