// guides / hreflang and multilingual

Hreflang sitemaps: an XML example, the rules and a generator

A hreflang sitemap puts every language version of a page into your XML sitemap instead of the page head, which keeps big multilingual WordPress sites tidy, but only if every entry carries the full set. Here's what a correct entry looks like, examples for subdomains and country domains, and a free generator that writes the entries for you.

By Muhammad Younus Updated

A frosted glass globe with amber route lines arcing to glass page tiles orbiting around it
the short answer
$ hreflang sitemap ✓ A hreflang sitemap gives every language URL its own url entry, and it's each entry's job to list every version, itself included.✓ It needs the xhtml namespace, absolute canonical URLs, valid language codes and an x-default where one applies.✓ Google treats HTML tags, HTTP headers and the sitemap as equivalent, so use one method, or make sure every method lists exactly the same URLs.
// 01 - when to use it

When should you put hreflang in an XML sitemap?

Hreflang tells Google which URLs are the same page in other languages or regions, and Google accepts it in three places: link tags in the page head, an HTTP header, or the XML sitemap. Its documentation says the three are equivalent, and that using all three at once brings no benefit in Search. A hreflang sitemap suits sites where head tags get unwieldy: a page with ten language versions carries eleven link tags, and a WooCommerce catalogue multiplies that across thousands of products. It's also the route when you can't edit a template's head.

If you only need the markup, open the hreflang sitemap generator and paste your URLs.

When should you put hreflang in an XML sitemap?
MethodWhere it livesBest forHow to check it
HTML link tagsIn each page's headMost WordPress sites; multilingual plugins usually print themView source, or the rendered HTML in URL Inspection
HTTP Link headerIn the server's response headersPDFs and other files with no HTML headThe response headers in your browser's developer tools
XML sitemapIn the sitemap, as xhtml:link linesLarge catalogues, or templates you can't editOpen the sitemap, then crawl it with a tool that reads sitemap hreflang
// 02 - the markup

What does a hreflang sitemap entry look like?

Two language versions of one page, English and Spanish, with English as the x-default. Notice that both url entries carry the same three lines, and that's deliberate.

<?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/tours/</loc>
    <xhtml:link rel="alternate" hreflang="en" href="https://example.com/en/tours/"/>
    <xhtml:link rel="alternate" hreflang="es" href="https://example.com/es/tours/"/>
    <xhtml:link rel="alternate" hreflang="x-default" href="https://example.com/en/tours/"/>
  </url>
  <url>
    <loc>https://example.com/es/tours/</loc>
    <xhtml:link rel="alternate" hreflang="en" href="https://example.com/en/tours/"/>
    <xhtml:link rel="alternate" hreflang="es" href="https://example.com/es/tours/"/>
    <xhtml:link rel="alternate" hreflang="x-default" href="https://example.com/en/tours/"/>
  </url>
</urlset>
// 03 - free tool

Can you generate a hreflang sitemap automatically?

Add each language version of a page below and the generator writes the url entries, full sets included. It flags invalid codes, relative or http URLs and duplicates as you go. It runs in your browser and sends nothing anywhere.

// format: code URL, blank line between pages

Options
// 04 - subdomains and country domains

What does a hreflang sitemap look like for subdomains and country domains?

The rules don't change when versions live on different hosts. Google says alternate URLs don't need to be on the same domain, and its own sitemap example mixes example.com and example.de. What changes is where the file can live: a sitemap normally covers only URLs under the directory it's hosted in, so a single file holding several domains or subdomains needs cross-submission, meaning verified ownership of every site in Search Console, or a Sitemap line in each site's robots.txt pointing at it.

<!-- Subdomains: one page on en.example.com and fr.example.com -->
<url>
  <loc>https://en.example.com/pricing/</loc>
  <xhtml:link rel="alternate" hreflang="en" href="https://en.example.com/pricing/"/>
  <xhtml:link rel="alternate" hreflang="fr" href="https://fr.example.com/tarifs/"/>
  <xhtml:link rel="alternate" hreflang="x-default" href="https://en.example.com/pricing/"/>
