Kamaankamaan

Hreflang Tags: The Complete Implementation Guide (With Real Examples)

Hreflang implementation done right: the three methods, copy-paste code examples, x-default, and the reciprocity mistakes that make Google ignore your tags.

Junaid Khalid
Junaid Khalid
July 15, 2026 · 10 min read

You translated your blog into three languages, added hreflang tags, and Google is still serving the English page to users in Madrid. This is the most common outcome of a first hreflang attempt, and it almost never means the concept is wrong. It means one of the strict rules got broken: a missing self-reference, a return tag that does not return, a language code in the wrong format, or a canonical tag quietly contradicting the whole set. Hreflang is unforgiving that way. Get every rule right and it works silently; miss one and Google discards the annotation and guesses. This guide shows you the three implementation methods, real code you can adapt, and the exact mistakes that break them.

Quick takeaways

  • There are three ways to implement hreflang: HTML <head> tags, XML sitemap entries, and HTTP headers. Pick one; do not mix methods for the same pages.
  • Every page must carry a self-referencing hreflang tag plus a tag for each alternate, and all of them must be reciprocal.
  • Use ISO 639-1 language codes (en, de) and optional ISO 3166-1 region codes in uppercase (en-US, en-GB).
  • Always add an x-default tag as the fallback for users no other tag matches.
  • A CMS that emits hreflang server-side removes the two errors that break most setups: missing return tags and format mistakes.

What hreflang actually does

Hreflang is an annotation that tells search engines which language and, optionally, which region a page is meant for. When you have the same content in English, German, and Spanish, hreflang says: "serve the English one to English speakers, the German one to German speakers, and here is the fallback for everyone else." Without it, Google has to infer the relationship between your pages, and when it infers wrong it either serves the wrong language or collapses your variants into suspected duplicates.

One clarification that saves hours of debugging: the HTML lang attribute and hreflang are not the same thing. The lang attribute declares the language of the page you are on. Hreflang declares the language of the alternate URLs you are pointing to. You need both, and they do different jobs.


The three implementation methods

Google treats all three methods as equivalent. Choose the one that fits how your site is built, and use only that one for a given set of pages.

Method Where it lives Best for Watch out for
HTML <head> tags In the <head> of every page Most sites, easiest to add Adds markup to every page's head
XML sitemap In your sitemap file Large multilingual sites Harder to author and audit by hand
HTTP headers In the server response Non-HTML files like PDFs Requires server-level configuration

Method 1: HTML head tags

This is the most common method. In the <head> of every language version, you list a <link> element for each version of that page, including the page itself. Here is a complete set for a post that exists in English, German, and Spanish:

<link rel="alternate" hreflang="en" href="https://example.com/blog/post" />
<link rel="alternate" hreflang="de" href="https://example.com/de/blog/post" />
<link rel="alternate" hreflang="es" href="https://example.com/es/blog/post" />
<link rel="alternate" hreflang="x-default" href="https://example.com/blog/post" />

The critical detail: this exact block, pointing to all four URLs, must appear on the English page, the German page, and the Spanish page. Not a version that only lists "the others." Every page lists every version, itself included.

Method 2: XML sitemap

For large sites, putting hreflang in the <head> of thousands of pages bloats every response. The sitemap method moves the annotations into your sitemap file using xhtml:link entries. Each URL entry lists all its alternates:

<url>
  <loc>https://example.com/blog/post</loc>
  <xhtml:link rel="alternate" hreflang="en" href="https://example.com/blog/post" />
  <xhtml:link rel="alternate" hreflang="de" href="https://example.com/de/blog/post" />
  <xhtml:link rel="alternate" hreflang="es" href="https://example.com/es/blog/post" />
  <xhtml:link rel="alternate" hreflang="x-default" href="https://example.com/blog/post" />
</url>

You repeat a parallel <url> block for the German and Spanish URLs. It keeps your HTML clean, but it is tedious to author and audit manually, which is why sitemap hreflang is usually generated by the CMS rather than hand-written.

Method 3: HTTP headers

For files that are not HTML, PDFs, for example, you cannot add a <head> tag, so you declare hreflang in the HTTP response header:

