// 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.
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.
| Method | Where it lives | Best for | How to check it |
|---|---|---|---|
| HTML link tags | In each page's head | Most WordPress sites; multilingual plugins usually print them | View source, or the rendered HTML in URL Inspection |
| HTTP Link header | In the server's response headers | PDFs and other files with no HTML head | The response headers in your browser's developer tools |
| XML sitemap | In the sitemap, as xhtml:link lines | Large catalogues, or templates you can't edit | Open the sitemap, then crawl it with a tool that reads sitemap hreflang |
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> 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
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> What rules must every hreflang sitemap entry follow?
- 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.
- ii.
Give every version its own url entry
The English and the Spanish URL each get a url element with their own loc.
- 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.
- 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.
- 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.
- vi.
Add x-default where it fits
For the language selector or the version shown to everyone your tags don't match.
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.
| Limit | Value | What to do about it |
|---|---|---|
| URLs per sitemap file | 50,000 url entries | Hreflang lines don't count; split by language or section and list the files in a sitemap index |
| File size | 50MB uncompressed | Hreflang lines do count toward it, so split earlier on sites with many languages |
| Compression | Gzip is allowed | The 50MB limit still applies to the uncompressed file |
| lastmod | Optional | Only set it when the page really changed, or Google learns to ignore it |
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.
Check what's already printed
View the source of a translated page. If hreflang tags are there, a sitemap version is optional, not required.
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.
Translated sitemaps
The SEO plugin's sitemap should list every indexable translation, or Google finds the versions only through links.
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.
| Mistake | What happens | Fix |
|---|---|---|
| An entry lists only the other language | Google can't confirm the pair, so it may ignore it | List every version, itself included, in every entry |
| Relative or http URLs | The alternates don't match the canonical https pages | Use full https URLs exactly as they're canonicalised |
| Redirecting or noindexed alternates | Google drops the pair it can't index | Point only at URLs that return 200 and are indexable |
| en-UK instead of en-GB | The region code isn't valid, so the tag's ignored | Use the ISO 3166-1 code, GB for the United Kingdom |
| Sitemap and head tags disagree | Google gets two different sets for one page | Pick one method, or generate both from the same data |
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.
- 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.
- 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.
- 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.
- 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.
- 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.
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 multilingualWhat 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.
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.
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.

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