Published 22 May 2026

Here is the problem. You run an online store with a UK English site, a US English site, and a Spanish site. The product pages are near-identical — same product, same images, prices and spelling adjusted per market. To a search engine these three pages look like duplicate content, and it has to guess which one to rank and serve. Left to guess, it serves your US page to a UK shopper (wrong currency, wrong spelling), or buries two of the three versions as duplicates of the first. Either way, a user lands on the wrong page.

Hreflang is the instruction that fixes this. It tells search engines: "these pages are alternate language or regional versions of each other — here is the full set, and here is the language and region each one targets." The search engine then serves the right version to the right user based on their language and location, and treats the cluster as a coordinated group rather than competing duplicates. This guide covers the syntax, the codes, the return-tag requirement that trips up nearly everyone, how hreflang interacts with canonical tags, and how to verify the whole thing is working.

What Hreflang Looks Like

An hreflang annotation is a set of <link rel="alternate"> tags in the <head>, one per language/region version:

<link rel="alternate" hreflang="en-gb" href="https://example.com/uk/widget/">
<link rel="alternate" hreflang="en-us" href="https://example.com/us/widget/">
<link rel="alternate" hreflang="es" href="https://example.com/es/widget/">
<link rel="alternate" hreflang="x-default" href="https://example.com/widget/">

Each tag names a version and the URL that serves it. The href must be an absolute URL — protocol and domain included. Relative URLs are a silent killer here; search engines do not reliably resolve them in hreflang context, and the whole annotation can be ignored.

Three Ways to Implement It — Pick One

There are three valid methods of delivering hreflang. They are equivalent in effect; the right choice depends on your site.

The important rule: use one method per site. Do not mix head tags and sitemap entries for the same pages — at best it is redundant, at worst the two disagree and you have created a debugging nightmare. Choose the method that fits your stack and apply it consistently.

Language and Region Codes

The value of the hreflang attribute is a language code, optionally followed by a region code:

Language alone (es) targets all speakers of that language regardless of country. Language plus region (es-mx) targets Spanish speakers in Mexico specifically. Use language-only when one version serves all regions, and add a region only when you genuinely have a country-specific version. You cannot specify a region without a language — hreflang="us" on its own is invalid.

The code mistakes that bite

The x-default Value

The special value x-default marks the fallback page — the version to serve when no other hreflang entry matches the user's language and region:

<link rel="alternate" hreflang="x-default" href="https://example.com/widget/">

Use it for the page that handles "everyone else." Common patterns: a language-selector landing page, a generic English page that catches users whose language you do not specifically target, or a global homepage that redirects based on geolocation. If you have a UK, US, and Spanish version and a French speaker arrives, x-default decides what they get instead of leaving the search engine to guess. It is optional, but on any serious international setup you want one.

The Return Tag Requirement

This is the single most important rule in hreflang, and the source of the number-one error: hreflang must be bidirectional.

If page A links to page B with an hreflang tag, page B must link back to page A. Every page in a cluster has to reference every other page in the cluster — and itself. These back-references are called return tags. If a return tag is missing, search engines treat the annotation as unconfirmed and may ignore it entirely.

Concretely, with three versions, the same complete block appears on all three pages:

<!-- This identical block goes on the UK, US, AND ES pages -->
<link rel="alternate" hreflang="en-gb" href="https://example.com/uk/widget/">
<link rel="alternate" hreflang="en-us" href="https://example.com/us/widget/">
<link rel="alternate" hreflang="es" href="https://example.com/es/widget/">
<link rel="alternate" hreflang="x-default" href="https://example.com/widget/">

Notice that each page also lists itself — the UK page includes the en-gb tag pointing at its own URL. That is the self-referencing hreflang, and it is required, not optional. A page that lists its siblings but omits itself is an incomplete annotation.

The practical takeaway: build the hreflang block once, then output the exact same block on every page in the cluster. If you generate it dynamically and each page only ever knows about its siblings, you will drop return tags. Generate the full set, every time.