Link: <https://example.com/doc.pdf>; rel="alternate"; hreflang="en",
      <https://example.com/de/doc.pdf>; rel="alternate"; hreflang="de"

Most blogs never need this method. It exists for completeness and for document-heavy sites.


The rules that make or break hreflang

Method matters less than getting these five rules exactly right. Break one and the entire annotation set for those pages gets ignored.

1. Self-referencing tags are mandatory. Every page must include an hreflang tag pointing to itself. A German page that lists English and Spanish but not German is invalid.

2. Return tags must be reciprocal. If page A points to page B as an alternate, page B must point back to page A. If your /us/ page links to /uk/, the /uk/ page must link back to /us/. One-directional annotations are discarded.

3. Use the correct code format. Language codes are lowercase ISO 639-1 (en, de, fr). Region codes are uppercase ISO 3166-1 Alpha 2 (US, GB), joined with a hyphen: en-US, en-GB. en_US with an underscore is wrong. A bare region without a language (hreflang="US") is also wrong; hreflang targets language first.

4. Always include x-default. The x-default value is the fallback for users whose language and region none of your other tags match. Leave it out and those users get an arbitrary version.

5. Hreflang and canonical must agree. Each language version should canonicalize to itself. A German page that canonicalizes to the English version while also claiming to be the German alternate sends contradictory signals and can get your translated pages dropped from the index.


The mistakes that silently cancel your work

These are the failure modes that produce "I added hreflang and nothing changed":

