A site with 40 pages in three languages doesn't need much hreflang discipline — you can eyeball the tags. A site with 4,000 pages in twelve languages, some machine-translated, some not, is where hreflang mistakes compound into invisible traffic loss: Google quietly ignores the annotations, indexes the wrong locale for a query, or serves the German page to French searchers. The failure mode is silent because broken hreflang doesn't throw errors — it just gets ignored, and nothing in your site's behavior tells you that happened.
Choosing a URL Structure Before Anything Else
Hreflang problems usually start upstream, in the URL structure decision. There are three real options, and the choice affects far more than SEO.
| Structure | Example | SEO signal strength | Operational cost | | --- | --- | --- | --- | | Subdirectories | example.com/fr/ | Consolidates domain authority across languages | Lowest — one deploy, one certificate, one DNS record | | Subdomains | fr.example.com | Treated as semi-distinct by search engines | Medium — separate hosting config, possible auth/cookie complications | | ccTLDs | example.fr | Strongest country signal | Highest — separate domains, registrations, and sometimes legal entities |
Subdirectories are the default recommendation for most SaaS and content sites: they keep backlink equity in one domain and are the simplest to maintain long term. ccTLDs make sense when the country signal itself has commercial value — payment processors, regulated industries, or genuinely separate country operations. Subdomains are the compromise nobody is fully happy with; only pick them if infrastructure constraints force it, such as needing to run app.fr.example.com on entirely different hosting than the English app.
Whatever you choose, the URL must be unique per language variant and stable — hreflang references URLs directly, so if the URL changes on redeploy without updating every page that references it, you get orphaned annotations pointing at 404s or redirects.
The Core Hreflang Rules That Actually Break Sites
Three mistakes account for most real-world hreflang failures.
Missing return tags (non-reciprocal annotations)
If /en/pricing declares hreflang="fr" pointing to /fr/tarification, then /fr/tarification must declare hreflang="en" pointing back to /en/pricing. Google's guidance is explicit that hreflang must be confirmed by a return link — a one-way reference is treated as unverified and dropped from processing. This is the single most common cause of "I added hreflang and nothing changed."
Missing or wrong x-default
x-default tells search engines which page to show when no other hreflang value matches the user's language/region. Skip it and users from unlisted locales land wherever crawl and ranking signals happen to point them, which is rarely the intended page.
<link rel="alternate" hreflang="en" href="https://example.com/en/pricing" />
<link rel="alternate" hreflang="fr" href="https://example.com/fr/tarification" />
<link rel="alternate" hreflang="de" href="https://example.com/de/preise" />
<link rel="alternate" hreflang="x-default" href="https://example.com/en/pricing" />
Self-referencing omission
Every page in a hreflang set must reference itself, including the x-default target. Developers often generate the annotation set from a template and accidentally exclude the current page from its own alternate list, which breaks the whole cluster's validity even though the other links look correct.
Sitemap-Based Hreflang vs. HTML Head Tags
For sites under a few hundred URLs, <link rel="alternate"> tags in the <head> are easy to reason about and debug in browser dev tools. Past that scale, sitemap-based hreflang is usually less error-prone because it's generated programmatically from one data source instead of templated per-page, where template drift between locales is common (someone adds a new language and forgets to update the shared head partial for one page type).
<url>
<loc>https://example.com/en/pricing</loc>
<xhtml:link rel="alternate" hreflang="fr" href="https://example.com/fr/tarification" />
<xhtml:link rel="alternate" hreflang="de" href="https://example.com/de/preise" />
<xhtml:link rel="alternate" hreflang="x-default" href="https://example.com/en/pricing" />
</url>
The decision point: if your CMS or framework generates URLs from a single locale-aware routing table, sitemap hreflang is straightforward because that table is also your source of truth for the sitemap. If locales are hand-maintained across separate repos or CMS instances, head tags are actually easier to audit because they live next to the content they describe, rather than in a separate generated file that can drift out of sync with what's actually deployed.
Whichever route you pick, run the generated sitemap through the Sitemap Generator to confirm the XML structure is valid before pushing to production — malformed hreflang XML can cause Search Console to reject the whole sitemap, not just the broken entries.
Language Codes vs. Region Codes
Hreflang uses ISO 639-1 language codes optionally combined with ISO 3166-1 Alpha-2 region codes, in the format language or language-region — never region-only. hreflang="fr-CA" (French, Canada) is valid; hreflang="CA" alone is not and will be ignored. A common mistake is targeting a country when the actual differentiation is language: if your French content is identical for France and Canada, use hreflang="fr" once rather than duplicating it as fr-FR and fr-CA pointing to the same URL, which adds maintenance surface with no targeting benefit.
Auditing an Existing Implementation
Before trusting a hreflang setup, check for these in order, since they're the ones that fail silently:
- Reciprocity — every referenced URL returns the referencing page in its own set.
- Canonical conflicts — a page's canonical tag should point to itself, not to another language version; a canonical pointing cross-language will cause the hreflang annotation to be ignored entirely.
- Redirect chains in hreflang targets — if
/fr/tarification301s somewhere, Google treats the hreflang reference to it as broken, not as "follow the redirect." - HTTP status consistency — all URLs in a set should return 200; a 404 or noindex page in the set invalidates its own annotation, not just that one link.
Search Console's International Targeting report (under Legacy tools, if still available on your property) surfaces reciprocity and status errors aggregated across the whole set, which is faster than spot-checking pages individually once you're past a few dozen URLs.
Once the structure and annotations are consistent, verify the rendered meta output per locale — including title and description localization — with the Meta Tags Generator so the hreflang-correct URL and the on-page metadata actually agree with each other.