Guide : How to Implement Hreflang (Step by Step)

Fonctionnement code pour tout three hreflang méthodes — HTML head balises, HTTP Lien headers, et XML sitemap annotations — plus le syntax règles, à-scale CMS automation, et le validation workflow à confirmer il en réalité shipped correctement.

Première publication : 2 juil. 2026 · Dernière mise à jour : 3 août 2026 · Avancé
1 indice probant sur cette page

Là sont exactly three façons à ajouter hreflang — HTML lien balises dans le head, HTTP Lien réponse headers (pour non-HTML fichiers comme PDFs), or xhtml:lien entries dans an XML sitemap (meilleur à scale). Pick un; Google treats tout three as equivalent et il y a aucun avantage à combining les. Chaque méthode obeys le même deux non-negotiable règles: self-reference (chaque page listes itself) et reciprocity (si A points à B, B doit point back à A, or Google ignores le pair). Codes sont ISO 639-1 langue plus optional ISO 3166-1 alpha-2 region; x-default est le fallback. Generate il tout depuis a unique source de truth, alors valider le rendu head, pas simplement view-source — dans mon study de 374 756 domains, over 67% de hreflang setups avait au moins un problème.

TL;DR — Three méthodes, pick un: HTML <link> balises dans le <head>, HTTP Link: headers (le seulement option pour non-HTML fichiers comme PDFs), or <xhtml:link> entries dans an XML sitemap (meilleur à scale — un machine-generated fichier, easiest à QA). Google dit le three sont equivalent et il y a aucun avantage à combining les. Chaque méthode obeys self-reference + reciprocity, utilise absolute URLs, et utilise ISO 639-1 langue + optional ISO 3166-1 alpha-2 region codes. Generate le entier chose depuis un source de truth — hand-maintained hreflang rots. Alors valider le rendu head, explorer le entier cluster pour reciprocity, et garder re-checking après chaque URL modifier. Faire pas auto-redirect robots d’exploration par geo.

Avant vous écrire a line of code: three decisions

«1. Which method. Google is explicit that the choice is about convenience, not performance — “The three methods are equivalent from Google’s perspective and you can choose the method that’s the most convenient for your site.” My rough rule:

Preuve à l’appui de cette affirmation 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. Portée : Google Search hreflang implementation methods. Niveau de confiance : élevé · Vérifié : Google: Localized versions