Checklist infographic of the five hreflang mistakes that break your tags: missing return tags, no self-reference, wrong code format like en_US, missing x-default, and canonical conflicts

  • Missing return tags. The number-one cause. An audit tool like Google Search Console's International Targeting report or a site crawler will flag these.
  • Wrong or absent canonicals. A translated page canonicalizing back to English tells Google the translation is a duplicate, not an alternate.
  • Mixing methods. Some pages annotated in the head, others in the sitemap, with conflicting sets. Pick one method per page set.
  • Codes that do not exist. Typos like hreflang="eng" or invented region codes are ignored.
  • Absolute vs. relative URL mistakes. Use full absolute URLs (https://...) in hreflang, always.

The common thread is that these are all mechanical, and all invisible until you audit. That is precisely why hand-maintaining hreflang across a growing multilingual blog is fragile: every new post is another chance to break reciprocity.


Let the CMS emit hreflang for you

Every rule above is deterministic. There is nothing creative about a self-referencing, reciprocal, correctly-formatted hreflang set; it is bookkeeping that a machine should do. That is the design choice behind Kamaan.

Kamaan is a headless blog CMS with Auto-Multilingual Delivery: you publish an English post once, it produces the language versions, and it emits the hreflang tags server-side, self-referencing and reciprocal, in the correct format, with x-default included. You never hand-write a <link rel="alternate"> tag, and you never ship a post with a missing return tag, because the tags are generated from the set of versions rather than typed per page. It uses the subfolder pattern (/de/blog, /es/blog) that this guide recommends, and it delivers content through a plain REST API into Next.js, Nuxt, SvelteKit, Astro, React, or Vue, so the hreflang lands correctly in whatever framework renders your blog.

If you run more than one blog, that correctness compounds: Kamaan's Multi-Site Management means every site you operate gets the same server-side hreflang from a single dashboard, instead of you re-verifying tags site by site.

Real-world scenarios

A developer maintaining a Next.js marketing blog kept getting "no return tags" errors in Search Console every time the content team added a language. They moved the blog to Kamaan on the Growth plan ($49/mo, 3 sites, 3 languages). Now every post ships with reciprocal hreflang emitted server-side; the developer fetches content through Kamaan's REST API with a normal fetch() and renders it, and the return-tag errors are gone because the tags are generated from the version set, not typed by hand.

A multi-product founder runs three SaaS blogs, each in four languages. Auditing twelve hreflang matrices by hand was a recurring chore. On Kamaan's Scale plan ($99/mo, 10 sites, 10 languages), all three blogs emit correct hreflang from one account, and adding a fourth product blog inherits the same correctness with no extra setup.


FAQ

What is hreflang implementation?

Hreflang implementation is the process of adding hreflang annotations to your pages so search engines serve the right language and region version to each user. It can be done through HTML head tags, XML sitemap entries, or HTTP headers, and it requires self-referencing, reciprocal tags in the correct code format.

What is an example of a hreflang tag?

A basic HTML example is <link rel="alternate" hreflang="de" href="https://example.com/de/blog/post" />, which tells search engines the German version of that post lives at that URL. Every language version, plus an x-default, needs its own line, and the full set must appear on every version of the page.

Do I need a self-referencing hreflang tag?

Yes. Every page must include an hreflang tag pointing to itself, in addition to tags for each alternate. Without the self-reference, the annotation set is invalid and search engines may ignore it.

What is x-default in hreflang?

x-default is the fallback value. It tells search engines which URL to serve to users whose language and region are not matched by any of your specific hreflang tags. Every set should include one.

Which hreflang method is best: HTML, sitemap, or HTTP headers?

Google treats all three as equivalent. HTML head tags are easiest for most blogs, the XML sitemap method suits very large sites because it avoids bloating every page's head, and HTTP headers are only needed for non-HTML files like PDFs. Use one method per page set, not a mix.

Why is my hreflang not working?

The most common causes are missing return tags (page A points to B but B does not point back), a canonical tag that contradicts hreflang, wrong code formats, or a missing self-reference. Google Search Console's International Targeting report and a site crawler will surface most of these errors.

Can a CMS handle hreflang automatically?

Yes. Because correct hreflang is fully deterministic, a headless CMS like Kamaan can emit the tags server-side from the set of published language versions, guaranteeing self-referencing, reciprocal, correctly-formatted annotations without anyone writing them by hand.

Start building with Kamaan

Stop hand-maintaining hreflang tags that break every time you add a language.

Kamaan gives you one dashboard for all your product blogs, auto-translated into every language your plan covers on each publish (up to 99+ on the Unlimited tier), with reciprocal hreflang emitted correctly server-side so your return-tag errors disappear. First month free.

Start free at kamaan.io

Frequently asked

FAQ · 7 ITEMS
What is hreflang implementation?

Hreflang implementation is the process of adding hreflang annotations to your pages so search engines serve the right language and region version to each user. It can be done through HTML head tags, XML sitemap entries, or HTTP headers, and it requires self-referencing, reciprocal tags in the correct code format.

What is an example of a hreflang tag?

A basic HTML example is `<link rel="alternate" hreflang="de" href="https://example.com/de/blog/post" />`, which tells search engines the German version of that post lives at that URL. Every language version, plus an `x-default`, needs its own line, and the full set must appear on every version of the page.

Do I need a self-referencing hreflang tag?

Yes. Every page must include an hreflang tag pointing to itself, in addition to tags for each alternate. Without the self-reference, the annotation set is invalid and search engines may ignore it.

What is x-default in hreflang?

`x-default` is the fallback value. It tells search engines which URL to serve to users whose language and region are not matched by any of your specific hreflang tags. Every set should include one.

Which hreflang method is best: HTML, sitemap, or HTTP headers?

Google treats all three as equivalent. HTML head tags are easiest for most blogs, the XML sitemap method suits very large sites because it avoids bloating every page's head, and HTTP headers are only needed for non-HTML files like PDFs. Use one method per page set, not a mix.

Why is my hreflang not working?

The most common causes are missing return tags (page A points to B but B does not point back), a canonical tag that contradicts hreflang, wrong code formats, or a missing self-reference. Google Search Console's International Targeting report and a site crawler will surface most of these errors.

Can a CMS handle hreflang automatically?

Yes. Because correct hreflang is fully deterministic, a headless CMS like Kamaan can emit the tags server-side from the set of published language versions, guaranteeing self-referencing, reciprocal, correctly-formatted annotations without anyone writing them by hand.

Junaid Khalid
Written by
Junaid Khalid

Junaid Khalid is the founder of Kamaan, a headless blog CMS that auto-publishes in five languages and lets you manage every product blog from one dashboard.