Como implementar hreflang (passo a passo)
Código funcional para os três métodos de hreflang — tags HTML no head, cabeçalhos HTTP Link e anotações em sitemap XML — além das regras de sintaxe, automação de CMS em escala e o fluxo de validação para confirmar que foi realmente implementado corretamente.
1 sinal de evidência nesta página
- Ferramenta relacionada ativareturntag - hreflang checker
Existem exatamente três maneiras de adicionar hreflang — tags link HTML no head, cabeçalhos de resposta HTTP Link (para arquivos não HTML, como PDFs) ou entradas xhtml:link em um sitemap XML (melhor em escala). Escolha uma; o Google trata as três como equivalentes e não há benefício em combiná-las. Cada método obedece às mesmas duas regras inegociáveis: autorreferência (cada página lista a si mesma) e reciprocidade (se A aponta para B, B deve apontar de volta para A, ou o Google ignora o par). Os códigos são ISO 639-1 para idioma mais região opcional ISO 3166-1 alpha-2; x-default é o fallback. Gere tudo a partir de uma única fonte de verdade e valide o head renderizado, não apenas o view-source — no meu estudo de 374 756 domínios, mais de 67% das configurações de hreflang tinham pelo menos um problema.
« » (Tradução) (Síntese localizada do trecho três, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«> TL;DR — There are three ways to add hreflang: small <link> tags in your
page’s
<head>, aLink:header your server sends, or entries in your XML sitemap. You only pick one. Whichever you pick, two rules never change: every page lists itself, and every page you link to has to link back — or Google ignores the whole set. Then you check that the tags actually show up in the page the way you meant them to. » (Tradução) (Síntese localizada do trecho quatro, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Start here: you’ve already decided you need hreflang » (Tradução) (Síntese localizada do trecho cinco, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«This is the how-to. If you’re still not sure whether you need hreflang or what it does, read the hreflang overview first — this page assumes you know you have multiple language or country versions of a page and you just want to build the thing correctly. » (Tradução) (Síntese localizada do trecho seis, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## The three ways to add it (pick one) » (Tradução) (Síntese localizada do trecho sete, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«1. HTML <link> tags in the <head>. You add a few lines to the top of each
page’s HTML. Easiest to understand, easiest to see, good for smaller sites.
2. HTTP Link: headers. The same information, sent by your server in the
response instead of in the HTML. This is the only option for files that aren’t
HTML — like a PDF, which has no <head> to put tags in.
3. XML sitemap. You list all the language versions inside your sitemap file
instead of on each page. Best for big sites, because you don’t have to touch
every page — the whole map lives in one place.
» (Tradução) (Síntese localizada do trecho oito, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Google treats all three the same. There’s no “faster” or “stronger” one, and there is no benefit to using more than one at a time — that just gives you more places for things to fall out of sync.
Evidência desta afirmação 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. Escopo: Google Search hreflang implementation methods. Confiança: alta · Verificado: Google: Localized versions» (Tradução) (Síntese localizada do trecho nove, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## What the HTML version looks like » (Tradução) (Síntese localizada do trecho dez, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Say you have a US English page, a UK English page, a German page, and a global homepage that lets people choose. On the US English page you’d put: » (Tradução) (Síntese localizada do trecho onze, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
<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/" />«Read each line as: “there’s an alternate version of this page, it’s for this
language/region, and it lives at this address.” The x-default line is your
fallback for anyone whose language doesn’t match the others.
» (Tradução) (Síntese localizada do trecho treze, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Two things to notice, because they’re the two rules that make hreflang work: » (Tradução) (Síntese localizada do trecho catorze, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«- The US page lists itself (that first en-us line points at the US page
you’re already on).
- Every other page in the set has to carry the same block pointing back. The UK page, the German page, and the homepage all need their own version of these four lines. » (Tradução) (Síntese localizada do trecho quinze, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## The two rules, in plain terms » (Tradução) (Síntese localizada do trecho dezesseis, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«- Every page points back. If your US page links to your German page, the German page has to link to the US page. Miss that return link and Google throws the pair out. This is the rule people break most.
- Every page points to itself. Each version lists its own URL in the set. Google calls this optional but good practice — do it anyway, it keeps everything consistent.
» (Tradução) (Síntese localizada do trecho dezessete, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Use real, complete web addresses » (Tradução) (Síntese localizada do trecho dezoito, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Always use the full address, starting with https://. Not /us/, not
//example.com/us/ — the whole thing, https://example.com/us/. And it has to
match the exact address Google actually indexes: same protocol, same www (or
not), same trailing slash, same capitalization.
» (Tradução) (Síntese localizada do trecho dezenove, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Get the codes right » (Tradução) (Síntese localizada do trecho vinte, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«The code is a two-letter language, optionally followed by a dash and a two-letter
country: en, en-us, de, es-mx. The classic mistakes are en-uk (it’s
en-gb — uk actually means Ukrainian) and jp for Japanese (it’s ja).
» (Tradução) (Síntese localizada do trecho vinte e um, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Then check that it worked » (Tradução) (Síntese localizada do trecho vinte e dois, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«The most important thing beginners miss: after you ship, actually look at the
rendered page to confirm the tags are there and in the <head>. If your tags are
added by JavaScript, they might not show up when you “View Page Source” but will
show up in the live page. Google Search Console’s URL Inspection can show you what
Google actually rendered.
» (Tradução) (Síntese localizada do trecho vinte e três, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Want full code for the header and sitemap methods, how to automate this across a whole CMS, the exact validation steps, and the mistakes that quietly break clusters? Switch to the Avançado tab. » (Tradução) (Síntese localizada do trecho vinte e quatro, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«> TL;DR — Three methods, pick one: HTML <link> tags in the <head>, HTTP
Link:headers (the only option for non-HTML files like PDFs), or<xhtml:link>entries in an XML sitemap (best at scale — one machine-generated file, easiest to QA). Google says the three are equivalent and there’s no benefit to combining them. Every method obeys self-reference + reciprocity, uses absolute URLs, and uses ISO 639-1 language + optional ISO 3166-1 alpha-2 region codes. Generate the whole thing from one source of truth — hand-maintained hreflang rots. Then validate the rendered head, crawl the whole cluster for reciprocity, and keep re-checking after every URL change. Do not auto-redirect crawlers by geo. » (Tradução) (Síntese localizada do trecho vinte e sete, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Before you write a line of code: three decisions » (Tradução) (Síntese localizada do trecho vinte e oito, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«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:
Evidência desta afirmação 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. Escopo: Google Search hreflang implementation methods. Confiança: alta · Verificado: Google: Localized versions» (Tradução) (Síntese localizada do trecho vinte e nove, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«- A handful of URLs, a static or simple site, few locales → HTML <link> tags.
- Non-HTML assets (PDFs, docs) → HTTP
Link:headers (you have no other option — there’s no<head>in a PDF). - Many locales, an existing sitemap pipeline, or a headless/JAMstack setup → XML sitemap, generated programmatically. » (Tradução) (Síntese localizada do trecho trinta, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«The Decision Trees lens walks this as an actual flowchart. » (Tradução) (Síntese localizada do trecho trinta e um, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«2. One source of truth. Whatever method you pick, the annotations should be generated from one place — a locale/translation table in your database, a CMS relationship field, or (for small sites) a single spreadsheet. The single worst hreflang anti-pattern is hand-maintaining tags per page. The moment one locale’s template drifts, return links go missing and pairs get dropped. » (Tradução) (Síntese localizada do trecho trinta e dois, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«3. Do not combine methods. You can run all three; Google says there’s no benefit, and every extra method is another surface for the three copies to disagree with each other.
Evidência desta afirmação Google requires fully qualified alternate URLs and reciprocal links, and recommends including each page itself in its alternate set. Escopo: Google Search hreflang rules shared by all delivery methods. Confiança: alta · Verificado: Google: Hreflang guidelines» (Tradução) (Síntese localizada do trecho trinta e três, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Method 1 — HTML <link> tags in the <head>
» (Tradução) (Síntese localizada do trecho trinta e quatro, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«The syntax, verbatim from Google, is: » (Tradução) (Síntese localizada do trecho trinta e cinco, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
<link rel="alternate" hreflang="lang_code" href="url_of_page" />«A full working set for a multi-language, multi-region cluster with a fallback: » (Tradução) (Síntese localizada do trecho trinta e sete, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
<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/" />«That exact block goes on every page in the cluster (the US page, the UK page, the German page, and the homepage) — each one includes its own self-referencing line. That’s what satisfies reciprocity. » (Tradução) (Síntese localizada do trecho trinta e nove, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Placement is a hard rule. Google: “The <link> tags must be inside a
well-formed <head> section of the HTML.” And their own troubleshooting advice:
“If in doubt, paste code from your rendered page into an HTML validator to ensure
that the links are inside the <head> element.”
» (Tradução) (Síntese localizada do trecho quarenta, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«This matters more than it sounds, because of a failure mode most written guides
skip: hreflang tags can be forced out of the <head> and into the <body>,
where they’re invalid. In my Pubcon Vegas 2019 deck
I flagged this directly — tags can’t legitimately live in the body (that would let
one site hijack another’s alternates), but a malformed or injected <p> tag, or an
iframe, can prematurely close the <head> so that everything after it — including
your hreflang — renders inside the <body>. The tag is technically present in
source but silently invalid. The fastest way to debug it is browser DOM
breakpoints: watch where the tags actually land in the rendered DOM, then walk
back to the markup that broke the <head>.
» (Tradução) (Síntese localizada do trecho quarenta e um, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«When HTML tags make sense: small-to-medium sites with a manageable number of
locales, where the per-page <link> block doesn’t balloon. On a site with dozens
of locales, every page carries a large block of markup — which is one reason big
sites lean on the sitemap method.
» (Tradução) (Síntese localizada do trecho quarenta e dois, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Don’t mix hreflang with other alternate attributes on the same
<link> element. Google’s guidance is explicit that a <link rel="alternate">
carrying hreflang shouldn’t also carry an unrelated alternate attribute like
media in the same tag — if you need both a language/region alternate and a
media-query alternate for the same URL, that’s two separate <link> elements,
not one combined one. Mixing them is an easy way to end up with a tag Google
can’t parse as either.
» (Tradução) (Síntese localizada do trecho quarenta e três, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Method 2 — HTTP Link: headers
» (Tradução) (Síntese localizada do trecho quarenta e quatro, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Same information, sent in the HTTP response instead of the HTML. The syntax: » (Tradução) (Síntese localizada do trecho quarenta e cinco, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
Link: <https://example.com/file.pdf>; rel="alternate"; hreflang="en",
<https://de-ch.example.com/file.pdf>; rel="alternate"; hreflang="de-ch"«Note the angle brackets around each URL, the semicolon-separated attributes, and the comma separating each alternate. Every URL in the header is comma-appended. » (Tradução) (Síntese localizada do trecho quarenta e sete, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«When you need this: non-HTML resources. A PDF, a .doc, an image served
directly — none of them have a <head> to hold <link> tags, so the header is
your only way to attach hreflang to them.
» (Tradução) (Síntese localizada do trecho quarenta e oito, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Configuration considerations: you set these headers at the server or CDN layer
(an Apache Header directive, an Nginx add_header, a Cloudflare/Fastly/CloudFront
response-header rule, or your application’s response). Because the header is set by
infrastructure rather than per-document markup, the reciprocity rule is easy to
break here — the English PDF’s header and the German PDF’s header are usually
configured separately, so it’s on you to make sure each one lists the whole set,
itself included. Keep the header generation driven by the same locale table as your
HTML/sitemap approach.
» (Tradução) (Síntese localizada do trecho quarenta e nove, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«The invariant to hold onto: every alternate response carries the identical complete set, every time. It’s not enough for the English PDF’s header to list the German alternate — the German PDF’s response has to carry the exact same set back (itself plus every other alternate), on every single response, not just the first one a crawler happens to hit. Treat the header as generated output, not a one-off you set and forget. » (Tradução) (Síntese localizada do trecho cinquenta, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Method 3 — XML sitemap <xhtml:link> annotations
» (Tradução) (Síntese localizada do trecho cinquenta e um, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«At scale, this is usually the right call: the whole cluster lives in one (or a few)
machine-generated files, nothing bloats each page’s <head>, and — because the
entire relationship graph is in one place — it’s by far the easiest method to QA.
The syntax:
» (Tradução) (Síntese localizada do trecho cinquenta e dois, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
<?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 things that trip people up in the sitemap method: » (Tradução) (Síntese localizada do trecho cinquenta e quatro, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«1. The namespace declaration is mandatory. That
xmlns:xhtml="http://www.w3.org/1999/xhtml" on the <urlset> element is not
optional decoration — omit it and every <xhtml:link> in the file is invalid.
2. Every <url> block must be self-complete. Notice that both <url> blocks
above list both alternates, including their own <loc>. Each <url> entry
carries the full set (self-reference + all alternates). Reciprocity in a sitemap
is just “every URL’s block lists every URL in the cluster, itself included.”
» (Tradução) (Síntese localizada do trecho cinquenta e cinco, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Two behaviors worth knowing so you don’t over-engineer the generator: the order
of the <xhtml:link> children inside a <url> block doesn’t matter to Google —
don’t waste time sorting them — and those <xhtml:link> annotations don’t count
against your sitemap’s 50,000-URL-per-file limit, since they’re children of a
<url> entry, not separate <url> entries themselves.
» (Tradução) (Síntese localizada do trecho cinquenta e seis, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Generating it programmatically. The whole point of the sitemap method is that
it’s a byproduct of your CMS’s own translation data. If your CMS already knows
that /english/page.html and /deutsch/page.html are translations of each other,
your sitemap generator should walk that relationship table and emit the
<xhtml:link> blocks at build time (or at sitemap-request time). Do that and
hreflang can’t drift out of sync with reality — it’s regenerated from the source of
truth every time, and adding a locale is a data change, not a hand-edit across
hundreds of pages.
» (Tradução) (Síntese localizada do trecho cinquenta e sete, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«For teams without dev resources, I built a lightweight Google Sheets template in my Ahrefs hreflang guide: a Setup tab (pick a default language plus up to four variants), a URLs tab (paste each language’s URLs into columns), and a Results tab that auto-generates the sitemap XML block for you. It’s the “single source of truth” idea made concrete for sites too small to justify a real CMS integration. » (Tradução) (Síntese localizada do trecho cinquenta e oito, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## The rules that apply no matter which method you pick » (Tradução) (Síntese localizada do trecho cinquenta e nove, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«These are method-agnostic and non-negotiable. » (Tradução) (Síntese localizada do trecho sessenta, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«- Self-reference. Every page (or every <url> block, or every header) lists
itself. Mueller frames this as optional-but-good-practice, but skipping it was
present in 18.0% of the domains in my study — automate it and it costs nothing.
- Reciprocity. “Each language version must list itself as well as all other language versions.” And the enforcement: “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.” One missing return link drops the pair.
- Absolute, fully-qualified URLs. “Alternate URLs must be fully-qualified,
including the transport method (http/https)” — so
https://example.com/foo, never//example.com/fooor/foo. And the URL must match the exact form Google indexes: protocol,www, trailing slash, and case all have to line up, or the return-link match fails. » (Tradução) (Síntese localizada do trecho sessenta e um, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Getting the codes right » (Tradução) (Síntese localizada do trecho sessenta e dois, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«“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).” Combine them with a dash: en-US. You can target a
language on its own (es = Spanish everywhere), but you cannot target a region
on its own — there’s always a language first.
» (Tradução) (Síntese localizada do trecho sessenta e três, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«The mistakes I see most often (and saw across the study dataset): » (Tradução) (Síntese localizada do trecho sessenta e quatro, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«- en-UK instead of en-GB — uk is Ukrainian, the UK’s region code is gb.
jpinstead ofjafor Japanese,cninstead ofzhfor Chinese.- Three-letter codes (
ger,eng) where two-letter ISO 639-1 is required. - Using
EU,UN, orUKas region codes — none are valid ISO 3166-1 alpha-2 targets. » (Tradução) (Síntese localizada do trecho sessenta e cinco, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«x-default is the reserved value for the fallback — a language selector or an
auto-redirecting home page that serves users who match none of your explicit
locales:
» (Tradução) (Síntese localizada do trecho sessenta e sete, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
<link rel="alternate" href="https://example.com/" hreflang="x-default" />«It’s not mandatory. It was the single most-missing element in my study (56.3% of
domains omitted it), but a missing x-default doesn’t break the cluster the way a
missing reciprocal tag does — Google just falls back to its own language/region
detection for unmatched users. Add it anyway; it’s a checklist item, not a
cluster-breaker. (There’s a dedicated x-default subtopic in this cluster.)
» (Tradução) (Síntese localizada do trecho sessenta e nove, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Implementing at scale — CMS and platform approaches » (Tradução) (Síntese localizada do trecho setenta, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«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.)
» (Tradução) (Síntese localizada do trecho setenta e um, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Shopify. Shopify Markets automatically generates mutually-linked hreflang
tags once you’ve configured markets/languages and the content is published and
linked in navigation — which removes the most common failure mode (missing
reciprocal links) by design. The catch: Markets’ automatic tags are often
language-only (fr, de) rather than language-region (fr-FR, fr-CA), which
under-serves brands that need regional specificity — French for France vs. Canada
vs. Belgium. For that you drop to manual <link> tags in theme.liquid (Shopify’s
own theme hreflang docs
show the pattern) or an app — and be careful, because mixing automatic Markets
tags with manual/app tags is a documented source of conflicts. Pick one.
» (Tradução) (Síntese localizada do trecho setenta e dois, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Custom / headless / enterprise. Generate the annotations from your translation-relationship table at build or serve time, as described in the sitemap section above. This is the same “single source of truth” principle — hreflang becomes a computed output of data your CMS already holds, not a hand-maintained artifact that can rot. » (Tradução) (Síntese localizada do trecho setenta e três, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Implementation mistakes that break the cluster » (Tradução) (Síntese localizada do trecho setenta e quatro, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Auto-redirecting by geo/IP. This is a separate failure from syntax errors and it’s worse. If you redirect visitors — and especially crawlers — to a version based on perceived location, you can de-index entire regional clusters, because Googlebot mostly crawls from the US. As I put it in that Pubcon deck: a geo-redirect “would redirect search engines to where they crawl from. Google for instance mostly crawls from the US so we would effectively de-index all geo pages.” There’s a regulatory angle too — potential exposure under EU anti-geoblocking rules. The right pattern is redirect users, never crawlers: detect and (optionally) redirect human visitors, but always let bots reach every URL variant directly, with hreflang doing the actual routing signal. Google’s own multi-regional guidance recommends a non-intrusive suggestion banner over automatic redirection for exactly this reason. » (Tradução) (Síntese localizada do trecho setenta e cinco, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Pointing hreflang at non-canonical, redirected, or noindexed URLs. If a locale’s
URL changes and the redirect goes in but the hreflang still points at the old URL,
your cluster now references a 301 or a 404 (16.9% of domains in my study
referenced broken/redirected pages). Similarly, each variant should canonicalize to
itself; pointing hreflang at a URL that’s canonicalized away, or at a noindexed
page, breaks the return link (8.0% pointed at non-canonical URLs).
» (Tradução) (Síntese localizada do trecho setenta e seis, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Inconsistent URL formats. The hreflang URL and the indexed URL have to be
byte-identical in form — trailing slash, www, protocol, and case all included. A
mismatch here is a silent reciprocity failure.
» (Tradução) (Síntese localizada do trecho setenta e sete, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Validating your implementation after launch » (Tradução) (Síntese localizada do trecho setenta e oito, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«View rendered source, not just raw source. If your hreflang is injected by
client-side JavaScript, curl or Ctrl+U (“View Page Source”) will show nothing —
but the tags exist in the rendered DOM. Confirm with GSC URL Inspection → “Test Live
URL” → “View Tested Page,” or a rendering-capable crawler. This is the single most
common reason someone says “my tags are missing” when they’re actually fine (or the
reverse — present in source but broken because they render in the <body>).
» (Tradução) (Síntese localizada do trecho setenta e nove, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Crawl the whole cluster, don’t spot-check one URL. Reciprocity is a relationship between pages, so checking one page tells you almost nothing. Run a crawler across the whole cluster — Screaming Frog’s hreflang audit or Ahrefs Site Audit — to catch missing return tags, non-canonical targets, and broken references at scale. Ahrefs Site Audit’s Hreflangs tab draws the cluster as a graph with broken links in red, which is far easier to reason about than a CSV. » (Tradução) (Síntese localizada do trecho oitenta, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Verify real SERPs with &hl= and &gl=. Append the host-language (&hl=) and
geolocation (&gl=) parameters to a Google search URL to preview what a given
locale’s results actually look like, rather than guessing from your own location.
» (Tradução) (Síntese localizada do trecho oitenta e um, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Validation is not a one-time step. New locales, URL/redirect changes, and dev/staging config bleeding into production are the recurring causes of post-launch breakage. Build hreflang checks into regression tests and recurring crawls, not just a launch-day QA pass. My framing from the talks: “any number of things can break from masking to things carrying over from dev/test/staging environments.” » (Tradução) (Síntese localizada do trecho oitenta e dois, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Myths worth retiring » (Tradução) (Síntese localizada do trecho oitenta e três, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«- “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.
- “Yandex doesn’t support hreflang in sitemaps.” False — Yandex’s own documentation confirms sitemap hreflang support.
- “Use all three methods for extra signal.” No benefit per Google, and it just multiplies inconsistency risk.
- “A missing
x-defaultbreaks the cluster.” False — it’s optional; Google falls back to its own detection. - “Wrong hreflang gets you penalized.” False — it’s a hint, not a directive. Broken hreflang is ignored, not penalized. » (Tradução) (Síntese localizada do trecho oitenta e quatro, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Where to go next » (Tradução) (Síntese localizada do trecho oitenta e cinco, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«This article is the how-to depth under the hreflang hub — the hub covers what hreflang is, why reciprocity matters, and what Bing does instead. The x-default subtopic goes deep on the fallback value. For the strategy this implements, see the International SEO pillar — hreflang is the technical layer, not a substitute for genuine localization. » (Tradução) (Síntese localizada do trecho oitenta e seis, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## AI summary » (Tradução) (Síntese localizada do trecho oitenta e nove, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«A condensed take on the Advanced version: » (Tradução) (Síntese localizada do trecho noventa, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«- Three methods, pick exactly one (Google treats them as equivalent; no benefit to combining):
- HTML
<link>tags in the<head>— small/medium sites; must be in a well-formed<head>, never the<body>; don’t mixhreflangwith another alternate attribute likemediaon the same<link>element. - HTTP
Link:headers — the only option for non-HTML files (PDFs); set at server/CDN; every alternate response must carry the identical complete set, every time. - XML sitemap
<xhtml:link>— best at scale; needs thexmlns:xhtml="http://www.w3.org/1999/xhtml"namespace on<urlset>; easiest to QA because the whole graph is in one file; child order doesn’t matter and these children don’t count toward the 50,000-URL sitemap limit. - Two universal rules: self-reference (each page lists itself) and reciprocity (A→B requires B→A, or the pair is ignored). Use absolute, fully-qualified URLs that match the exact indexed form.
- Codes: ISO 639-1 language + optional ISO 3166-1 alpha-2 region (
en-GB, noten-UK;ja, notjp).x-defaultis the reserved fallback — optional but the most-missed element (56.3% in my study). - Automate from one source of truth. WordPress needs WPML/Polylang (Yoast alone does nothing); Shopify Markets auto-generates reciprocal tags but often language-only; custom/headless should emit hreflang from the translation table.
- Don’t auto-redirect crawlers by geo — Googlebot crawls mostly from the US, so » (Tradução) (Síntese localizada do trecho noventa e um, parte um: o texto-fonte foi preservado para conferência na revisão nativa.) « it can de-index regional clusters; redirect users, never bots.
- Validate the rendered head, not just view-source (JS-injected tags won’t show
in source); crawl the whole cluster for reciprocity; check locales with
&hl=/&gl=; re-check after every URL change. » (Tradução) (Síntese localizada do trecho noventa e um, parte dois: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Official documentation » (Tradução) (Síntese localizada do trecho noventa e quatro, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Primary-source documentation for implementing hreflang. » (Tradução) (Síntese localizada do trecho noventa e cinco, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
- Localized versions of your pages — the primary implementation doc: all three methods with exact syntax, the reciprocity requirement, valid codes, the absolute-URL rule, and
x-default. - Managing multi-regional and multilingual sites — URL-structure options and the auto-redirect / cloaking warning (why you must not geo-redirect crawlers).
- Tell Google about localized versions (x-default blog, 2013) — the original introduction of
x-default. - International Targeting report deprecation (Sept 2022) — the old report is gone; hreflang tags still work. » (Tradução) (Síntese localizada do trecho noventa e seis, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Bing / Microsoft
- Bing Webmaster Guidelines — Bing’s guidance; note Bing leans on
content-languageand<html lang>over hreflang. - Bingbot Series: Maximizing Crawl Efficiency — context on how Bing handles international/multilingual sites. » (Tradução) (Síntese localizada do trecho noventa e sete, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«CMS / platform
- WPML — Using WordPress SEO (Yoast) with WPML — how WPML outputs hreflang (head vs. sitemap setting).
- Shopify — Add hreflang tags in your theme — the manual
theme.liquid<link>pattern. » (Tradução) (Síntese localizada do trecho noventa e oito, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Quotes from the source » (Tradução) (Síntese localizada do trecho cento e um, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«On-the-record statements relevant to implementation. Each Google-docs link is a deep link that jumps to the quoted passage on the live page. » (Tradução) (Síntese localizada do trecho cento e dois, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Google — the three methods » (Tradução) (Síntese localizada do trecho cento e três, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«- “The three methods are equivalent from Google’s perspective and you can choose the method that’s the most convenient for your site.” — Google Search Central docs. Jump to quote » (Tradução) (Síntese localizada do trecho cento e quatro, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Google — placement » (Tradução) (Síntese localizada do trecho cento e cinco, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«- “The <link> tags must be inside a well-formed <head> section of the HTML.”
— Google Search Central docs.
Jump to quote
» (Tradução) (Síntese localizada do trecho cento e seis, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Google — the two rules » (Tradução) (Síntese localizada do trecho cento e sete, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«- “Each language version must list itself as well as all other language versions.” — Google Search Central docs. Jump to quote
- “If two pages don’t both point to each other, the tags will be ignored.” — Google Search Central docs. Jump to quote
- “Alternate URLs must be fully-qualified, including the transport method (http/https).” — Google Search Central docs. Jump to quote » (Tradução) (Síntese localizada do trecho cento e oito, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Google — codes » (Tradução) (Síntese localizada do trecho cento e nove, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«- “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).” — Google Search Central docs. Jump to quote » (Tradução) (Síntese localizada do trecho cento e dez, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«John Mueller, Google — it’s a hint, not a directive » (Tradução) (Síntese localizada do trecho cento e onze, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«- On self-referential tags: hreflang self-references are reported as optional but good practice. — John Mueller, Google, relayed via my Ahrefs hreflang guide.
- On correctness not guaranteeing outcome (May 2025, Bluesky): Mueller noted that hreflang doesn’t guarantee indexing, so a variant may simply not be indexed, and that same-language variants (like
fr-frandfr-be) are commonly consolidated. — relayed via Search Engine Journal coverage. » (Tradução) (Síntese localizada do trecho cento e doze, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Note: the two Google-docs quote sets deep-link to the live documentation and were re-verified verbatim against it. The Mueller Bluesky and self-reference remarks are relayed via secondary coverage (SEJ, Ahrefs) rather than re-verified against the original posts, so they’re paraphrased here rather than quoted. » (Tradução) (Síntese localizada do trecho cento e treze, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Which implementation method should I use? » (Tradução) (Síntese localizada do trecho cento e dezesseis, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Work top to bottom and stop at the first match. » (Tradução) (Síntese localizada do trecho cento e dezessete, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«1. Are the pages non-HTML files (PDFs, docs, images served directly)?
→ Yes → HTTP Link: headers. They have no <head>, so this is your only
option. Set the header at the server/CDN, listing the whole set on each file.
→ No → continue.
» (Tradução) (Síntese localizada do trecho cento e dezoito, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«2. Do you have more than a handful of locales, an existing sitemap pipeline, or a
headless/JAMstack build?
→ Yes → XML sitemap <xhtml:link>. Generate it programmatically from your
translation table. One machine-generated file, no per-page markup, easiest to QA.
→ No → continue.
» (Tradução) (Síntese localizada do trecho cento e dezenove, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«3. Small/simple site, few locales, and you’d rather keep everything visible on the
page?
→ HTML <link> tags in the <head>. Just make sure the block is generated from
one source of truth and lands inside a well-formed <head>.
» (Tradução) (Síntese localizada do trecho cento e vinte, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Whatever you pick: use it alone. Google says there’s no benefit to combining methods, and every extra copy is a place for the three to disagree. » (Tradução) (Síntese localizada do trecho cento e vinte e um, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Do I need x-default?
» (Tradução) (Síntese localizada do trecho cento e vinte e dois, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Do you have a page that serves users who match none of your explicit locales — a
country/language selector, or a global homepage?
→ Yes → add x-default pointing at that fallback page.
→ No → you can skip it. It’s optional; Google falls back to its own detection. It
won’t break the cluster (unlike a missing reciprocal tag). Adding it is still good
practice — it was the single most-missed element in my study (56.3%).
» (Tradução) (Síntese localizada do trecho cento e vinte e três, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Should I auto-redirect users by location? » (Tradução) (Síntese localizada do trecho cento e vinte e quatro, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Are you thinking about redirecting based on IP/geo? → Redirect human visitors only, and prefer a non-intrusive banner over a hard redirect. → Never redirect crawlers by geo. Googlebot mostly crawls from the US, so a crawler geo-redirect can de-index your other regional versions — and it risks cloaking classification and EU anti-geoblocking exposure. Let bots reach every URL variant directly; hreflang does the routing signal. » (Tradução) (Síntese localizada do trecho cento e vinte e cinco, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Which CMS path applies to me? » (Tradução) (Síntese localizada do trecho cento e vinte e seis, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«- WordPress? → Yoast alone does nothing. Install WPML or Polylang; they emit hreflang (choose head vs. sitemap output in WPML’s SEO settings).
- Shopify? → Markets auto-generates reciprocal tags — but often language-only.
Need
fr-FRvsfr-CA? Add manualtheme.liquidtags or an app, and don’t mix the two (conflict risk). - Custom / headless? → Emit
<xhtml:link>(or head tags) from your translation-relationship table at build/serve time. » (Tradução) (Síntese localizada do trecho cento e vinte e sete, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## SOP: Ship a hreflang cluster from scratch » (Tradução) (Síntese localizada do trecho cento e trinta, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«A repeatable procedure for adding a new hreflang cluster (or a new locale to an existing one). Run it top to bottom. » (Tradução) (Síntese localizada do trecho cento e trinta e um, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«1. Build the locale matrix (single source of truth).
List every URL and its language-region code in one place — a database table, a CMS
translation field, or a spreadsheet. Confirm every URL is the canonical, indexed
form (right protocol, www, trailing slash, case). This table is the input to
everything below; nothing gets hand-typed downstream.
» (Tradução) (Síntese localizada do trecho cento e trinta e dois, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«2. Pick one method using the Decision Trees lens. Do not combine methods. » (Tradução) (Síntese localizada do trecho cento e trinta e três, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«3. Generate the annotations from the matrix.
- HTML: emit the
<link>block into each page’s<head>from the matrix. - Sitemap: emit each
<url>block with thexmlns:xhtmlnamespace on<urlset>. - Headers: emit the
Link:header from the matrix at the server/CDN. » (Tradução) (Síntese localizada do trecho cento e trinta e quatro, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«4. Verify the two rules programmatically before publishing. Every entry must (a) include a self-reference and (b) list every other entry in the cluster. Confirm reciprocity: for each A→B, there’s a matching B→A. » (Tradução) (Síntese localizada do trecho cento e trinta e cinco, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«5. Add x-default if you have a selector or global fallback page.
» (Tradução) (Síntese localizada do trecho cento e trinta e seis, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«6. Publish, then validate the rendered output (see the Playbooks lens for the
detailed validation runbook): rendered head (not view-source), a full-cluster crawl
for reciprocity, and a &hl=/&gl= SERP spot-check.
» (Tradução) (Síntese localizada do trecho cento e trinta e sete, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«7. Wire it into ongoing checks. Add a recurring crawl / regression test so a future URL change or new locale can’t silently rot a return tag. Validation is not a one-time task. » (Tradução) (Síntese localizada do trecho cento e trinta e oito, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«When adding a locale later: you only edit the matrix (step 1) and re-run steps 3–6. If you’re hand-editing individual pages to add a locale, your source of truth is wrong — fix that first. » (Tradução) (Síntese localizada do trecho cento e trinta e nove, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Playbook: “My hreflang isn’t working” — validation runbook » (Tradução) (Síntese localizada do trecho cento e quarenta e dois, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Run these in order. Each step either finds the break or clears a suspect. » (Tradução) (Síntese localizada do trecho cento e quarenta e três, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Step 1 — Confirm the tags actually render. Open the page and view the rendered DOM (GSC URL Inspection → Test Live URL → View Tested Page, or a rendering crawler). Do not rely on Ctrl+U “View Page Source” — if hreflang is JS-injected it won’t appear there even though it’s live.
- Tags present in rendered head → go to Step 3.
- Tags missing from rendered head → Step 2. » (Tradução) (Síntese localizada do trecho cento e quarenta e quatro, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Step 2 — Are the tags in the <head> or the <body>?
If the tags exist in source but sit inside <body>, they’re invalid. A malformed or
injected <p> tag or an iframe likely closed the <head> early. Use browser DOM
breakpoints to find where the <head> breaks, fix that markup, re-check.
» (Tradução) (Síntese localizada do trecho cento e quarenta e cinco, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Step 3 — Check the URLs are absolute and canonical.
Every href must be fully-qualified (https://…) and byte-identical to the indexed
form (protocol, www, trailing slash, case). Confirm none point at a 301, 404,
noindexed, or canonicalized-away URL.
» (Tradução) (Síntese localizada do trecho cento e quarenta e seis, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Step 4 — Check reciprocity across the whole cluster. Crawl the entire cluster (Screaming Frog / Ahrefs Site Audit). For every A→B, verify a matching B→A exists, and that each page self-references. This is where most breaks live — a single missing return tag drops the pair. » (Tradução) (Síntese localizada do trecho cento e quarenta e sete, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Step 5 — Validate the codes.
Confirm ISO 639-1 language + ISO 3166-1 alpha-2 region. Look specifically for
en-UK (→ en-GB), jp (→ ja), three-letter codes, and region-only codes.
» (Tradução) (Síntese localizada do trecho cento e quarenta e oito, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Step 6 — Rule out geo-redirects. Confirm crawlers aren’t being geo-redirected. If Googlebot (crawling from the US) gets bounced to your US version, your other regional URLs may never be reached. » (Tradução) (Síntese localizada do trecho cento e quarenta e nove, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Step 7 — Reset expectations if the cluster is technically correct.
If everything above checks out and same-language variants (e.g. fr-fr / fr-be)
are still consolidated in reporting, that’s expected — Google can consolidate
near-identical same-language variants regardless of implementation. It’s a hint, not
a directive; wrong or ignored hreflang is not a penalty. Stop chasing it as a bug.
» (Tradução) (Síntese localizada do trecho cento e cinquenta, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Implementation anti-patterns » (Tradução) (Síntese localizada do trecho cento e cinquenta e três, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Concrete mistakes, why they’re wrong, and what to do instead. » (Tradução) (Síntese localizada do trecho cento e cinquenta e quatro, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«1. Hand-maintaining hreflang per page. Why it’s wrong: the moment one template or locale drifts, return tags go missing and pairs get dropped — reciprocity rot at scale. Do instead: generate every annotation from one source of truth (translation table, CMS field, or the Sheets template for small sites), so the whole cluster is regenerated, not edited. » (Tradução) (Síntese localizada do trecho cento e cinquenta e cinco, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«2. Using all three methods for “extra signal.” Why it’s wrong: Google says there’s no benefit, and three copies of the truth means three chances for them to disagree. Do instead: pick one method and use it alone. » (Tradução) (Síntese localizada do trecho cento e cinquenta e seis, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«3. Auto-redirecting crawlers by geo/IP. Why it’s wrong: Googlebot crawls mostly from the US, so a crawler geo-redirect can de-index your other regional clusters entirely — plus cloaking and EU anti-geoblocking exposure. Do instead: redirect (or better, banner-prompt) users only; never crawlers. Let bots reach every URL directly and let hreflang carry the signal. » (Tradução) (Síntese localizada do trecho cento e cinquenta e sete, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«4. Pointing hreflang at non-canonical, redirected, or noindexed URLs.
Why it’s wrong: the return link resolves to a 301/404/noindexed page, so the
pair breaks (16.9% referenced broken/redirected pages, 8.0% non-canonical in my
study).
Do instead: each variant canonicalizes to itself; hreflang points only at live,
canonical, indexable URLs — regenerated whenever URLs change.
» (Tradução) (Síntese localizada do trecho cento e cinquenta e oito, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«5. Relative or protocol-relative URLs.
Why it’s wrong: Google requires fully-qualified URLs; /foo and //example.com/foo
are invalid, and even absolute-but-mismatched forms (wrong slash/www/case) fail the
reciprocity match.
Do instead: always https://example.com/foo, matching the exact indexed form.
» (Tradução) (Síntese localizada do trecho cento e cinquenta e nove, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«6. Trusting “View Page Source” as validation.
Why it’s wrong: JS-injected hreflang doesn’t appear in raw source, so you either
think it’s missing (it isn’t) or miss that it renders in the <body> (invalid).
Do instead: validate the rendered DOM via GSC URL Inspection or a rendering
crawler.
» (Tradução) (Síntese localizada do trecho cento e sessenta, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«7. Wrong or invented locale codes.
Why it’s wrong: en-UK, jp, ger, and region-only codes are invalid and
ignored.
Do instead: ISO 639-1 language + optional ISO 3166-1 alpha-2 region — en-GB,
ja, de, es-MX.
» (Tradução) (Síntese localizada do trecho cento e sessenta e um, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Before / after » (Tradução) (Síntese localizada do trecho cento e sessenta e quatro, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«1. Missing reciprocal tag (the classic). Before: the US page lists US + UK + DE, but the German page’s template only lists DE + US — it forgot the UK return link. Google drops the DE↔UK pair. After: the German page’s block lists DE + US + UK (all self-referencing and reciprocal). Regenerated from the locale table so it can’t drift again. » (Tradução) (Síntese localizada do trecho cento e sessenta e cinco, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«2. Relative URLs.
Before: <link rel="alternate" hreflang="de" href="/de/" /> — relative, so it’s
invalid and ignored.
After: <link rel="alternate" hreflang="de" href="https://example.com/de/" /> —
fully-qualified and matching the indexed form.
» (Tradução) (Síntese localizada do trecho cento e sessenta e seis, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«3. Wrong UK code.
Before: <link rel="alternate" hreflang="en-uk" href="https://example.com/uk/" />
— uk is Ukrainian; the annotation is invalid.
After: <link rel="alternate" hreflang="en-gb" href="https://example.com/uk/" />.
» (Tradução) (Síntese localizada do trecho cento e sessenta e sete, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«4. Sitemap missing the namespace.
Before: a sitemap using <xhtml:link> entries but with a <urlset> that only
declares the base sitemaps namespace — every <xhtml:link> is invalid.
After: <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml"> — the xhtml namespace is declared, so
the annotations validate.
» (Tradução) (Síntese localizada do trecho cento e sessenta e oito, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Ready-to-copy AI prompts » (Tradução) (Síntese localizada do trecho cento e setenta e um, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Adapt the placeholders, then paste into your assistant of choice. Always validate the output against a real crawl — an LLM can generate plausible-but-wrong codes or miss a return link. » (Tradução) (Síntese localizada do trecho cento e setenta e dois, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Generate an HTML <head> block from a locale matrix
» (Tradução) (Síntese localizada do trecho cento e setenta e três, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
I have these language/region page variants:
- en-US: https://example.com/us/
- en-GB: https://example.com/uk/
- de: https://example.com/de/
- global fallback / selector: https://example.com/
For EACH page above, output the complete hreflang <link> block that belongs in its
<head>. Every block must (a) self-reference, (b) list all other variants, and
(c) include an x-default pointing at the fallback. Use fully-qualified https URLs
exactly as given. Validate the codes as ISO 639-1 language + ISO 3166-1 alpha-2
region and flag any that look wrong.«Convert the same matrix into an XML sitemap block » (Tradução) (Síntese localizada do trecho cento e setenta e quatro, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
Using the same variant list, output an XML sitemap that uses <xhtml:link> hreflang
annotations. Requirements: declare xmlns:xhtml="http://www.w3.org/1999/xhtml" on
<urlset>; give every <url> block a full self-referencing + all-alternates set; use
the exact URLs provided. Do not add any URL not in my list.«Audit a pasted cluster for reciprocity + code errors » (Tradução) (Síntese localizada do trecho cento e setenta e cinco, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
Here are the hreflang tags from each page in my cluster: [paste each page's URL and
its hreflang tags]. Check for: missing self-reference, missing reciprocal (A->B
without B->A), invalid ISO codes, relative/protocol-relative URLs, and any URL that
appears with inconsistent formatting (trailing slash / www / case). List each issue
with the exact page and tag it's on. Do not assume tags I didn't paste. «## Extraction, console, and generation snippets » (Tradução) (Síntese localizada do trecho cento e setenta e oito, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Practical one-liners for building and checking hreflang. Adjust URLs before running. » (Tradução) (Síntese localizada do trecho cento e setenta e nove, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Chrome DevTools Console — list the hreflang tags on the current page Paste into the Console (F12 → Console) on any page to see what the browser actually rendered — this reflects JS-injected tags that “View Source” misses: » (Tradução) (Síntese localizada do trecho cento e oitenta, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
[...document.querySelectorAll('link[rel="alternate"][hreflang]')]
.map(l => ({ hreflang: l.hreflang, href: l.href,
inHead: !!l.closest('head') }));«The inHead flag is the tell for the <head>-break bug: any tag showing
inHead: false is rendering in the <body> and is invalid.
» (Tradução) (Síntese localizada do trecho cento e oitenta, parte dois: o texto-fonte foi preservado para conferência na revisão nativa.)
«Bookmarklet — same check, one click Save as a bookmark with this URL, then click it on any page: » (Tradução) (Síntese localizada do trecho cento e oitenta e um, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
javascript:(()=>{const t=[...document.querySelectorAll('link[rel="alternate"][hreflang]')].map(l=>`${l.hreflang} ${l.href} ${l.closest('head')?'(head)':'(BODY - INVALID)'}`);alert(t.length?t.join('\n'):'No hreflang tags found');})();«XPath — select hreflang links inside the head (for a crawler / browser inspector) » (Tradução) (Síntese localizada do trecho cento e oitenta e dois, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
//head/link[@rel='alternate' and @hreflang]«If a crawler finds link[@hreflang] matches under //body instead, that’s the
head-break bug.
» (Tradução) (Síntese localizada do trecho cento e oitenta e dois, parte dois: o texto-fonte foi preservado para conferência na revisão nativa.)
«Regex — pull hreflang code + URL from raw HTML (quick grep, not a real parser) » (Tradução) (Síntese localizada do trecho cento e oitenta e três, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
<link[^>]*rel=["']alternate["'][^>]*hreflang=["']([^"']+)["'][^>]*href=["']([^"']+)["']«Capture group 1 is the code, group 2 is the URL. Use only for a fast sanity grep — parse real HTML with a DOM library, not regex. » (Tradução) (Síntese localizada do trecho cento e oitenta e três, parte dois: o texto-fonte foi preservado para conferência na revisão nativa.)
«curl — check for hreflang in HTTP Link: response headers (the PDF/non-HTML case)
» (Tradução) (Síntese localizada do trecho cento e oitenta e quatro, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
curl -sI https://example.com/file.pdf | grep -i '^link:'«Python — generate a self-consistent hreflang <head> block from a matrix
» (Tradução) (Síntese localizada do trecho cento e oitenta e cinco, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
variants = {
"en-us": "https://example.com/us/",
"en-gb": "https://example.com/uk/",
"de": "https://example.com/de/",
"x-default": "https://example.com/",
}
# Every page gets the SAME full block (self-reference + all alternates),
# which is exactly what satisfies reciprocity.
block = "\n".join(
f'<link rel="alternate" hreflang="{code}" href="{url}" />'
for code, url in variants.items()
)
print(block) «## Test yourself: Implementing hreflang » (Tradução) (Síntese localizada do trecho cento e oitenta e oito, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Five quick questions on building a hreflang cluster correctly. Pick an answer for each, then check. » (Tradução) (Síntese localizada do trecho cento e oitenta e nove, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Resources worth your time » (Tradução) (Síntese localizada do trecho cento e noventa e três, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«My related writing
- Hreflang: The Easy Guide for Beginners — my Ahrefs guide with all three methods, the nine common implementation issues and fixes, and the Google Sheets template for semi-automated hreflang generation at scale.
- Over 67% of Domains Using Hreflang Have Issues — my study of 374,756 domains, the largest ever run, and the source of the error-rate breakdown (missing x-default 56.3%, missing self-reference 18.0%, broken/redirected targets 16.9%, missing reciprocal 15.3%, non-canonical 8.0%, bad codes 4.6%). » (Tradução) (Síntese localizada do trecho cento e noventa e quatro, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«My speaking
- International SEO: The Weird Technical Parts — Pubcon Vegas 2019 — the richest implementation source: the
<head>-break bug (tags forced into<body>by iframes/malformed markup) and DOM-breakpoint debugging, why “sitemaps are faster” is a myth, the geo-redirect de-indexing risk, and the&hl=/&gl=SERP-check technique. - Hreflang Study and Interesting Issues — Brighton SEO 2023 — the deck behind the study, plus Google’s most-specific matching order (language+country → language → x-default) and the most common code mistakes across the dataset.
- You’re Going To Screw Up International SEO — Pubcon Vegas 2017 — the ecosystem of implementation chaos: tools reporting wrong info, content served from URLs that differ from what’s indexed, duplicate-page traps. » (Tradução) (Síntese localizada do trecho cento e noventa e cinco, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«From around the industry
- Google’s Localized versions of your pages — the primary implementation doc; the exact syntax for all three methods, the reciprocity/self-reference rules, valid codes, and the absolute-URL requirement. Read it in full before you build.
- Google’s Managing multi-regional and multilingual sites — URL-structure options and the auto-redirect / cloaking warning behind “redirect users, not crawlers.”
- WPML — Using WordPress SEO (Yoast) with WPML — how WordPress actually outputs hreflang (Yoast alone doesn’t), and the head-vs-sitemap output setting.
- Shopify — Add hreflang tags in your theme — the manual
theme.liquid<link>pattern for when Shopify Markets’ language-only tags aren’t specific enough. - Screaming Frog — How To Audit & Test Hreflang — the crawl-based workflow for confirming reciprocity across a whole cluster rather than spot-checking one URL. » (Tradução) (Síntese localizada do trecho cento e noventa e seis, parte um: o texto-fonte foi preservado para conferência na revisão nativa.) «- Google Reminds That Hreflang Tags Are Hints, Not Directives — Search Engine Journal, May 2025, on Mueller’s same-language-consolidation clarification (why a technically perfect cluster can still be consolidated).
- r/TechSEO — the community for debugging broken hreflang clusters. » (Tradução) (Síntese localizada do trecho cento e noventa e seis, parte dois: o texto-fonte foi preservado para conferência na revisão nativa.)
«## Prove the hreflang cluster actually shipped » (Tradução) (Síntese localizada do trecho cento e noventa e nove, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«Hreflang fails silently: the tags can be present, well-formed, and still ignored if the return leg is missing. “It’s in the code” is not the test — reciprocity across the whole cluster is. Run these after you deploy a language/region set. » (Tradução) (Síntese localizada do trecho duzentos, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«### Test 1 — Every pair returns the tag (reciprocity) » (Tradução) (Síntese localizada do trecho duzentos e um, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«- Test to run — Crawl the whole cluster with returntag (it checks that every page A points to actually points back at A), or run Screaming Frog’s hreflang report across the set.
- Expected result — 0 non-reciprocal pairs and every URL self-references. Zero errors, not “a few.”
- Failure interpretation — A one-way pair (A → B but B doesn’t → A) means Google drops that pair — the most common real-world failure, and invisible if you only spot-check one URL’s view-source.
- Monitoring window — Immediate for the rendered tags; the checker reads what’s live now.
- Rollback trigger — Any non-reciprocal pair, or a tag pointing at a URL that 301s or 404s — fix the source of truth and redeploy before waiting on Google. » (Tradução) (Síntese localizada do trecho duzentos e dois, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«### Test 2 — Google is processing it cleanly » (Tradução) (Síntese localizada do trecho duzentos e três, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
«- Test to run — Google retired the old International Targeting report in Search Console in September 2022, so don’t rely on it — check Page Indexing for each locale in the cluster, and confirm via URL Inspection on a sample of pages that the “Google-selected canonical” and indexing status line up with what you expect for that locale.
- Expected result — Each locale’s intended pages are indexed (not “Duplicate, Google chose different canonical” in a way that collapses distinct language versions into one), and URL Inspection shows the alternate you expect.
- Failure interpretation — Pages showing up as duplicates of a different locale’s canonical, or clustered/consolidated indexing, usually traces back to a broken return leg (re-check Test 1) rather than hreflang itself — hreflang is a hint, not a directive, so a technically perfect cluster can still be consolidated if Google judges the content near-duplicate.
- Monitoring window — 2–4 weeks — Search Console re-crawls and reports the cluster over time, not instantly.
- Rollback trigger — A locale’s pages consistently indexing under the wrong canonical, or the wrong regional URL surfacing for a query — re-audit reciprocity first; don’t assume the tags “aren’t working” when the return leg is the actual gap. » (Tradução) (Síntese localizada do trecho duzentos e quatro, parte um: o texto-fonte foi preservado para conferência na revisão nativa.)
Registro de alterações
Atualizado em 25 de jul. de 2026.
Resumo editorial e detalhes registrados da alteração.Detalhes da alteração
-
As notas detalhadas sobre as alterações estão disponíveis atualmente em inglês.
Não é possível fazer a comparação completa — nenhum instantâneo anterior foi arquivado para esta revisão.
Atualizado em 18 de jul. de 2026.
Resumo editorial e detalhes registrados da alteração.Detalhes da alteração
-
As notas detalhadas sobre as alterações estão disponíveis atualmente em inglês.
-
As notas detalhadas sobre as alterações estão disponíveis atualmente em inglês.
-
As notas detalhadas sobre as alterações estão disponíveis atualmente em inglês.
-
As notas detalhadas sobre as alterações estão disponíveis atualmente em inglês.
Não é possível fazer a comparação completa — nenhum instantâneo anterior foi arquivado para esta revisão.