Hreflang tags tell search engines which language and region each version of a page targets. They're powerful, and the most error-prone area in technical SEO, because they demand strict reciprocity and accuracy. Here's every rule, and every way they break.
If you publish the same content for multiple languages or regions, hreflang ensures the right version reaches the right user, and stops your versions being treated as duplicates of each other.
You need hreflang when you have, say, Turkish and English versions of a page. Each version must annotate all the others, including itself, plus an x-default fallback. In the HTML head it looks like this, and the exact same set of tags must appear on every page in the group:
Done right, a Turkish searcher gets the Turkish page and an English searcher gets the English page, with no duplicate-content confusion. Done wrong, the wrong-language result ranks or your versions compete with each other. The difficulty is that hreflang only works when the whole cluster is consistent and reciprocal: every page references every other, with valid codes, pointing only at canonical 200 URLs.
Each rule below maps to a real hreflang check. Break one and the cluster can fail.
hreflang must be mutual: if A points to B, B must point back to A. A missing return tag is the most common hreflang error and can make search engines ignore the annotation. The audit flags missing reciprocal hreflang.
Every page must include an hreflang entry for itself. Without a self-reference, the cluster is incomplete. The audit flags pages missing a self-reference hreflang.
Use ISO 639-1 language codes (e.g. en, tr) and, where used, ISO 3166-1 region codes (e.g. en-GB, en-US). Invalid or made-up codes break the annotation. The audit flags invalid hreflang codes and language mismatches between the tag and the page's actual language.
Provide an x-default for the fallback when no version matches. Don't list multiple conflicting entries for the same language. And every hreflang target must be canonical and return 200: pointing at a redirect, a 404, or a non-canonical URL breaks it. The audit flags missing x-default, multiple entries per language, broken (non-200) targets, and hreflang pointing to non-canonical URLs.
A few disciplines that prevent most hreflang failures.
Generate it programmatically rather than hand-maintaining tags, so reciprocity and self-references are guaranteed. Keep it aligned with canonicals, hreflang and canonical must agree on which URL is the version; a contradiction between them is a frequent, confusing bug that overlaps with indexability.
Point only at indexable, 200, canonical URLs.Include x-default for users outside your targeted locales. Set the html lang attribute to match, the audit flags missing or invalid html lang and language mismatches. Re-validate after changes, because one edited or removed URL can break the whole cluster's reciprocity.
There are three places hreflang can be declared, and they are equally valid to a search engine. The choice is an engineering decision about where the data lives and how it stays correct, not an SEO one.
Whichever you pick, one rule dominates everything else: the set of annotations must be identical on every URL in the cluster, and every URL must annotate itself. A cluster is a closed group. If page A lists B and C, then B must list A and C, and C must list A and B. Miss one entry and search engines commonly discard the whole group rather than the single broken edge, which is why partial hreflang so often behaves as if it were not there at all.
The most common approach, and the easiest to debug because you can read it in view-source. A three-locale cluster with an x-default looks like this, and this exact block appears unchanged on all three pages:
Note that the English page lists itself, and that x-default points at the same URL as en. Both are correct and both are frequently omitted. The self-reference is not decorative: without it a page is not a member of its own cluster, and the annotation is treated as incomplete.
The cost of this method is page weight and duplication. A cluster spanning twelve locales puts thirteen link tags in the head of every page, and any locale you add means editing every existing page in the group. That is fine when the block is generated from a single source of truth in your templating layer, and painful when it is maintained by hand.
The sitemap method moves the whole cluster definition into one file, which is why it scales better. Each URL gets a <url> entry that carries the full set of alternates, using the xhtml namespace:
The same block is repeated for the Turkish and German URLs. It is more verbose in the sitemap, but it keeps page markup clean and gives you a single file to validate, which makes reciprocity errors far easier to catch programmatically. The trade-off is that the data is now invisible in view-source, so debugging a specific page means going back to the sitemap rather than reading the page itself.
For files with no HTML head, principally PDFs and other documents, the annotations go in the response header instead:
This is the narrowest of the three and worth using only where the other two cannot apply. Headers are the hardest to inspect casually and the easiest to lose in a server or CDN configuration change.
Mixing is where implementations quietly break. If the head tags say one thing and the sitemap says another, you have published two contradictory descriptions of the same cluster, and there is no rule that says which wins.
The usual way this happens is not a decision but an accident: a plugin starts writing head tags while a legacy sitemap still carries its own annotations, and nobody notices because both look correct in isolation. Pick one method, remove the others, and check for leftovers when you migrate.
Language-only codes such as en are enough if you don't target specific regions. Add a region code, for example en-GB against en-US, only when you genuinely have different versions per region: different pricing, different stock, different spelling and legal copy.
Adding region codes you don't need is not free. Every extra entry creates more reciprocity to maintain across the cluster and more that can break, so the safer default is the smallest set of codes that describes real differences in your content.
hreflang does not boost rankings. What it does is control which version is served to which user and prevent your localised pages being treated as duplicates of each other.
The benefit shows up indirectly: showing the right page to the right user improves relevance and reduces the chance your own versions cannibalise one another in search. A correct hreflang cluster doesn't lift a page above its competitors, it makes sure the traffic you already earn reaches the version that can actually convert it.
Free to start. Find broken return tags, invalid codes, missing x-defaults and non-200 targets.
Start my free audit