The short answer
Hreflang is markup that tells Google several pages are language versions of one another. It does not improve rankings: its job is to serve the right version to the right user and stop your versions from competing in the same result set. The setup comes down to three rules: links are reciprocal, every page references itself, and every URL is absolute and returns a 200 status.
Everything else in this article is about why hreflang still breaks even when those three rules are followed, and how to spot it.
What hreflang is actually for
"So Google understands the languages" is too vague to configure anything against. In practice hreflang solves two problems.
First, version selection in search results. Someone searches in Estonian and is shown the Russian version of your page. They do not switch language — they go back to the results and click a competitor instead. Hreflang reduces the chance of that swap.
Second, signal consolidation. Google treats hreflang-linked pages as one entity across languages rather than several independent documents. Link and behavioural signals accumulated by one version work for the whole cluster.
What hreflang does not do:
- it does not substitute for genuinely good content in that language — if a page is machine-translated and misses the actual query wording, no markup will save it (I covered why in the article on which language to target for SEO in Estonia);
- it does not protect against duplicate content — language versions are not duplicates in the first place;
- it is not a directive. Google describes hreflang as a signal it takes into account, not one it is obliged to follow.
What correct markup looks like
Take a service page on a site with three languages. The <head> of all three versions must carry the same set of tags:
<link rel="alternate" hreflang="et" href="https://example.ee/teenused/seo" />
<link rel="alternate" hreflang="ru" href="https://example.ee/ru/uslugi/seo" />
<link rel="alternate" hreflang="en" href="https://example.ee/en/services/seo" />
<link rel="alternate" hreflang="x-default" href="https://example.ee/teenused/seo" />
The key point: the set is identical on all three pages, including the page's reference to itself. That is not redundancy — without the self-reference the relationship counts as incomplete.
There are three places to put the markup, and the choice does not affect the result:
| Method | When it suits | Limitation |
|---|---|---|
Tags in <head> | Ordinary HTML pages, most sites | Bloats <head> when you have many languages |
| XML sitemap | Many languages, or no access to the template | Harder to verify by eye |
HTTP Link header | PDFs and other non-HTML files | Configured at server level |
Choose on one criterion: can you generate it automatically. Hreflang added by hand at publication time falls apart somewhere around the second hundred URLs — that is a matter of time, not of diligence.
On this site the markup is generated from a single registry of slug mappings, and language alternates are only emitted for pages that actually exist. That is a deliberate constraint: better to serve no hreflang at all than to point at a page that is not there.
The six mistakes I see most often
Below is what I regularly find on multilingual Estonian sites during a technical audit, roughly in order of frequency.
| Mistake | How it shows up | What to do |
|---|---|---|
| Non-reciprocal links | Google ignores hreflang across the whole cluster | Generate markup from one source, not page by page |
| No self-reference | The relationship counts as incomplete and is discarded | Add a hreflang for the page itself in every version |
| Relative URLs | The markup is not parsed | Absolute URLs only, with scheme and domain |
| Link to a redirect or 404 | The relationship breaks silently | Check status codes of every URL in the markup with a crawler |
| Conflict with canonical | Canonical points at another language version, cancelling hreflang | Each page's canonical points at itself |
| Automatic redirect by browser language | Googlebot only ever sees one version | Offer the language with a banner, do not force a redirect |
The conflict with canonical deserves separate attention — it is the most insidious of the six, because each piece of markup looks correct in isolation. If the Russian version of a page carries a canonical pointing at the Estonian one (a common result of copying a template), you are telling Google both "this is an independent language version" and "this is a copy of another page, do not index it". Google follows the canonical and the Russian version simply drops out of the index. I covered similar drop-out scenarios in the article on why Google is not indexing your pages.
One more thing specific to Estonia: a language code is not a country code. hreflang="ee" is a common typo, because the .ee domain is right there in front of you. There is no language code ee — Estonian is et. Such a tag is simply ignored and the markup becomes incomplete.
How to verify Google accepted it
Check on three levels, and the first two do not replace the third.
- Page source. Open the page through "view page source", not the element inspector. If the tags only appear in the inspector, JavaScript is injecting them after load and the markup may never reach the index. Check one page of each type this way: home, category, article, product.
- Crawler. Screaming Frog or equivalent walks the site and surfaces what you cannot find by hand: non-reciprocal pairs, links to redirects, missing self-references, canonical conflicts. It is the only practical way to check a site with more than about fifty pages.
- Search Console. The final authority: it shows what Google accepted, not what you served. Look at the coverage report and crawl stats — if pages moved into "Duplicate, Google chose a different canonical" after you deployed hreflang, you have a canonical conflict.
Expect the changes to take weeks rather than days to register: Google has to recrawl every page in the cluster to see that the links are reciprocal. It is the same delayed-reaction logic I described when explaining why changing hosting does not hurt SEO — changes are only visible after a recrawl.
What I see in practice
A few observations from Estonian projects, without numbers where I do not have precise ones.
Hreflang is almost never the reason traffic drops. When a second language version brings no visitors, in the overwhelming majority of cases the problem is not the markup but that the pages were translated word for word and miss the query wording of their own language. Hreflang gets checked first because it is quick and legible, while the real problem sits in the semantics.
Broken hreflang, on the other hand, is almost always broken entirely. I rarely meet a site where the markup is correct on 90% of pages: either it is generated from code and works everywhere, or it was added by hand and has fallen apart almost everywhere. There is practically no middle state — and that is good news, because what needs fixing is the generation, not individual pages.
Limits of applicability. Everything above is tested on sites of up to a few thousand pages with two or three languages. On large multi-regional projects, where a dozen countries are layered on top of language, region priorities introduce their own complications and the verification approach is different.
What to do right now
A short sequence if you have a second language version and are unsure about the markup.
- Open the page source of one page from each version and compare the tag sets — they must match completely, including the self-reference.
- Check the canonical on the non-primary language versions: it must point at the page itself, not at the primary language.
- Run a crawler over the site and filter for non-reciprocal relationships and URLs returning anything other than 200.
- Remove any automatic redirect based on browser language and replace it with an unobtrusive banner offering to switch.
- Confirm the markup is generated rather than hand-written. If it is hand-written, that is the first thing worth rebuilding at the web development stage, while the page count is still small.
If the picture still does not add up after those five steps, or Search Console is showing something ambiguous, write to me. Reviewing multilingual markup usually takes a couple of hours and is part of a technical SEO audit; more often than not the problem turns out not to be hreflang at all, but it is worth finding out before you invest in content for the second version.
