SEO
Written on 13/9/2026
Updated on 13/9/2026
3min

hreflang: across 19 multilingual sites, the top defect is a forgotten template

Thibaut Legrand
Thibaut Legrand
Co-founder - Vydera
hreflang international SEO audit Vydera
Table of contents

Your site speaks several languages, Google serves one?

Vydera audits, fixes and verifies template by template.

Talk to an expert

Key takeaways

  • 25 public multilingual domains frozen before the measurement, 23 measured, 110 pages, 790 hreflang declarations, 305 targets opened. Plain HTTP, no browser, 28 August 2026
  • Four classic syntax errors do not appear once: missing self-reference 0 sites out of 19, relative URL 0 declarations out of 790, conflicting duplicate 0, tags outside the <head> 0
  • The most widespread defect is a missing tag, not a malformed one. 4 sites out of 19 serve hreflang on only part of their pages, and the same templates drop out every time: blog pagination, category pages, deep sections
  • 2 multilingual sites serve no hreflang at all in their HTML while exposing 9 and 19 locales in their own links
  • No measured count exceeds 4 sites out of 19, and every one is a floor: 5 pages per site say nothing about the sixth

The scenario never changes. hreflang is in place, the agency shipped it, the audit tool shows green, and Google keeps serving English to French visitors. The list of six classic mistakes has been circulating for a decade: missing self-reference, relative URL, invented language code, tags outside the <head>. We were going to publish it.

We measured first. The list does not hold. Four of those mistakes do not appear once across the 19 sites in our panel that serve hreflang. The dominant defect is not a malformed tag, it is a tag missing from an entire template. Here is the measurement, the method to repeat it, and the three manual checks that changed the result.

What we measured

25 public multilingual domains, frozen before the measurement on editorial criteria: 8 French SaaS, 5 e-commerce sites, 5 international brands, 5 SEO tools, plus vydera.com and a second reference site we work on. One domain per hreflang cluster, to avoid counting the same markup twice.

23 were measured. Two, blablacar.fr and decathlon.fr, return 403 on the homepage itself: that is a failed measurement, not a result. Nothing can be said about their hreflang, and they leave the denominator.

On each site, 5 pages drawn deterministically: the homepage after redirects, 2 first-level pages spread across the link list, 2 pages reached on the second hop, the deepest available. 113 pages drawn, 110 measured: three failures, one 403 behind bot protection and two email-obfuscation URLs that are not pages.

Total: 790 hreflang declarations, 564 distinct declared targets, 305 opened, 570 HTTP requests. No browser, no JavaScript rendering: a browser User-Agent, bare HTTP requests, and above all no Accept-Language header, because a crawler sends none. That detail turns out to move the numbers.

One caveat governs everything below. Every counter is a floor. A defect absent from 5 pages is not a defect absent from the site. We write "at least 4 sites out of 19", never "21% of sites".

Four textbook errors, zero occurrences

The most useful result is a negative one. Across the 19 sites serving hreflang:

  • Missing self-reference: 0 sites out of 19. All 80 pages carrying tags declare themselves.
  • Relative URL: 0 declarations out of 790. Every one is absolute, protocol and domain included.
  • Same code pointing at two URLs: 0 sites out of 19.
  • Tags served outside the <head>: 0 sites out of 19.

Two further checks also come back at zero: no target returns 4xx across the 305 opened, and no target lands back on its source page.

Malformed hreflang is a largely solved problem on sites of this calibre. CMSs generate the markup, and a generator does not get the syntax wrong. It gets the scope wrong.

The top defect: the template the CMS forgets

