hreflang Implementation: HTML Tags, Headers or Sitemap?

By the ResilientLang team · Published · 5 min read

Google accepts hreflang in three places: link elements in the HTML head, Link HTTP response headers, and xhtml:link entries in an XML sitemap. Google states that the three methods are equivalent from its perspective, so the right choice is the one you can generate and maintain without errors. Use one, not several.

What are the three hreflang methods?

Each method carries the same information: the language or region of a page and the URLs of all its alternates, including itself. They differ in where the information lives and who has to edit what.

Item HTML link tags HTTP Link header XML sitemap
Where <head> of each page Response header of each URL One or more sitemap files
Works for non-HTML files No Yes Yes
Needs access to Page templates Server or CDN configuration Sitemap generator
Adds to page weight Yes, per page No No
Easy to inspect in a browser View source Network tab or curl -I Open the XML file
Best for Small to mid-size sites with template control PDFs and other files Large sites, or when heads are hard to edit

All three require return links, self-references and fully-qualified URLs; the rules are covered in What is hreflang.

Place one link element per version inside the head of every page in the group:

<head>
  <link rel="alternate" hreflang="en-GB" href="https://example.com/en-gb/shoes/" />
  <link rel="alternate" hreflang="en-US" href="https://example.com/en-us/shoes/" />
  <link rel="alternate" hreflang="fr"    href="https://example.com/fr/chaussures/" />
  <link rel="alternate" hreflang="x-default" href="https://example.com/shoes/" />
</head>

Google's documentation says this approach is useful if you do not have a sitemap or the ability to specify HTTP response headers.

Strengths: the annotation sits on the page it describes, so it is easy to audit by viewing the source, and it is the default in most CMS plugins and platform features.

Weaknesses: every page carries the full list, so a site with 20 languages adds 20 lines to each page. If the tags are injected by JavaScript, they only count if the page is rendered; the more robust choice is to output them in the server-delivered HTML. Because each page has its own copy, a template bug or a stale cache can leave different pages with different lists.

The same information is sent in the Link header of the response. Google documents the pattern as a comma-separated list:

Link: <https://example.com/en/guide.pdf>; rel="alternate"; hreflang="en",
      <https://example.com/fr/guide.pdf>; rel="alternate"; hreflang="fr",
      <https://example.com/guide.pdf>; rel="alternate"; hreflang="x-default"

Google's documentation says the header method is useful for non-HTML files such as PDFs, which have no head to hold link tags. In an Nginx configuration the idea looks like this:

location = /en/guide.pdf {
  add_header Link '<https://example.com/en/guide.pdf>; rel="alternate"; hreflang="en", <https://example.com/fr/guide.pdf>; rel="alternate"; hreflang="fr"';
}

Strengths: it works for files that are not web pages and adds nothing to the HTML.

Weaknesses: it is hard to see without a developer tool, long headers can run into size limits in proxies and servers (check your own limits, since they vary), and it is easy to forget when a CDN or cache rule strips or rewrites headers. For ordinary pages it is rarely the most convenient option.

How do XML sitemap annotations work?

In a sitemap, each url entry lists all its alternates as xhtml:link children. The xhtml namespace must be declared on the urlset element:

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
        xmlns:xhtml="http://www.w3.org/1999/xhtml">
  <url>
    <loc>https://example.com/en/shoes/</loc>
    <xhtml:link rel="alternate" hreflang="en" href="https://example.com/en/shoes/" />
    <xhtml:link rel="alternate" hreflang="fr" href="https://example.com/fr/chaussures/" />
  </url>
  <url>
    <loc>https://example.com/fr/chaussures/</loc>
    <xhtml:link rel="alternate" hreflang="en" href="https://example.com/en/shoes/" />
    <xhtml:link rel="alternate" hreflang="fr" href="https://example.com/fr/chaussures/" />
  </url>
</urlset>

Notice that the French and English pages each get their own url block, and both blocks list both versions. The rules do not relax in a sitemap: self-reference and return links still apply. Our article on multilingual XML sitemaps covers sitemap indexes, lastmod and submission.

Strengths: it keeps pages light, it can be produced by a single script or plugin, and one file shows the whole language graph, which makes auditing and diffing easier. It is useful when you cannot edit page heads.

Weaknesses: the file grows quickly. Each URL repeats every alternate, so the number of lines is roughly the number of URLs times the number of languages. Sitemaps have limits of 50,000 URLs and 50MB uncompressed per file according to sitemaps.org, so large sites need several files and a sitemap index. A stale sitemap silently serves outdated annotations.

Which hreflang method should you choose?

A practical way to decide:

  1. Do you serve non-HTML files that need alternates? Use HTTP headers for those, and the same method for the rest only if that is simpler for you.
  2. Do you control the page templates and have fewer than a few thousand URLs per language? HTML tags are the simplest and the easiest to verify by eye.
  3. Is your catalogue large, or are templates owned by someone else (a platform, an agency)? A sitemap is usually easier to generate and audit in one place.
  4. Is your content managed by a plugin or platform that already outputs one method? Keep that method and turn the others off.

This is common practice and our own reasoning rather than a documented rule; Google only says the methods are equivalent.

Why should you not mix methods?

Google says that although you can use all three at once, there is no benefit in Search. The cost is real: if the HTML tags say one thing and the sitemap says another, you have conflicting signals and a harder debugging job. If you change a slug in one place and forget the other, the stale copy points to a redirect or a 404. Choose a single source of truth and remove the rest. If you must keep two for a transition, make them generated from the same data so they cannot diverge, and see hreflang mistakes for what conflicts look like.

What about Bing?

Bing's Webmaster Blog recommends hreflang for language and regional targeting, but we did not find Bing documentation that says which of the three delivery methods it reads or how it resolves conflicts. Treat support for the sitemap and header variants in Bing as unverified. If Bing traffic matters to you, HTML tags are the form most likely to be read by any crawler, though that is an inference and not a documented guarantee.

Key takeaways

  • Google documents three hreflang methods (HTML tags, HTTP headers, XML sitemap) and says they are equivalent.
  • Pick one and generate it from a single data source; mixing methods offers no benefit in Search and invites conflicts.
  • Use HTTP headers for PDFs and other non-HTML files.
  • Sitemaps keep pages light and are easy to audit, but grow with URLs times languages and must respect sitemap size limits.
  • The rules are identical for all methods: self-reference, return links, fully-qualified URLs, valid codes.
  • Bing's handling of each method is not clearly documented, so verify with your own testing.

Sources

Frequently asked questions

Which hreflang method is best?

Google says the three methods are equivalent from its perspective, so there is no universally best one. Choose by what you can maintain reliably: HTML tags if you control templates, a sitemap if you have many pages or cannot edit page heads, HTTP headers for non-HTML files such as PDFs.

Can I use more than one hreflang method at once?

You can, but Google says there is no benefit in Search. It also becomes harder to keep the copies consistent, and conflicting annotations are a common source of errors. Pick one method as the source of truth and generate it from a single data source.

How do I add hreflang to a PDF?

Use an HTTP Link header in the response that serves the PDF, because a PDF has no HTML head to hold link tags. A sitemap with xhtml:link entries is the other option. Google's documentation recommends the header approach for non-HTML files.

Does the HTML tag need to be in the head?

Yes. Google's documentation places the link elements in the head of the page. Tags placed in the body are not the documented method, and some HTML parsers will close the head early if invalid markup precedes them, so check the rendered source.

Keep reading