Hreflang and Canonical Tags

Hreflang and canonical tags must be consistent, and getting their relationship wrong silently breaks both.

The rule: each language version canonicals to itself, not across languages. The Spanish page's canonical points to the Spanish URL; the UK page's canonical points to the UK URL. They are different pages serving different audiences — they are not duplicates of each other, even though hreflang declares them as alternates.

<!-- On the Spanish page -->
<link rel="canonical" href="https://example.com/es/widget/">  <!-- self -->
<link rel="alternate" hreflang="en-gb" href="https://example.com/uk/widget/">
<link rel="alternate" hreflang="en-us" href="https://example.com/us/widget/">
<link rel="alternate" hreflang="es" href="https://example.com/es/widget/">

The classic mistake is pointing every language version's canonical at the English page — for example the Spanish page canonicalising to /uk/widget/. That tells the search engine "the Spanish page is a duplicate of the UK page, index the UK one instead," which de-indexes your Spanish content and makes the hreflang annotation self-contradictory. Hreflang says "these are distinct alternates"; the cross-language canonical says "no they're not." The two instructions conflict, and you lose. Canonical points to self within each language version, always.

Common Mistakes

1. Missing return tags

Page A references B but B does not reference A. The most common hreflang error by a wide margin. The annotation goes unconfirmed and is ignored. Always output the full bidirectional set.

2. Wrong or invalid codes

en-uk instead of en-gb, en-eu for "Europe," region-only values like us, or codes that are not real ISO 639-1 / 3166-1 entries. Invalid codes are silently dropped.

3. Canonical pointing across languages

Each version canonicalising to the English page instead of to itself. Contradicts hreflang and de-indexes the alternates. Self-canonical per language version.

4. Relative URLs

href="/es/widget/" instead of the full absolute URL. Hreflang requires absolute URLs with protocol and domain; relative ones can cause the whole annotation to be ignored.

5. Only tagging some pages

Hreflang on the homepage cluster but not on product or category pages. hreflang works per-URL — each set of alternate pages needs its own annotation. Partial coverage means partial protection.

6. Linking to non-200 URLs

An hreflang href pointing at a redirect or a 404. The alternate must resolve directly to a live 200 page, just like a canonical. Broken targets break the cluster.

7. Mismatched clusters

The UK page lists three alternates, the US page lists two, the ES page lists four. Every page in a cluster should declare the identical set. Inconsistent sets confuse the consolidation.

How to Verify Hreflang

  1. Run any URL through Meta Tag Checker — it surfaces the alternate tags alongside the canonical and the rest of your meta tags, so you can confirm the language codes and URLs at a glance.
  2. View Source in the browser and search for hreflang — confirm every expected version is present, including the self-reference and any x-default.
  3. curl and grep across the cluster: curl -s https://example.com/es/widget/ | grep hreflang. Run it on each URL and check the blocks match.
  4. Google Search Console. The international targeting and indexing reports flag return-tag errors and unknown language codes — historically surfaced in the dedicated hreflang report, and still reported through Search Console's coverage and URL Inspection tooling. This is the authoritative check for whether Google has actually accepted your annotations.
  5. Third-party crawlers (Screaming Frog, Sitebulb, Ahrefs) crawl the full cluster and explicitly flag missing return tags, invalid codes, and broken alternate URLs across the whole site at once — the fastest way to audit a large multilingual setup.

The crawler and Search Console checks complement each other: the crawler tells you whether your markup is internally consistent, Search Console tells you whether the search engine accepted it.

The Production Habit

For new international pages:

For existing sites:

Hreflang is unforgiving in the small details and invisible when it fails — pages just quietly rank in the wrong markets. Build the block correctly once, output it consistently, and verify it. Meta Tag Checker takes the guesswork out of confirming the alternates and canonical on any URL you want to check.

Verify your hreflang setup

Meta Tag Checker shows the alternate tags, the canonical, and every meta tag for any URL — instantly.

Check Your Page →