Hreflang tags tell search engines which language and regional version of a page to show each user. They are HTML annotations — or XML sitemap entries, or HTTP headers — that connect equivalent pages across languages and countries so Google can rank the right version in the right market. Implemented correctly, hreflang tags stop the wrong-language page from appearing in search and prevent your own translations from competing against each other.
That last part is what most teams miss. Hreflang is not a growth lever. It is insurance on traffic you have already earned. Get it wrong and a German user lands on your English page, bounces, and Google quietly demotes the version that should have ranked. This guide is the implementation reference I hand to engineering teams before they ship a multi-region site.
What hreflang tags actually do
Hreflang is a signal, not a directive. Google’s own documentation is explicit on this point: the tags suggest which version to serve, and Google is free to override them. That single fact changes how you should think about the whole system. You are not commanding Google — you are giving it clean, consistent evidence and hoping it agrees.
The mechanism is reciprocity. A hreflang set is a cluster of pages that all point at each other as language or region alternatives. If your /en/ page names /de/ as its German equivalent, the /de/ page must name /en/ as its English equivalent in return. Break that reciprocity and the entire set collapses — Google discards annotations it cannot confirm from both sides.
Three rules sit at the core of every valid implementation:
- Return tags: every URL in the set links to every other URL, in both directions.
- Self-reference: every page includes a hreflang entry pointing at itself.
- Absolute URLs: every reference uses the full
https://URL, never a relative path.
Miss any one of these and the annotations fail silently. There is no error page, no warning at runtime — just a gradual loss of the right pages ranking in the right places.
When you need hreflang — and when you don’t
You need hreflang when you serve the same or similar content in more than one language, or target the same language across more than one country. A SaaS product with English, Spanish, and German versions needs it. A retailer running Spanish for Spain and Spanish for Mexico needs it. A single-language, single-country site does not — adding hreflang there creates maintenance risk with zero upside.
The decision that trips people up is language versus region. These are two different problems and they demand different code. If you only care about language, use a language subtag alone (es, de, fr). If you care about country — because pricing, shipping, or vocabulary differ — add a region subtag (es-es, es-mx). Deciding this early is part of any serious international SEO strategy, because reversing it later means rewriting every annotation on the site.
The three ways to implement hreflang tags
There are exactly three valid methods. They are functionally equivalent — Google treats them the same — so the choice is about maintenance, not ranking.
1. HTML link elements in the head
You place a <link rel="alternate" hreflang="x" href="..."> for every version, including the page itself, inside the <head> of every page:
<link rel="alternate" hreflang="en" href="https://example.com/en/pricing/" />
<link rel="alternate" hreflang="es" href="https://example.com/es/precios/" />
<link rel="alternate" hreflang="de" href="https://example.com/de/preise/" />
<link rel="alternate" hreflang="x-default" href="https://example.com/en/pricing/" />
This is the most common approach and the easiest to inspect. The downside is weight: a site in ten languages carries eleven link tags on every single page, which bloats the HTML and is painful to keep synchronised.
2. XML sitemap annotations
You declare the alternates inside your XML sitemap using the xhtml:link element. Each URL entry lists every language variant, including itself. This is my default recommendation for large or fast-changing sites — the annotations live in one place, they never bloat page HTML, and a single template generates them programmatically. It is far easier to audit one sitemap than ten thousand page heads.
3. HTTP headers
For non-HTML resources like PDFs, you send hreflang in the Link HTTP header. Few sites need this, but it is the only option when the content has no head to inject into.
Pick one method per URL and commit to it. Mixing HTML tags and sitemap entries for the same pages is a classic source of conflicting signals that Google flags and ignores.
Hreflang syntax: getting the codes right
Wrong language and region codes are the single most common hreflang mistake I see in technical SEO audits. The rules are simple, but the failure modes are specific.
- Language uses ISO 639-1:
en,es,de,pt,zh. Always lowercase. - Region uses ISO 3166-1 Alpha-2:
US,GB,MX,ES. Case is ignored, but the code must be valid. - Order is language first, then an optional region, separated by a hyphen:
en-gb,es-mx,pt-br.
The errors cluster around a handful of invalid codes. en-uk is wrong — the United Kingdom’s ISO country code is GB, so it must be en-gb. en-eu is wrong — the EU is not a country, and there is no valid region subtag for a continent. Using a country code alone, like hreflang="mx", is wrong because mx is not a language. Get the standard right at the source and most problems disappear.
The x-default value
x-default marks the fallback for users who match none of your specified versions. If a French speaker in Canada hits a set that only defines en, es, and de, x-default decides what they see. Point it at your language selector, your global homepage, or your primary international version. Google recommends including it on any site that redirects users by language or region.
A hreflang implementation checklist
Here is the exact sequence I run when implementing or auditing hreflang tags. Work through it in order.
- Map the matrix. List every language and region combination, and confirm each has a real, indexable URL.
- Choose one method — head tags, sitemap, or headers — and apply it consistently.
- Add self-references. Every page must reference itself in the set.
- Add return tags. Every page references every other page, both directions.
- Use absolute URLs. Full
https://paths, no relative or protocol-relative links. - Validate every code against ISO 639-1 and ISO 3166-1 Alpha-2.
- Add x-default pointing at your fallback page.
- Confirm canonical alignment. Each page must be self-canonical (see below).
- Point hreflang at indexable pages only — never at redirects, noindex pages, or 404s.
- Crawl and verify the full set before and after deploy.
Skip step four and step ten and you have built something that looks right in the code and does nothing in the SERP.
The most common hreflang errors — and how to fix them
In my experience auditing international sites, the same failures appear again and again. Here is how to spot and fix each one.
Missing return tags. Page A names Page B, but Page B does not name Page A. Fix: make every reference reciprocal, including self-references. This is the number-one cause of ignored annotations.
Invalid language or region codes. en-uk, en-eu, es-la, or a bare country code. Fix: validate against the ISO standards; UK becomes gb, and drop any invented region subtags.
Relative URLs. href="/de/" instead of the full URL. Fix: always use absolute https:// URLs.
Hreflang to non-canonical pages. The tag points at a URL that canonicalises elsewhere, so Google follows the canonical and drops the annotation. Fix: point hreflang only at self-canonical, indexable URLs.
Missing x-default. Not an error, but a missed opportunity on any site with geo redirects. Fix: add it pointing at your fallback.
Mixed methods. HTML tags and sitemap entries fighting for the same URLs. Fix: consolidate to one method.
When you inherit a site mid-migration, these tend to compound — which is exactly why a full site audit should map the hreflang cluster before anyone touches production.
Hreflang and canonical tags: the relationship that breaks sites
This is where I see the most damage. Hreflang and canonical tags interact, and the interaction is unforgiving. The rule is short: every page in a hreflang set must be canonical to itself.
The disaster pattern is canonicalising every language version to one master page — usually the English one. When you do that, you are telling Google the German page is a duplicate that should not be indexed, while the hreflang tags simultaneously claim it is a distinct, equal alternative. Google resolves the contradiction by trusting the canonical and discarding the hreflang. Your translated pages fall out of the index. I have watched sites lose entire non-English markets to this one mistake.
The fix is mechanical. The German page canonicalises to the German page. The Spanish page canonicalises to the Spanish page. Hreflang then connects those self-canonical pages as alternatives. Canonical says “this is the definitive version of this content”; hreflang says “and here are its equivalents in other languages.” They must never contradict each other. If you are unsure how these signals combine on your stack, this is a fast, high-value question to bring to an SEO consultant before launch rather than after.
How to monitor hreflang tags at scale
Google retired the International Targeting report in Search Console in 2022, which removed the one native tool that surfaced hreflang errors directly. As of 2026, monitoring is a third-party job. That is not a downgrade — the crawlers are more thorough than the old report ever was.
Screaming Frog, Ahrefs Site Audit, and Semrush Site Audit all crawl and validate hreflang clusters, checking for missing return tags, invalid codes, and non-canonical targets. Ahrefs’ crawl data has consistently shown hreflang errors ranking among the most frequent international SEO issues on large sites, which matches what I find in the field — the problem is rarely awareness, it is drift. A tag set that was perfect at launch decays as pages are added, moved, and retired without the matrix being updated.
Build the check into your process, not your memory:
- Run a scheduled crawl that validates the full hreflang set after every deploy.
- Alert on any page whose return tags become incomplete.
- Re-verify the matrix whenever a new market or URL is added.
Hreflang tags are not a set-and-forget artefact. They are a living cluster that has to stay reciprocal as the site changes, and the sites that keep their international rankings are the ones that treat monitoring as ongoing maintenance rather than a launch-day task.
Frequently Asked Questions
Do hreflang tags improve rankings? No. Hreflang tags do not boost rankings on their own. They control which language or region version of a page Google serves to a given user, which protects the traffic you already earn and prevents your translated pages from cannibalising each other in search results.
What is the x-default hreflang value? The x-default value marks the fallback page shown to users whose language or region does not match any of your specified versions. It is typically your language selector, global homepage, or main international version. Google recommends it whenever you run a geo or language redirect.
Do I need hreflang for the same language in different countries? Yes, if the content differs meaningfully or you want to target markets separately — for example, English for the US versus the UK, or Spanish for Spain versus Mexico. Use both a language and a region subtag, such as en-us and en-gb, so Google can distinguish the versions.
Can hreflang tags be in the XML sitemap instead of the HTML head? Yes. Sitemap hreflang annotations work exactly like head-level tags and are easier to maintain at scale because they live in one file. Pick one method and never mix HTML tags and sitemap entries for the same URLs, as conflicting signals cause errors.
Why is Google ignoring my hreflang tags? The most common cause is missing return tags — every page in a set must link back to all the others, including itself. Other causes include incorrect language or region codes, relative URLs, hreflang pointing to non-canonical pages, and conflicting canonical tags. Validate the full set with a crawler.