</url>
<url>
  <loc>https://fr.example.com/tarifs/</loc>
  <xhtml:link rel="alternate" hreflang="en" href="https://en.example.com/pricing/"/>
  <xhtml:link rel="alternate" hreflang="fr" href="https://fr.example.com/tarifs/"/>
  <xhtml:link rel="alternate" hreflang="x-default" href="https://en.example.com/pricing/"/>
</url>

<!-- Country domains: English for Canada on .ca, German for Germany on .de -->
<url>
  <loc>https://www.example.ca/shop/</loc>
  <xhtml:link rel="alternate" hreflang="en-CA" href="https://www.example.ca/shop/"/>
  <xhtml:link rel="alternate" hreflang="de-DE" href="https://www.example.de/shop/"/>
  <xhtml:link rel="alternate" hreflang="x-default" href="https://www.example.ca/shop/"/>
</url>
<url>
  <loc>https://www.example.de/shop/</loc>
  <xhtml:link rel="alternate" hreflang="en-CA" href="https://www.example.ca/shop/"/>
  <xhtml:link rel="alternate" hreflang="de-DE" href="https://www.example.de/shop/"/>
  <xhtml:link rel="alternate" hreflang="x-default" href="https://www.example.ca/shop/"/>
</url>
// 05 - the rules

What rules must every hreflang sitemap entry follow?

  1. i.

    Declare the xhtml namespace

    The urlset tag needs xmlns:xhtml="http://www.w3.org/1999/xhtml", or the xhtml:link lines aren't valid.

  2. ii.

    Give every version its own url entry

    The English and the Spanish URL each get a url element with their own loc.

  3. iii.

    Repeat the full set in each entry

    Every entry lists every language version, itself included. Missing return links are the first mistake on Google's own list of common hreflang errors: if two pages don't both point to each other, the tags are ignored.

  4. iv.

    Use absolute, canonical URLs

    Full https addresses that return 200, are indexable and canonicalise to themselves. The rules for how hreflang and canonical tags work together apply here too.

  5. v.

    Use valid codes

    An ISO 639-1 language code, optionally with an ISO 3166-1 Alpha 2 region: es, es-MX, en-GB. There's no en-UK, a region code on its own isn't valid, and Google says codes outside those standards, such as es-419, aren't supported.

  6. vi.

    Add x-default where it fits

    For the language selector or the version shown to everyone your tags don't match.

// 06 - size

Which size limits apply when a sitemap carries hreflang?

Hreflang lines make sitemap files bigger, so you'll hit the 50MB file limit sooner. Google says the xhtml:link child elements don't count towards the URL limit, so the 50,000 count is still url entries only.

Which size limits apply when a sitemap carries hreflang?
LimitValueWhat to do about it
URLs per sitemap file50,000 url entriesHreflang lines don't count; split by language or section and list the files in a sitemap index
File size50MB uncompressedHreflang lines do count toward it, so split earlier on sites with many languages
CompressionGzip is allowedThe 50MB limit still applies to the uncompressed file
lastmodOptionalOnly set it when the page really changed, or Google learns to ignore it
// 07 - wordpress

How do WordPress multilingual plugins handle hreflang in sitemaps?

Most WordPress multilingual plugins print hreflang in the page head by default, and it's the SEO plugin that builds the sitemap.

i.

Check what's already printed

View the source of a translated page. If hreflang tags are there, a sitemap version is optional, not required.

ii.

Keep one source of truth

If you add hreflang to the sitemap, it has to match the head tags URL for URL, including x-default.

iii.

Translated sitemaps

The SEO plugin's sitemap should list every indexable translation, or Google finds the versions only through links.

// 08 - common errors

What mistakes stop hreflang in a sitemap from working?

These are the ones I find most on WordPress sites, and none of them throws an error in Search Console. They just don't work.

