---
title: "Hreflang: a practical guide with WordPress examples"
description: "What hreflang does, the codes Google accepts, where the tags go, a worked WordPress example with subdirectories, the common mistakes and a checklist."
url: "https://www.langrelay.com/guides/hreflang"
---

1. [Home](https://www.langrelay.com/)
2. [Guides](https://www.langrelay.com/guides)
3. Hreflang: a practical guide with WordPress examples

GuideMultilingual SEO

# Hreflang: a practical guide with WordPress examples

What hreflang does, the codes Google accepts, where the tags go, a worked WordPress example with subdirectories, the common mistakes and a checklist.

[Chris Jayden](https://www.langrelay.com/about)

Founder

Published

6 October 2026

Reading time

8 min read

![Two neighbours lean on a gate by golden wheat fields while a child runs along the path to a barn whose doors carry leaf tiles.](https://www.langrelay.com/_emdash/api/media/file/01M4ETF1VRM80EF3PQS0ZW2969.webp)

On this page

1. What does hreflang do?
2. The syntax of one tag
3. Language and region codes Google accepts
4. Three places to declare the set
5. The rules that make a set count
6. Every version lists itself
7. Every link is returned
8. The set is identical on every version
9. Each URL is final and indexable
10. Unmatched visitors get a fallback
11. Tags sit inside a valid <head>
12. A worked example: WordPress in subdirectories
13. Common mistakes, and what each one breaks
14. How do you check hreflang on a live page?
15. How LangRelay handles hreflang
16. Further reading in this cluster

Hreflang is an HTML attribute that tells search engines which URLs are language or regional versions of the same page. With it, a searcher in Germany gets your German page in the results and a searcher in Spain gets the Spanish one. You add it as a set of `<link rel="alternate">` tags in each page's `<head>`, as an HTTP header, or as entries in an XML sitemap. It does not translate anything and it does not tell Google what language a page is in. It only connects versions that already exist.

## What does hreflang do?

Google asks for hreflang "so that we can understand that these pages are localized variations of the same content". Its documentation, last updated on 2026-09-21, is direct about one limit: "Google doesn't use hreflang or the HTML lang attribute to detect the language of a page; instead, we use algorithms to determine the language." The companion page on multilingual sites adds that Google reads the visible content of the page for this, and ignores the URL as well.

Once Google knows that `/pricing/` and `/de/pricing/` are the same page in two languages, it can swap one for the other in the results depending on the searcher's language and location. If the German page is thin or half in English, hreflang will not save it, because Google still judges the page on what it reads.

Google also notes that it may find alternate versions without any annotation. Declaring them yourself is safer, and the tags cost little once your setup generates them.

## The syntax of one tag

Each tag names one version of the page:

```
<link rel="alternate" hreflang="de" href="https://www.harbourcoffee.example/de/pricing/">
```

`rel="alternate"` says the linked URL is another version of this document. `hreflang` holds a language code, optionally followed by a region code, or the reserved value `x-default`. `href` is the full URL of that version, including `https://`. Google's guidelines say alternate URLs "must be fully-qualified", so `/de/pricing/` on its own is not enough.

A page carries one tag per version, itself included, and every version of the page carries the same set.

## Language and region codes Google accepts

The value has one code, or two joined by a hyphen:

- The first part is a language in ISO 639-1, the two-letter list: `en`, `de`, `fr`, `nl`, `pt`, `tr`.
- The optional second part is a region in ISO 3166-1 Alpha 2: `GB`, `US`, `AT`, `CH`, `BR`.
- Case does not matter to Google, though writing the region in capitals (`en-GB`) follows the ISO convention.
- A script subtag from ISO 15924 is allowed, for example `zh-Hant` or `zh-Hans` for Chinese, optionally with a region after it.

Four values go wrong often enough to list:

| Value | Problem | Use instead |
| --- | --- | --- |
| `be` | Meant as Belgium, but `be` is Belarusian. A region cannot stand alone. | `nl-BE`, `fr-BE` or `de-BE` |
| `en-UK` | `UK` is a reserved code, and Google says it has no effect. | `en-GB` |
| `es-419` | `419` is not an ISO 3166-1 Alpha 2 region, and Google names `es-419` as unsupported. | `es-MX`, `es-AR`, or plain `es` |
| `en_GB` | The codes are joined with `_`; Google's format separates them with a dash. | `en-GB` |

When you have several regional versions of one language, Google suggests a catch-all for everyone else who speaks it: a plain `en` page beside `en-GB` and `en-AU`, for example. The catch-all can be one of the regional pages if you have no generic version.

## Three places to declare the set

Google accepts hreflang in three forms and treats them as equal:

1. Link tags in the HTML `<head>`, the usual choice for web pages.
2. An HTTP `Link:` header, for files that have no `<head>`, such as PDFs.
3. `<xhtml:link>` entries inside each `<url>` of an XML sitemap.

Its documentation says you can combine them but "there's no benefit in Search", and that managing three implementations is harder than managing one. Pick the one your stack produces reliably. If you are deciding between the head and the sitemap, the article on [hreflang in XML sitemaps](https://www.langrelay.com/blog/hreflang-xml-sitemap) goes through when each fits.

## The rules that make a set count

### Every version lists itself

The German page carries a tag pointing at the German page. Google's wording is "Each language version must list itself as well as all other language versions." The article on [self-referencing hreflang and x-default](https://www.langrelay.com/blog/self-referencing-hreflang-x-default) covers the edge cases.

### Every link is returned

If the English page names the German page as its `de` alternate, the German page has to name the English page back. When two pages do not point at each other, Google ignores the tags. This stops another site from claiming to be a version of yours.

### The set is identical on every version

Each version prints the same list in any order, which is the easiest way to satisfy the first two rules.

### Each URL is final and indexable

Point every tag at the URL you want in the results: the HTTPS version, with your usual trailing-slash convention, returning 200 rather than a redirect. Google's canonical documentation asks for HTTPS URLs in hreflang annotations and says it prefers URLs that sit in an hreflang cluster when it chooses a canonical. How the two tags interact is the subject of [hreflang and canonical tags](https://www.langrelay.com/blog/hreflang-and-canonical-tags).

### Unmatched visitors get a fallback

`x-default` names the page for searchers whose language you do not cover. Google introduced it in 2013 for language selectors and home pages that adapt to the visitor, and still describes it as working best on those.

### Tags sit inside a valid `<head>`

Google requires the link tags inside a well-formed head section and suggests pasting the rendered source into an HTML validator when in doubt. It also asks you not to combine `hreflang` with other attributes such as `media` on one tag.

## A worked example: WordPress in subdirectories

Take a coffee roaster's WordPress site written in English, with German and Dutch versions under `/de/` and `/nl/`, and a separate UK English version under `/en-gb/` because UK customers see prices in pounds. The pricing page exists in all four. This is the `<head>` of the German version:

```
<html lang="de">
<head>
  <title>Preise und Abos | Harbour Coffee</title>
  <link rel="canonical" href="https://www.harbourcoffee.example/de/pricing/">
  <link rel="alternate" hreflang="en" href="https://www.harbourcoffee.example/pricing/">
  <link rel="alternate" hreflang="de" href="https://www.harbourcoffee.example/de/pricing/">
  <link rel="alternate" hreflang="nl" href="https://www.harbourcoffee.example/nl/pricing/">
  <link rel="alternate" hreflang="en-GB" href="https://www.harbourcoffee.example/en-gb/pricing/">
  <link rel="alternate" hreflang="x-default" href="https://www.harbourcoffee.example/pricing/">
</head>
```

Line by line:

- `lang="de"` on the `<html>` element declares the page language for browsers and screen readers. It is a separate attribute from hreflang with a separate audience; [hreflang vs the HTML lang attribute](https://www.langrelay.com/blog/hreflang-vs-html-lang) explains both.
- The canonical names the German page itself. Each language version is its own canonical.
- Four language tags list all versions, including this one.
- `x-default` points at the English original, so a searcher in Brazil or Japan lands on the English page.
- The English original appears twice, as `en` and as `x-default`, which is allowed: Google says `x-default` can be used for any page.

The English, Dutch and UK pages carry the same five alternate lines, each with its own canonical and its own `lang`.

Now suppose the Dutch translation of a new page, `/brewing-guide/`, is not finished. The set for that page has three alternates plus `x-default`, and `nl` is missing on every version. Listing a Dutch URL that redirects, shows English text or returns 404 would break the return-link rule and send Dutch searchers to a page that does not exist in Dutch. Add `nl` to the set on the day the Dutch page goes live.

On WordPress, hreflang usually comes from the translation plugin, sometimes together with an SEO plugin that also writes tags into the head. The article on [hreflang in WordPress](https://www.langrelay.com/blog/hreflang-wordpress) covers how to see which plugin printed what.

## Common mistakes, and what each one breaks

| Mistake | What happens | Fix |
| --- | --- | --- |
| A version does not list itself | The set is incomplete on that page | Print the full set on every version |
| No return tag on one version | Google ignores the pair | Generate the set from one list, not per page |
| Relative URLs (`/de/`) | The tag is invalid | Use full `https://` URLs |
| `en-UK`, `be`, `es-419` | That code, or the whole tag, has no effect | Use ISO 639-1 plus ISO 3166-1 Alpha 2 |
| A URL in the set redirects or returns 404 | The target cannot be shown | List the final URL, or drop the version |
| A version in the set is `noindex` | It cannot appear in results | Remove it from the set until it is indexable |
| Tags outside a well-formed `<head>` | Google expects them inside it | Validate the rendered source |
| `hreflang` on the canonical tag | Google ignores that canonical | Keep canonical and alternates as separate tags |

The last row comes from Google's canonical documentation: `rel="canonical"` annotations that carry `hreflang`, `lang`, `media` or `type` attributes are not used for canonicalization.

## How do you check hreflang on a live page?

Search Console's International Targeting report has been deprecated. The help page that says so adds that Google "will continue to support and use hreflang tags on your pages", so the tags still count and checking them is up to you:

1. Fetch the raw HTML, not the page your browser rendered: `curl -s https://www.harbourcoffee.example/de/pricing/ | grep -i hreflang`. If the tags appear only after JavaScript runs, find out whether your setup prints them on the server.
2. Confirm every version lists itself and every other version, with the same set on each.
3. Request each `href` and confirm it returns 200 without a redirect.
4. Compare each version's canonical with its own URL.
5. Check the codes against the table above.
6. In Search Console, run URL Inspection on an indexed translated URL and compare "User-declared canonical" with "Google-selected canonical". The help page says the Google-selected value can only be read from indexed data; the live test cannot predict it.

For more than a handful of pages, Google's own documentation names two third-party tools, a tag generator by Aleyda Solis and a single-page tester from Merkle, and says that Google does not maintain or check them. A site crawler that reads hreflang does the same job across the whole site.

## How LangRelay handles hreflang

LangRelay's WordPress plugin serves translated pages from your own WordPress, with each language in a subdirectory: `/de/`, `/nl/`, `/en-gb/`. The hreflang set comes from LangRelay and the plugin prints it as given. It contains the original page, every language in which that page has an approved and live translation, and `x-default` on the original's URL. The same set appears on the original and on every translated version, so return links hold by construction.

The codes come from one place. A target language in LangRelay is a BCP 47 tag such as `de` or `en-GB`, and the hreflang value and the `lang` attribute are that tag, while the URL prefix is its lowercase form.

A language joins a page's set once that page's translation is live, and until then the set leaves it out. Once a language is live on at least one page, a page with no approved translation yet answers under that language's prefix with the original, and that response carries no hreflang set. After each publish, LangRelay fetches the translated page and checks its `lang`, its canonical, its own hreflang entry and the `x-default` entry. A page that contradicts what was published is flagged on the release.

The plugin prints hreflang in the head only and does not generate a multilingual sitemap. LangRelay's script embed for non-WordPress sites translates in the browser, so crawlers see the original language and no hreflang is printed for it. The [multilingual SEO](https://www.langrelay.com/multilingual-seo) page covers the rest of what the plugin does for search, and if you want to see the output on your own site, [book a demo](https://www.langrelay.com/book-a-demo).

## Further reading in this cluster

- [Hreflang and canonical tags together](https://www.langrelay.com/blog/hreflang-and-canonical-tags)
- [Self-referencing hreflang and x-default](https://www.langrelay.com/blog/self-referencing-hreflang-x-default)
- [Hreflang in XML sitemaps](https://www.langrelay.com/blog/hreflang-xml-sitemap)
- [Hreflang vs the HTML lang attribute](https://www.langrelay.com/blog/hreflang-vs-html-lang)
- [Hreflang in WordPress](https://www.langrelay.com/blog/hreflang-wordpress)
- [Subdomain vs subdirectory for a multilingual website](https://www.langrelay.com/blog/subdomain-vs-subdirectory-multilingual-seo)
- [Does machine translation hurt SEO?](https://www.langrelay.com/blog/does-machine-translation-hurt-seo)

## Sources

The pages this one cites, with the day each was read.

1. 01[Localized versions of your pages (Google Search Central, last updated 2026-09-21)](https://developers.google.com/search/docs/specialty/international/localized-versions)developers.google.com, checked 6 October 2026
2. 02[Managing multi-regional and multilingual sites (Google Search Central, last updated 2025-12-10)](https://developers.google.com/search/docs/specialty/international/managing-multi-regional-sites)developers.google.com, checked 6 October 2026
3. 03[How to specify a canonical with rel="canonical" and other methods (Google Search Central, last updated 2026-07-10)](https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls)developers.google.com, checked 6 October 2026
4. 04[The International Targeting report is deprecated (Search Console Help)](https://support.google.com/webmasters/answer/12474899)support.google.com, checked 6 October 2026
5. 05[URL Inspection tool (Search Console Help)](https://support.google.com/webmasters/answer/9012289)support.google.com, checked 6 October 2026
6. 06[Introducing "x-default hreflang" for international landing pages (Google Search Central Blog, 2013-04-10)](https://developers.google.com/search/blog/2013/04/x-default-hreflang-for-international-pages)developers.google.com, checked 6 October 2026

[Chris Jayden](https://www.langrelay.com/about)

Founder, LangRelay

Chris Jayden is the founder of LangRelay. Chris has worked on websites of every size, from large e-commerce stores to small sites with a handful of pages, and started LangRelay after years of translating them the hard way.

On this page

1. What does hreflang do?
2. The syntax of one tag
3. Language and region codes Google accepts
4. Three places to declare the set
5. The rules that make a set count
6. Every version lists itself
7. Every link is returned
8. The set is identical on every version
9. Each URL is final and indexable
10. Unmatched visitors get a fallback
11. Tags sit inside a valid <head>
12. A worked example: WordPress in subdirectories
13. Common mistakes, and what each one breaks
14. How do you check hreflang on a live page?
15. How LangRelay handles hreflang
16. Further reading in this cluster

Share

- [Share on LinkedIn (opens in a new tab)](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fwww.langrelay.com%2Fguides%2Fhreflang)
- [Share on X (opens in a new tab)](https://x.com/intent/post?url=https%3A%2F%2Fwww.langrelay.com%2Fguides%2Fhreflang&amp;text=Hreflang%3A%20a%20practical%20guide%20with%20WordPress%20examples)

See it on your site

A 30-minute walkthrough on one of your pages.

[Book a demo](https://www.langrelay.com/book-a-demo)

- hreflang
- international SEO
- multilingual SEO
- WordPress

## Keep reading

- Article
  ### [Hreflang vs the HTML lang attribute: what each one does](https://www.langrelay.com/blog/hreflang-vs-html-lang)
  The lang attribute says what language this page is in; hreflang points to the page in other languages. Who reads each, valid values, and both in one head.
- Article
  ### [Hreflang in WordPress: how plugins print it and how to check](https://www.langrelay.com/blog/hreflang-wordpress)
  Where hreflang comes from on WordPress, what WPML, Polylang, TranslatePress and Weglot print by default, how Yoast SEO and Rank Math fit in, and how to check.

Book a demo

## See LangRelay on your own site

Book 30 minutes with the team. We translate one of your pages live and walk through review, publishing and multilingual SEO.

[Book a demo](https://www.langrelay.com/book-a-demo)[See pricing](https://www.langrelay.com/pricing)
