Hreflang sitemaps: putting the hreflang attribute in the XML instead of the head, and the hreflang best practices that follow

Updated

There are three places the hreflang annotation can live: in the head of every page, in the HTTP headers, or in an XML sitemap. They are equivalent to a search engine and very different to maintain. On a site with a few hundred pages in four languages, the sitemap route is usually the one that survives, because it is one file your build writes rather than an edit that has to happen on every template in every locale.

What the sitemap actually has to contain

One url element per page per locale, and inside each one an xhtml:link for every language version of that page including itself. That is the part people get wrong: the sitemap does not list each page once with its translations, it lists each version, and each version carries the complete set. A page in four locales therefore appears four times, and each appearance carries four or five links.

Why the sitemap route wins on a real site

Because it is generated. A head-tag implementation depends on every template rendering the right set for the page it is on, which is fine until a marketing page is built by hand or a locale is added and three templates are missed. A sitemap is written by the same build that knows which pages exist, so the tags are as complete as the site's own knowledge of itself.

The practices that keep it right

Absolute URLs including the scheme, one sitemap set kept in step with the pages that actually exist, and a regeneration on every deploy rather than on a schedule. Where a page exists in only some locales, list the versions that exist and nothing else; a link to a URL that returns a 404 is worse than a missing link because it takes the set down with it.

How big it gets

Multiply your pages by your locales for the number of url entries, then by the locales again for the links inside them. That is the number that decides whether you hand-maintain anything, and it grows quadratically rather than linearly. The free map on this site works it out from your own page and locale counts.

What one url entry looks like

For a pricing page in English, German and French, the English entry carries the English loc, then three xhtml:link elements: rel alternate, hreflang en, href the English URL; the same with de and the German URL; the same with fr and the French URL; and optionally an x-default pointing at the selector. The German entry carries the German loc and the same three links in the same set; so does the French. Three entries, nine links, one set. Add a fourth locale to that page and it becomes four entries and sixteen links, which is the quadratic growth the map on this site counts. The absolute URLs, the scheme, and the exact same set in each entry are what a validator checks, and what a hand-maintained sitemap gets wrong by the second edit.

Sitemap size, index files and the fifty-thousand limit

A sitemap file holds at most fifty thousand url entries, and a multilingual site reaches that sooner than a monolingual one because every version is an entry. A thousand pages in six locales is six thousand entries and thirty-six thousand links, comfortably inside one file; ten thousand pages in six locales is sixty thousand entries and needs a sitemap index with the files split, usually by locale, each still carrying the full cross-locale set for its pages. Splitting by locale is the sensible partition because a locale's pages change on the locale's own schedule, and the build regenerates the file whose pages changed. The map on this site tells you the entry and link counts before the build does.

Checking a generated sitemap without reading it

Nobody reads thirty-six thousand links. The checks are counts and samples: the number of entries equals the number of page-locale pairs the record says exist; every href in the file returns 200; every set is symmetric, so a URL that appears as an alternate in an entry has an entry of its own carrying the same set; and a random sample of twenty entries, opened in a browser, are the pages they claim to be in the language they claim. The record is what makes the first check possible, and the first check is the one that finds the template somebody added by hand.

Questions people ask about hreflang sitemaps

Is a sitemap better than head tags for hreflang?

Not to a search engine; they are treated the same. It is better to maintain on any site where the pages are generated, which is most of them.

Can we mix the two?

You can, but do not. Two sources of truth for the same annotation is how a site ends up with sets that disagree, and disagreeing sets are ignored.

How often should the sitemap be regenerated?

On every deploy that adds, removes or translates a page. A nightly job is a compromise that leaves the tags wrong for up to a day.

Does the sitemap replace the canonical tag?

No. The canonical still goes in the head of each page, pointing at itself; the sitemap carries only the hreflang alternates. The two answer different questions and the canonical has no sitemap form.

Sources

Related answers

Keep the pages in Hreflangly ProStart Hreflangly Pro, $17 a month