If you’ve ever opened Search Console and seen the warning “Your site has no hreflang tags” — or worse, the silent variant where Google just stops ranking your translated pages and you can’t figure out why — this guide is for you.
hreflang is one of those technical SEO topics that gets explained over and over but never quite clicks, because most explanations skip the parts that actually break in production. The four-line example works fine until you have 23 languages, regional variants, AMP pages, and a checkout flow that lives on a subdomain. Then everything quietly falls apart and your German traffic drops 40% in a quarter.
This guide covers the implementation that works in the real world. Not the textbook version. The version where Cloudflare caches your headers, Next.js generates pages on demand, and your CMS adds trailing slashes that don’t exist in your sitemap.
hreflang tells search engines which version of a page to show users in different languages or regions. It’s a relationship signal, not a ranking signal.
This distinction matters. Adding hreflang doesn’t make your French page rank higher in France. It tells Google: “this English page and this French page are equivalent translations of the same content. When someone searches in French from France, show them the French one.” Without it, Google might still rank your French page, but it might also serve your English page to French searchers — or worse, treat both as duplicate content and pick one to demote.
Three things hreflang does:
Three things hreflang does not do:
Here’s the version most guides show you. It’s correct, and it’s also missing the most important line:
<link rel="alternate" hreflang="en" href="https://example.com/" />
<link rel="alternate" hreflang="fr" href="https://example.com/fr/" />
<link rel="alternate" hreflang="de" href="https://example.com/de/" />
This snippet declares three language versions. It will partially work. The issue: every page that uses these tags must reference itself in the list. Otherwise Google treats the references as one-directional and may discard them.
The complete version on the English page looks like this:
<link rel="alternate" hreflang="en" href="https://example.com/" />
<link rel="alternate" hreflang="fr" href="https://example.com/fr/" />
<link rel="alternate" hreflang="de" href="https://example.com/de/" />
<link rel="alternate" hreflang="x-default" href="https://example.com/" />
Two things changed:
Now here’s the part that’s almost never explained correctly: the same logic applies to the French page and the German page. Each page must list every language version, including itself, and x-default. Not just the English source.
On the French page:
<link rel="alternate" hreflang="en" href="https://example.com/" />
<link rel="alternate" hreflang="fr" href="https://example.com/fr/" />
<link rel="alternate" hreflang="de" href="https://example.com/de/" />
<link rel="alternate" hreflang="x-default" href="https://example.com/" />
Identical to the English page. That’s the point. hreflang declarations must be reciprocal — every language version must reference every other language version. If page A points to page B, page B must point back to page A. Google calls these “return tags,” and they’re the single most-failed validation rule in international SEO.
hreflang codes follow the format
language or language-REGION. Languages use ISO 639-1 (two-letter, lowercase). Regions use ISO 3166-1 Alpha 2 (two-letter, uppercase). The most common confusions:
| Code | What it actually means | Common mistake |
|---|---|---|
en |
English (any region) | Using “en” when you mean en-US specifically |
en-US |
English for United States users | Writing en-us (lowercase region) — invalid |
en-GB |
English for United Kingdom | Writing en-UK — UK is not a valid country code |
zh-Hans |
Simplified Chinese (script-based) | Using zh-CN when you mean script, not region |
zh-Hant |
Traditional Chinese | Using zh-TW for all Traditional Chinese users |
pt-BR / pt-PT |
Brazilian / European Portuguese | Using just “pt” — Brazil and Portugal differ significantly |
es-419 |
Latin American Spanish (UN region code) | Using es-MX as a stand-in for all of LATAM |
x-default |
Fallback for unmatched languages | Omitting it; pointing it to a region-specific page |
UK is not a country code. This is the single most-frequent error I’ve seen in 10 years of audits. The ISO 3166-1 code for the United Kingdom is GB. Use
en-GB, not en-UK. Google ignores invalid codes silently — your tag exists, but it does nothing.
hreflang can be declared in three places. Each has trade-offs.
Tags placed in the <head> section of every page. Easy to debug, easy to inspect, supported by every CMS. The downside: every page must include every other language’s tag, which means a 50-page site in 10 languages requires 500 hreflang declarations to be generated and kept in sync.
Use this method if your site has fewer than ~10,000 pages or your CMS handles hreflang generation automatically.
hreflang can be sent as an HTTP Link header. This is the only way to declare hreflang for non-HTML resources like PDFs:
Link: <https://example.com/en/file.pdf>; rel="alternate"; hreflang="en",
<https://example.com/fr/file.pdf>; rel="alternate"; hreflang="fr"
Use HTTP headers when you have downloadable assets that exist in multiple languages — product manuals, regulatory documents, white papers.
For sites with hundreds of thousands of pages, declaring hreflang in <head> tags becomes unwieldy. Sitemap-based hreflang is more efficient and keeps your HTML lean:
<url>
<loc>https://example.com/</loc>
<xhtml:link rel="alternate" hreflang="en"
href="https://example.com/" />
<xhtml:link rel="alternate" hreflang="fr"
href="https://example.com/fr/" />
<xhtml:link rel="alternate" hreflang="x-default"
href="https://example.com/" />
</url>
Same reciprocity rules apply. Each URL entry in the sitemap must list every language version, including itself.
Don’t mix methods. Pick one approach per site and stick with it. Conflicting hreflang signals from <head> and sitemap is one of the most frustrating bugs to debug because Google’s behavior in this case is undocumented and inconsistent.