What mistakes stop hreflang in a sitemap from working?
MistakeWhat happensFix
An entry lists only the other languageGoogle can't confirm the pair, so it may ignore itList every version, itself included, in every entry
Relative or http URLsThe alternates don't match the canonical https pagesUse full https URLs exactly as they're canonicalised
Redirecting or noindexed alternatesGoogle drops the pair it can't indexPoint only at URLs that return 200 and are indexable
en-UK instead of en-GBThe region code isn't valid, so the tag's ignoredUse the ISO 3166-1 code, GB for the United Kingdom
Sitemap and head tags disagreeGoogle gets two different sets for one pagePick one method, or generate both from the same data
// 09 - search console

How do you submit and check a hreflang sitemap in Search Console?

Submitting tells Google where the file is; it doesn't check the hreflang inside it. Google retired the International Targeting report, the one that listed hreflang errors, in 2022, so the last two steps are yours.

  1. i.

    Find the sitemap's address

    WordPress has served a core sitemap index at /wp-sitemap.xml since version 5.5, Rank Math's sitemap index lives at /sitemap_index.xml, and any site can name its sitemaps on a Sitemap: line in robots.txt.

  2. ii.

    Submit it in the Sitemaps report

    Paste the URL into Add a new sitemap and click Submit. You need owner permissions on the property; without them, list the sitemap in robots.txt instead.

  3. iii.

    Read the status

    Success means Google fetched and read it. Has errors means Google fetched it but couldn't parse some entries. If the details page says sitemap could not be read, the fetch failed, so fix the cause shown there and resubmit.

  4. iv.

    Check the hreflang with a crawler

    Crawl the sitemap with a tool that reads sitemap hreflang, and run URL Inspection on a few translated URLs to see the canonical Google chose for each.

  5. v.

    Watch search traffic by country

    Filter the Performance report by country. When hreflang works, searchers in Spain land on the /es/ pages, not the English ones, and that share is the number that should move.

// 10 - diy or help

What can you set up yourself, and when do you need help?

Full hreflang audits and plugin-level fixes are what multilingual SEO services cover, and sitemap structure in general is robots and sitemaps work.

Fine to do yourself

  • A small site with two or three languages
  • Generating entries for a handful of pages
  • Checking one translated page's source

Worth handing over

  • Catalogues with thousands of translated products
  • Head tags and sitemap that disagree
  • Translations Google keeps treating as duplicates

Rather have it fixed for you? See the Hreflang and multilingual service.

Hreflang and multilingual
// questions

What else do people ask about hreflang sitemaps?

Should hreflang go in HTML tags or the sitemap?

Either works: Google says HTML tags, HTTP headers and the sitemap are equivalent. Use head tags when your multilingual plugin already prints them, and the sitemap when the head gets crowded or can't be edited. If you use both, they must list exactly the same URLs.

Are sitemaps still used?

Yes. Google still reads them and says most sites benefit from one, though a sitemap doesn't guarantee every URL gets crawled. A small, well-linked site of about 500 pages or fewer might not need one, but a multilingual site with hreflang in its sitemap does.

Does the order of hreflang entries matter?

No. Google says the order of the xhtml:link lines inside an entry doesn't matter, though keeping one order makes mistakes easier to spot.

Do I need a separate sitemap for each language?

No. One sitemap can hold every language. Splitting by language only helps when files approach the size limits or you want each language's indexing on its own.

Does the x-default URL need its own url entry?

Only if it's a separate page, such as a language selector. If x-default points at one of the language versions, that version's entry already covers it.

// sources

Where do these rules come from?

Google's own documentation, plus what I see on the WordPress sites I work on. Written by Muhammad Younus, a WordPress technical SEO consultant.

// from the blog

A sitemap only helps once Google can read it. Setting up Search Console on WordPress covers where it's submitted, and the URL Inspection tool shows which canonical Google chose for each version.

Muhammad Younus with his arms folded and a relaxed, confident smile
// next step

Want this checked on your own site?

Book a call on Upwork, share the URL and read-only Search Console access, and you'll get back what's actually wrong, ranked by the clicks it's costing.

Book a call on Upwork