» (Traduction) (Résumé en français de la section vingt-neuf, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

  • A handful of URLs, a static or simple site, few locales → HTML <link> tags.
  • Non-HTML assets (PDFs, docs) → HTTP Link: headers (vous have aucun autre option — there’s aucun <head> in a PDF).
  • Nombreux locales, an existing sitemap pipeline, or a headless/JAMstack setup → XML sitemap, generated programmatically.

Le Décision Trees lens walks ce as an réel flowchart.

2. Un source de truth. Whatever méthode vous pick, le annotations devrait être generated depuis un placer — a locale/traduction tableau dans votre database, a CMS relationship champ, or (pour petit sites) a unique spreadsheet. Le unique worst hreflang anti-modèle est hand-maintaining balises par page. Le moment un locale’s template drifts, retourner liens go manquant et pairs obtenir dropped.

3. Ne faites pas combine méthodes. Vous peut exécuter tout three; Google dit il y a aucun avantage, et chaque supplémentaire méthode est un autre surface pour le three copies à disagree avec chaque autre.

Preuve à l’appui de cette affirmation Google requires fully qualified alternate URLs and reciprocal links, and recommends including each page itself in its alternate set. Portée : Google Search hreflang rules shared by all delivery methods. Niveau de confiance : élevé · Vérifié : Google: Hreflang guidelines

Le syntax, verbatim depuis Google, est:

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

A complet working définir pour a multi-language, multi-region cluster with a fallback:

<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/" />

Que exact bloquer goes on chaque page dans le cluster (le US page, le UK page, le German page, et le homepage) — chaque un inclut son propre self-referencing line. c’est ce que satisfies reciprocity.

Placement est a difficile règle. Google: “Le <link> balises doit être à l’intérieur a well-formed <head> section de le HTML.” Et leur propre troubleshooting advice: “Si dans doubt, paste code depuis votre rendu page dans an HTML validator à garantir que le liens sont à l’intérieur le <head> element.”

Ce matters plus que il sounds, parce que de a échec mode la plupart written guides skip: hreflang balises peut être forced out de le <head> et dans le <body>, où ils sont invalide. Dans mon Pubcon Vegas 2019 deck Je flagged ce directement — balises ne peut pas legitimately actif dans le corps (que voudrait let un site hijack autre’s alternates), mais a malformed or injected <p> balise, or an iframe, peut prematurely fermer le <head> donc que tout après il — notamment votre hreflang — renders à l’intérieur le <body>. Le balise est technically présent dans source mais silently invalide. Le fastest façon à debug il est navigateur DOM breakpoints: watch où le balises en réalité land dans le rendu DOM, alors walk back à le markup que broke le <head>.

Quand HTML balises faire sense: petit-à-medium sites avec a manageable number de locales, où le per-page <link> bloquer ne fait pas balloon. On a site avec dozens de locales, chaque page carries a grand bloquer de markup — qui est un raison big sites lean on le sitemap méthode.

ne pas mix hreflang avec autre alternate attributs on le même <link> element. Google’s guidance est explicit que a <link rel="alternate"> carrying hreflang ne devrait pas aussi carry an unrelated alternate attribut comme media dans le même balise — si vous besoin les deux a langue/region alternate et a media-requête alternate pour le même URL, c’est deux séparé <link> elements, pas un combined un. Mixing les est an facile façon à fin up avec a balise Google ne peut pas parse as soit.

Même information, sent dans le HTTP réponse au lieu de le HTML. Le syntax:

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

Remarque le angle brackets autour chaque URL, le semicolon-separated attributs, et le comma separating chaque alternate. Chaque URL dans le header est comma-appended.

Quand vous besoin ce: non-HTML resources. A PDF, a .doc, an image served directement — none of les have a <head> to hold <link> tags, so the header is votre seulement façon to attach hreflang to les.

Configuration considerations: vous définir ces headers à le serveur or CDN couche (an Apache Header directive, an Nginx add_header, a Cloudflare/Fastly/CloudFront réponse-header règle, or votre application’s réponse). Parce que le header est définir par infrastructure plutôt que per-document markup, le reciprocity règle est facile à break ici — le English PDF’s header et le German PDF’s header sont généralement configuré séparément, donc c’est on vous à assurez-vous chaque un listes le entier définir, itself inclus. Garder le header generation driven par le même locale tableau as votre HTML/sitemap approche.

Le invariant à hold sur: chaque alternate réponse carries le identical complet définir, chaque temps. c’est pas suffisant pour le English PDF’s header à liste le German alternate — le German PDF’s réponse a à carry le exact même définir back (itself plus chaque autre alternate), on chaque unique réponse, pas simplement le premier un a robot d’exploration se produit à hit. Treat le header as generated sortie, pas a un-off vous définir et forget.

À scale, ce est généralement le correct appel: le entier cluster lives dans un (or a quelques) machine-generated fichiers, rien bloats chaque page’s <head>, et — parce que le entier relationship graph est dans un placer — c’est par far le easiest méthode à QA. Le syntax:

<?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>

Two choses que trip personnes up in le sitemap méthode:

  1. Le namespace declaration est mandatory. Que xmlns:xhtml="http://www.w3.org/1999/xhtml" on le <urlset> element n’est pas optional decoration — omit il et chaque <xhtml:link> dans le fichier est invalide.
  2. Chaque <url> bloquer doit être self-complet. Notice que les deux <url> bloque ci-dessus liste les deux alternates, notamment leur propre <loc>. Chaque <url> entry carries le complet définir (self-reference + tout alternates). Reciprocity dans a sitemap est simplement “chaque URL’s bloquer lists chaque URL dans le cluster, itself inclus.”

Deux behaviors worth knowing donc vous ne pas over-engineer le generator: le order de le <xhtml:link> children à l’intérieur a <url> bloquer ne fait pas matter à Google — ne pas waste temps sorting les — et ceux <xhtml:link> annotations ne pas count contre votre sitemap’s 50 000-URL-per-fichier limite, since ils sont children de a <url> entry, pas séparé <url> entries themselves.

Generating il programmatically. Le entier point de le sitemap méthode est que c’est a byproduct de votre CMS’s propre traduction données. Si votre CMS déjà knows que /english/page.html et /deutsch/page.html sont translations de chaque autre, votre sitemap generator devrait walk que relationship tableau et emit le <xhtml:link> bloque à construire temps (or à sitemap-requête temps). Faire que et hreflang ne peut pas drift out de sync avec reality — c’est regenerated depuis le source de truth chaque temps, et ajout a locale est a données modifier, pas a hand-edit à travers hundreds de pages.

Pour teams sans dev resources, Je construit a lightweight Google Sheets template dans mon Ahrefs hreflang guide: a Setup tab (pick a par défaut langue plus up à four variants), a URLs tab (paste chaque langue’s URLs dans columns), et a Résultats tab que auto-generates le sitemap XML bloquer pour vous. c’est le “single source of truth” idea fait concrete pour sites aussi petit à justify a réel CMS integration.

The rules que appliquer aucun matter qui méthode vous pick

«These are method-agnostic and non-negotiable. » (Traduction) (Résumé en français de la section soixante, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

  • Self-reference. Chaque page (or chaque <url> bloquer, or chaque header) listes itself. Mueller frames ce as optional-mais-bon-practice, mais skipping il était présent dans 18,0% de le domains dans mon study — automate il et il coûts rien.
  • Reciprocity. “Chaque langue version doit liste itself as bien as tout autre langue versions.” Et le enforcement: “Si deux pages ne pas les deux point à chaque autre, le balises va être ignored. Ce est donc que quelqu’un on un autre site ne peut pas arbitrarily créer a balise naming itself as an alternative version de un de votre pages.” Un manquant retourner lien drops le pair.
  • Absolute, fully-qualified URLs. “Alternate URLs doit être fully-qualified, notamment le transport méthode (http/https)” — donc https://example.com/foo, jamais //example.com/foo or /foo. Et l’URL doit match le exact formulaire Google indexes: protocol, www, trailing slash, et cas tout ont à line up, or le renvoyer-lien match fails.

Getting le codes correct

“Le premier code de le hreflang attribut est le langue code (dans ISO 639-1 format) followed par an optional deuxième code que represents le region code (dans ISO 3166-1 Alpha 2 format).” Combine les avec a dash: en-US. Vous pouvez cible a langue on son propre (es = Spanish everywhere), mais vous ne peut pas cible a region on son propre — il y a toujours a langue premier.

Le mistakes Je voir la plupart souvent (et saw à travers le study dataset):

  • en-UK au lieu de en-GB — uk est Ukrainian, le UK’s region code est gb.
  • jp au lieu de ja pour Japanese, cn au lieu de zh pour Chinese.
  • Three-letter codes (ger, eng) où deux-letter ISO 639-1 est requis.
  • En utilisant EU, UN, or UK as region codes — none sont valide ISO 3166-1 alpha-2 targets.

x-default est le reserved valeur pour le fallback — a langue selector or an auto-redirecting page d’accueil que sert utilisateurs qui match none de votre explicit locales:

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

c’est pas mandatory. Il était le unique la plupart-manquant element dans mon study (56,3% de domains omitted il), mais a manquant x-default ne fait pas break le cluster le façon a manquant reciprocal balise fait — Google simplement falls back à son propre langue/region detection pour unmatched utilisateurs. Ajouter il anyway; c’est a liste de contrôle élément, pas a cluster-breaker. (il y a a dedicated x-default subtopic dans ce cluster.)

Implementing à scale — CMS et plateforme approaches

«WordPress. Yoast SEO does not generate hreflang on its own. To actually output tags you need a multilingual plugin — WPML or Polylang. WPML auto-generates hreflang for every page that has translations, adds an x-default pointing at your default-language version, and by default injects the annotations into the XML sitemap; there’s a setting under WPML → Languages → SEO Options (“Display alternative languages in the HEAD section”) if you want head-tag output instead of, or in addition to, the sitemap. (See WPML’s docs on using it with Yoast.) » (Traduction) (Résumé en français de la section soixante-onze, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.)

Shopify. Shopify Markets automatiquement generates mutually-linked hreflang balises une fois vous avez configuré markets/languages et le contenu est publié et lié dans navigation — qui supprime le la plupart courant échec mode (manquant reciprocal liens) par design. Le catch: Markets’ automatic balises sont souvent langue-seulement (fr, de) plutôt que langue-region (fr-FR, fr-CA), qui under-serves brands que besoin regional specificity — French pour France vs. Canada vs. Belgium. Pour que vous drop à manual <link> balises dans theme.liquid (Shopify’s propre theme hreflang docs montrer le modèle) or an app — et faites attention, parce que mixing automatic Markets balises avec manual/app balises est a documented source de conflicts. Pick un.

Custom / headless / enterprise. Generate le annotations depuis votre traduction-relationship tableau à construire or servir temps, as décrit dans le sitemap section ci-dessus. Ce est le même “single source of truth” principle — hreflang becomes a computed sortie de données votre CMS déjà holds, pas a hand-maintained artifact que peut rot.

Implementation mistakes que break the cluster

Auto-redirecting par geo/IP. Ce est a séparé échec depuis syntax erreurs et c’est pire. Si vous redirection visitors — et surtout robots d’exploration — à a version fondé on perceived emplacement, vous pouvez de-indexer entier regional clusters, parce que Googlebot mostly explore depuis le US. As Je put il dans que Pubcon deck: a geo-redirect “voudrait redirection moteur de recherches à où ils explorer depuis. Google pour instance mostly explore depuis le US donc nous voudrait effectively de-indexer tout geo pages.” il y a a regulatory angle aussi — potential exposure sous EU anti-geoblocking règles. Le correct modèle est redirection utilisateurs, jamais robots d’exploration: detect et (optionally) redirection human visitors, mais toujours let bots reach chaque URL variant directement, avec hreflang doing le réel routing signal. Google’s propre multi-regional guidance recommends a non-intrusive suggestion banner over automatic redirection pour exactly ce raison.

Pointing hreflang à non-canonical, redirigé, or noindexed URLs. Si a locale’s URL changements et le redirection goes dans mais le hreflang encore points à le old URL, votre cluster maintenant références a 301 or a 404 (16,9% de domains dans mon study referenced broken/redirigé pages). Similarly, chaque variant devrait canonicalize à itself; pointing hreflang à une URL c’est canonicalized away, or à a noindexed page, breaks le retourner lien (8,0% pointed à non-URL canoniques).

Inconsistent URL formats. Le hreflang URL et le indexé URL ont à être byte-identical dans formulaire — trailing slash, www, protocol, et cas tout inclus. A mismatch ici est a silent reciprocity échec.

Validating votre implementation après launch

View rendu source, pas simplement raw source. Si votre hreflang est injected par client-side JavaScript, curl or Ctrl+U (“View Page Source”) va montrer rien — mais le balises exist dans le rendu DOM. Confirmer avec GSC Inspection d’URL → “Tester Actif URL” → “View Testé Page,” or a rendu-capable robot d’exploration. Ce est le unique la plupart courant raison quelqu’un dit “my tags are missing” quand ils sont en réalité fine (or le reverse — présent dans source mais broken parce que ils rendre dans le <body>).

Explorer le entier cluster, ne pas spot-vérifier un URL. Reciprocity est a relationship entre pages, donc checking un page indique vous presque rien. Exécuter a robot d’exploration à travers le entier cluster — Screaming Frog’s hreflang audit or Ahrefs Site Audit — à catch manquant retourner balises, non-canonical targets, et broken références à scale. Ahrefs Site Audit’s Hreflangs tab draws le cluster as a graph avec broken liens dans red, qui est far easier à raison à propos de que a CSV.

Vérifier réel SERPs avec &hl= et &gl=. Append le host-langue (&hl=) et geolocation (&gl=) parameters à a Recherche Google URL à preview ce que a donné locale’s résultats en réalité regarder comme, plutôt que guessing depuis votre propre emplacement.

Validation n’est pas a un-time étape. Nouveau locales, URL/redirection changements, et dev/staging config bleeding dans production sont le recurring causes de post-launch breakage. Construire hreflang vérifications dans regression tests et recurring explore, pas simplement a launch-day QA réussir. Mon framing depuis le talks: “quelconque number de choses peut break depuis masking à choses carrying over depuis dev/tester/staging environments.”

Myths worth retiring

«- “Sitemaps process faster than HTML tags.” False. Both are resolved at crawl time — I’ve debunked this directly. The sitemap’s advantage is maintainability and QA, not speed. » (Traduction) (Résumé en français de la section quatre-vingt-quatre, sous-partie un : le texte source est conservé pour vérification lors de la relecture francophone.) «- “Yandex doesn’t support hreflang in sitemaps.” False — Yandex’s own documentation confirms sitemap hreflang support. » (Traduction) (Résumé en français de la section quatre-vingt-quatre, sous-partie deux : le texte source est conservé pour vérification lors de la relecture francophone.) «- “Use all three methods for extra signal.” No benefit per Google, and it just multiplies inconsistency risk. » (Traduction) (Résumé en français de la section quatre-vingt-quatre, sous-partie trois : le texte source est conservé pour vérification lors de la relecture francophone.) «- “A missing x-default breaks the cluster.” False — it’s optional; Google falls back to its own detection. » (Traduction) (Résumé en français de la section quatre-vingt-quatre, sous-partie quatre : le texte source est conservé pour vérification lors de la relecture francophone.) «- “Wrong hreflang gets you penalized.” False — it’s a hint, not a directive. Broken hreflang is ignored, not penalized. » (Traduction) (Résumé en français de la section quatre-vingt-quatre, sous-partie cinq : le texte source est conservé pour vérification lors de la relecture francophone.)

Où to go suivant

Ce article est le comment-à depth sous le hreflang hub — le hub covers ce que hreflang est, pourquoi reciprocity matters, et ce que Bing fait à la place. Le x-default subtopic goes deep on le fallback valeur. Pour le stratégie ce implements, voir le International SEO pillar — hreflang est le technique couche, pas a substitute pour genuine localization.

Ajouter une note d’expert

Épingler une citation d’expert

Nouvelle personne ? Créez son profil non revendiqué à /admin/experts/ → Épingler une citation d’expert d’abord.