Common hreflang mistakes
The English page lists French and German versions, but doesn’t reference itself as the English version. Google ignores the entire hreflang cluster. Fix: every page must include a hreflang tag pointing to itself.
English page points to French page. French page doesn’t point back. Google sees this as broken and may discard the relationship. Fix: every reference must be mutual. The French page must list the English page as its English alternative.
Your English page declares the French version at
https://example.com/fr/ but that URL 301-redirects to https://example.com/fr/home/. Google follows the redirect, but the hreflang signal is weakened — and in some cases ignored entirely.
Fix: hreflang must point to the final canonical URL, not to a redirect chain. Audit with a crawler that flags non-200 hreflang targets.
Your French page has a canonical pointing to the English page (because someone copy-pasted the canonical tag). Google reads this as “the French page is just a duplicate of the English page” and the hreflang relationship gets ignored. Fix: every translated page must self-canonicalize. The French page’s canonical points to itself, not to the English original.
Some pages declare
hreflang="en", others declare hreflang="en-US". Google treats these as separate language clusters. Pick one strategy per language and stick with it across the entire site.
You have an English-Canadian variant of your page but no global English version. Don’t use
hreflang="en" alone — Google may serve your Canadian page to UK users, which probably isn’t what you want. Instead, declare
hreflang="en-CA" specifically and let x-default handle non-Canadian English speakers.
US, UK, and Australian English versions of the same product page with identical text. This is fine — declare each region explicitly:
<link rel="alternate" hreflang="en-US" href="https://example.com/" />
<link rel="alternate" hreflang="en-GB" href="https://example.com/uk/" />
<link rel="alternate" hreflang="en-AU" href="https://example.com/au/" />
<link rel="alternate" hreflang="x-default" href="https://example.com/" />
Even when content is identical, regional hreflang variants are valuable for products with region-specific pricing, currency, or shipping.
If you have separate m. subdomain mobile pages, each mobile page needs its own hreflang declarations pointing to other mobile language variants. Don’t point a mobile French page to a desktop English page — Google considers this a broken cluster.
Both work for hreflang. fr.example.com and example.com/fr/ are equally valid. The choice is operational (DNS, hosting, analytics) — not an SEO factor by itself. What matters is consistency: pick one structure and apply it across all languages.
Page 2 of your French blog index should declare hreflang to page 2 of your English blog index, not to page 1. Map equivalent pages to equivalent pages, including pagination, query parameters, and filters.
If a translated version of a page doesn’t exist (yet), don’t declare hreflang for that language. Pointing hreflang to a 404 is worse than not declaring it at all — Google sees it as a broken relationship and may demote the entire cluster.
Three tools cover 95% of validation needs:
Run all three before any major launch. Search Console catches what Google sees. Screaming Frog catches what’s actually on your site. Merkle catches what you missed in code review.
If you’re using a website translation platform like ConveyThis, Weglot, or similar, hreflang generation should be automatic. The platform crawls your content, detects new pages, and inserts the correct hreflang tags on every translated version — including self-referencing tags, return tags, and x-default.
This is the strongest argument for using a translation platform over a manual translation pipeline. Manually maintaining hreflang across a 200-page site in 12 languages means tracking 31,200 tag relationships. Every new page adds 12 new relationships that must be added in 12 places. Manual maintenance breaks at scale.
If you’re using a platform and still seeing hreflang errors in Search Console, the cause is usually one of three things: a CDN caching layer that’s stripping headers, a CMS plugin that’s overwriting tags, or a redirect rule that’s interfering with the canonical structure. All three are fixable, but they require coordination between your translation platform, your hosting setup, and your CDN.
hreflang isn’t complicated. It’s verbose. The complexity comes from the volume of declarations and the fragility of any single missing tag. Get the foundations right — self-referencing, reciprocal, canonical-aligned, x-default present — and the rest is just maintenance.
Most international sites lose 20–40% of their potential foreign-language traffic to hreflang misconfigurations. Fix the basics and you’ll likely see meaningful traffic recovery in the language versions that were previously misranked or merged with the wrong original.
It’s the highest-leverage technical SEO fix in multilingual websites. Spend the afternoon.
Alex Buran, Founder of ConveyThis
Alex has spent the last decade building infrastructure for multilingual websites. He writes about localization, AI search, and the technical side of going global.
LinkedIn: linkedin.com/in/alexburan
Tired of debugging hreflang manually? ConveyThis generates valid, reciprocal, self-referencing hreflang tags on every translated page automatically — including x-default and edge cases. See the API documentation
Translation, far more than just knowing languages, is a complex process.
By following our tips and using ConveyThis, your translated pages will resonate with your audience, feeling native to the target language.
While it demands effort, the result is rewarding. If you’re translating a website, ConveyThis can save you hours with automated machine translation.
Try ConveyThis free for 3 days!