Only one check goes above 2 sites: hreflang present on only part of the site's pages. 4 sites out of 19, and the mechanism is identical in all four.

  • dashlane.com: homepage and about page carry 5 declarations. The three /resources/category/* pages carry zero.
  • ahrefs.com: homepage and about page carry 14 declarations. The two /blog/category/* pages carry zero.
  • oncrawl.com: homepage, blog and product page carry 3 declarations. /blog/page/2/ and /blog/page/3/ carry zero.
  • ikea.com: the global homepage carries 116 hreflang values. The four /global/en/* pages carry zero.

The pattern is impossible to miss: the markup is emitted by the homepage and content templates, and it disappears on listing, category and pagination templates. Nobody removed it. Nobody ever added it, because those templates were written elsewhere, usually later, usually by somebody else.

The consequence is mechanical, and worth stating for exactly what it is: on those pages, Google has no declared locale signal at all. What the engine serves instead, our measurement does not say: we collected no SERP and no per-language position data. The absence of signal, though, is measured.

Hence a simple working rule: audit by template, not by page. List your site's templates, take one instance of each, and start with the ones nobody ever looks at: page 2 of a blog, category pages, author archives, internal search results, legal pages, corporate sections living under their own path.

International SEO: the widest gap is total absence

Before talking about errors at all, there are the sites serving nothing. Of the 23 domains measured, 3 serve no hreflang tag at all, neither in their HTML nor in their sitemap. The case is more interesting than it looks, because the three are not alike.

  • qonto.com: zero hreflang, and 9 locale segments exposed in the links on its own homepage (de, de-at, en, es, fr, fr-be, it, nl, pt).
  • deepl.com: zero hreflang, and 19 locale segments in its homepage links.
  • screamingfrog.co.uk: zero hreflang, and zero locale segments. The site is monolingual: its lack of hreflang is the correct behaviour, not a defect. Counting it as faulty would be a reading error.

That leaves 2 multilingual sites out of 22 declaring no language mapping in the HTML they serve. A fourth, pennylane.com, serves none in its HTML but publishes hreflang in its sitemap, a channel Google accepts.

One critical reservation here, and it is methodological: we are talking about served HTML, not the rendered DOM. With no browser, hreflang injected by JavaScript stays invisible. So we do not know whether qonto.com and deepl.com inject it client-side. What we know is that none of it sits in the HTTP response, which is already a gamble: we covered served HTML versus rendering in detail in our JavaScript rendering measurement.

Tag-level defects, all at 1 or 2 sites

The five other positive checks involve 1 or 2 sites each. The gap between those ranks means nothing: at these counts no statistical test applies, and one site either way flips the order. They are worth reading as cases, not as frequencies.

Codes outside ISO, 2 sites. ikea.com declares in-ID (the language code in was withdrawn in favour of id for Indonesian), es-SP (Spain is ES, SP is not a country) and es-CE (no CE region in ISO 3166-1). ovhcloud.com declares asia, which is not a language code: the first segment of a hreflang value is always a language, never a geographic zone. Covering a region takes one line per country.

Target redirecting to a third URL, 2 sites. 360learning.com declares /lp/ pages that redirect to /use-cases/. similarweb.com declares a product page redirected to its category, across 4 locales at once. In both cases the announced pair does not exist as written: it is the trace of a URL rework the markup never followed.

Approximate self-reference, 1 site. dashlane.com serves /about and declares hreflang="en" there pointing at /about/, with a trailing slash the served page does not have. The self-reference is present, it is simply not exact. That is the kind of gap no human review catches and only a character-by-character comparison finds.

Target canonical naming another URL, 1 site. oncrawl.com declares fr pointing at fr.oncrawl.com, whose canonical points at www.oncrawl.com, the English version. The markup sends visitors to a page that itself says it is not the right one. Canonical and hreflang have to tell the same story, and when they clash the canonical wins. The same conflict shows up among the causes of pages not being indexed.

Reciprocity contradicted, 1 site. ikea.com again. Of 8 targets tested from the global homepage, 7 serve a page canonical of itself, with zero hreflang tags. The eighth, ikea.gr/en/, declares only el-gr and en-gr and points nowhere back.

Reciprocity: 287 out of 305, and why that is not a rate

Across the 305 opened targets, 287 do point back at their source page, 10 redirect elsewhere, 7 serve no tag at all, 1 serves tags that ignore the source.

The number looks excellent. Read it twice. 305 targets opened out of 564 declared, which is 54%. The probe caps at 8 targets per page, and 19 pages hit that cap. The reciprocity of the other 259 is unknown. So this is a floor measured on a sample that is itself a floor.

What the number does establish: when a target is opened, it confirms the pair in the large majority of cases. Reciprocity is not a courtesy, it is the condition of validity. A hreflang the target does not confirm is ignored.

Three manual checks that changed the result

This is the part audits rarely publish, and the one worth most to anyone repeating this kind of measurement. Three times, the first pass produced a false result.

1. An HTTP 202 with 0 bytes is not a page without hreflang. similarweb.com answered 202 with an empty body on its locale pages. The script concluded "zero tags" and manufactured 8 false reciprocity breaks. Reclassified as a failed measurement, then detected by the script. The general rule: an empty response, a 202, a 403, a 429 or a bot-check page is unmeasured, never "no hreflang".

2. An Accept-Language header manufactures defects that do not exist. The first pass sent Accept-Language: fr-FR, as a French browser would. Result: 5 target redirects appeared, with the English version of payfit.com, spendesk.com and dashlane.com falling back to the French page. Without the header, all five vanish. Those same three sites also serve a different canonical depending on the announced language: dashlane.com/business-password-manager/buy declares itself canonical with no header, and canonical of its French version with Accept-Language: fr-FR. That is not a hreflang error, and a crawler will never see it. Always audit without a language header. Otherwise you are auditing what your browser sees, not what the engine sees.

3. Two HTTP clients do not count the same thing. curl reported 0 tags on ikea.gr/en/ and on ikea.com/ee/et/ where Node's fetch saw 2 and 0. The 7 zero-tag targets were therefore reopened with an independent request: canonical of themselves, zero tags confirmed. When two tools disagree, neither is the measurement: the measurement is the third reading.

vydera.com goes through the same bench

Our own site went through the same code as the other 24, with no special handling. 5 pages out of 5 carry hreflang, 3 declared values (fr, en, x-default), strict self-reference on all 5, reciprocity verified against the English version, consistent canonical. None of the 12 defects found.

Two reservations, because a floor is not a clean bill of health. First, 5 pages on a site of 168 URLs prove nothing about the other 163: the floor rule applies to us exactly as it applies to ikea. Second, our x-default points at the French version, not the English one. That is a deliberate choice for an agency whose first market is France, and we make no claim about what Google does with it.

The panel's second reference site, one we work on and therefore do not name here, shows 5 pages out of 5, 5 declared values and no defect found. Same floor caveat.

Repeating the measurement on your site

None of this needs a paid tool. The protocol fits in four steps.

  1. List your templates, not your pages. One instance of each: homepage, content page, product page, category page, page 2 of a pagination, legal page, corporate section. That is where the top defect lives.
  2. Fetch the served HTML with no language header. A curl -sL with a browser User-Agent is enough. No Accept-Language.
  3. Open every declared target and record four things: HTTP status, final URL after redirects, the target's own hreflang tags, and its canonical. A pair is valid only when all four agree.
  4. File failures as failures. 403, 429, empty 202, timeout: unmeasured. A site you could not open is not a site without hreflang.

The block below runs the six checks readable from a single page's HTML, and generates the curl loop for the checks that require opening the targets. Nothing you type leaves your browser.


  

What this measurement does not say

The most important part of any measurement is its perimeter. This one stops dead in several places.

  • hreflang injected by JavaScript. No rendering was performed. Everything above concerns served HTML.
  • blablacar.fr and decathlon.fr. 403 on the homepage, so nothing to say about them.
  • 259 declared targets out of 564 were never opened, for lack of room under the cap of 8 per page.
  • No position, traffic or impression data by locale. Nothing here ties a hreflang error to a measured loss, and nobody should infer one from these numbers.
  • No SERP collected. We do not know which language version Google actually serves for these domains.
  • No history. This is a photograph taken on 28 August 2026, not a trend.

What survives those reservations fits in one sentence: on sites of this calibre, hreflang syntax is a solved problem and hreflang coverage is not. Hunt for templates, not for typos.

For the definitions: indexing and crawl. And if the topic is shipping a site across several markets, that is our localization offer.

  • What does a hreflang tag actually do?

    It tells Google that two URLs are the same page in two languages or two markets, so it serves the right version to the right user instead of arbitrating between pages it might read as duplicates. It pushes nothing up the rankings: it steers which version is displayed, it does not create a position.

  • What is the most frequent hreflang error?

    On our panel it is not a syntax error: it is hreflang missing from part of the site's templates, found on 4 sites out of 19. Blog pagination, category pages and deep sections carry zero tags where the homepage carries up to 116. The four classic syntax errors, meanwhile, do not appear once.

  • Is x-default mandatory?

    No. Google recommends it without requiring it, and 7 of the 19 sites measured serve none. It is useful if you run a language picker or a default version for visitors matching no declared locale. Counting its absence as an error would distort any scorecard.

  • Should hreflang go in the HTML, the sitemap or the HTTP header?

    All three channels are valid for Google. Across our 790 declarations, all 790 come from the HTML <head> and none from the HTTP header, and one site in the panel publishes hreflang only in its sitemap. The sitemap keeps pages lighter and centralises maintenance; the HTML is verifiable with a plain curl. What matters is picking one and sticking to it.

  • Why does my audit tool report hreflang errors that do not exist?

    Often because it sends an Accept-Language header. On our first pass, an Accept-Language: fr-FR manufactured 5 target redirects and 3 varying canonicals that vanish without the header. A crawler sends none: audit the way it does, with no language header. Second cause: empty or 202 responses read as pages without tags.

  • How do I check hreflang without a paid tool?

    A curl -sL with a browser User-Agent, no Accept-Language, plus a grep on <link[^>]*hreflang. Then open each target and record its HTTP status, final URL, own tags and canonical. Budget one page per template, not one page per section: it is the only way to see the most frequent defect.


Thibaut Legrand
Thibaut Legrand
Co-founder - Vydera