Hreflang for a multilingual website: how to set it up without the usual mistakes

Hreflang for a multilingual website: how to set it up without the usual mistakes

Hreflang tells Google which language or regional version of a page to show to whom: a user with a Ukrainian interface gets /ua/, a user with an English one gets /en/. Without this markup a multilingual website often ranks with the "wrong" version: the Ukrainian page shows up in Polish search results while the English one is never treated as a separate page at all. Below we break down what the hreflang attribute actually does, the three ways to declare it, which language and region codes are valid, and where multilingual sites usually break the markup.

SEO specialist checking hreflang tags of a multilingual website in the page source code on a laptop screen

What hreflang does and what it does not do

The hreflang attribute links together pages with the same content in different languages or for different countries. Google reads that link and, for each country or interface language, serves the most appropriate version in search results. The key word here is "serves": all versions must already be indexed, hreflang only helps pick one of them for a specific user.

What hreflang does not do, and this is where most of the confusion lives:

  • It does not redirect. It is not a redirect and not a replacement for automatic language detection on the site. People land where they clicked.
  • It does not translate and does not judge translation quality. If the /en/ page still has Ukrainian text on it, Google will notice, and hreflang will not help.
  • It does not merge versions for ranking purposes. Each page ranks on its own; the markup only removes competition between them for the same user.
  • It does not replace canonical. These are two separate signals, and they only work together and without contradictions.

The practical takeaway is simple. If you have one language and one market, you do not need hreflang at all. You need it when there are at least two language versions, or one language for several countries with different prices or shipping (en-US and en-GB, for instance).

Three ways to declare hreflang: which one to pick

Google accepts the markup from three sources, and all three are equal. Pick one method for the whole site, because mixing them produces conflicts that are hard to track down later.

A link tag in the page head

The most common option for CMS-based sites. On every version of the page, the <head> lists all versions, including the page itself:

<link rel="alternate" hreflang="uk" href="https://site.ua/ua/dostavka/" />
<link rel="alternate" hreflang="ru" href="https://site.ua/dostavka/" />
<link rel="alternate" hreflang="en" href="https://site.ua/en/delivery/" />
<link rel="alternate" hreflang="x-default" href="https://site.ua/ua/dostavka/" />

Upside: visible in the source, easy to eyeball. Downside: on a site with 20,000 pages and five languages every page gets five or six extra lines, so the CMS has to generate this, not a person.

The HTTP Link header

For non-HTML files such as PDF catalogues, the server response carries a header:

Link: <https://site.ua/ua/catalog.pdf>; rel="alternate"; hreflang="uk", <https://site.ua/en/catalog.pdf>; rel="alternate"; hreflang="en"

A rare method, configured at the server level. Nobody uses it for regular pages.

Markup in sitemap.xml

Every <url> in the sitemap is extended with <xhtml:link> elements listing all versions. An example for one page:

<url><loc>https://site.ua/ua/dostavka/</loc><xhtml:link rel="alternate" hreflang="uk" href="https://site.ua/ua/dostavka/"/><xhtml:link rel="alternate" hreflang="en" href="https://site.ua/en/delivery/"/></url>

Upside: page HTML stays lean, everything sits in one file that is easy to generate and validate with a script. Downside: the sitemap grows, and on large catalogues you end up splitting it into several files. At Query we tend to choose the sitemap for stores with tens of thousands of pages, while for small service sites the link tag in the head is more convenient.

x-default and reciprocity: two rules the markup cannot work without

Reciprocity means this: if page A points to page B as its English version, page B must point back to A as the Ukrainian version. Google ignores a one-way link completely, and this is the single most common reason behind "we added hreflang and nothing changed". You have to check pairs, not individual pages.

x-default says which version to show to people whose language and country match none of the listed ones. For a Ukrainian site with uk/ru/en, it makes sense to point x-default either to the English version (for foreign visitors) or to a language selector page if one exists. Pointing x-default to the Ukrainian version is also acceptable: then undetermined users see the primary version. What matters is that there is exactly one x-default and it leads to a real page returning a 200 code.

Which language and region codes to use

The language is written in ISO 639-1 (two letters), the region in ISO 3166-1 Alpha-2 after a hyphen. A region without a language is not allowed: hreflang="UA" is invalid, you need uk-UA. The most frequent mistake involves Ukrainian: its code is uk, not ua. The value ua is a domain, not a language, and Google does not recognise it.

CodeMeaningWhen to use
ukUkrainian, any countryStandard for the Ukrainian version
uk-UAUkrainian for UkraineOnly with another Ukrainian version
ruRussian, any countryVersion not tied to a country
enEnglish, any countryOne English version for all
en-GB, en-USEnglish for the UK / USDifferent prices, currency, delivery
x-defaultVersion "for everyone else"Once per set

If you have a single English version, write plain en. Adding a region "just in case" is a bad idea: en-US narrows the audience, and a British user formally falls outside it, even though Google does try to pick the closest language.

Leave an application

Enter your name and email, our managers will contact you as soon as possible.
By submitting the form you agree to our privacy policy.

Common hreflang mistakes and how to fix them

In our experience, on most sites that come to us for technical SEO, the markup is either broken or missing entirely. The mistakes repeat from site to site.

MistakeConsequenceFix
No return linkGoogle ignores the pairOne list of versions on every page
Points to a non-canonical pageConflicting signalsCanonical URLs only
Relative URLsInvalid markupAbsolute URLs with the domain
Conflict with canonicalA version drops outEach version canonical to itself
Several languages on one URLVersions are not linkedOne language = one URL
Code ua instead of ukVersion without markupReplace the code in the template
Points to noindex, 404, redirectThe pair breaksCheck versions before output
No translation, but hreflangLink to a missing pageOnly really translated pages
Marketer comparing language versions of a website page on two monitors in an office

How to check that hreflang works

  1. Look at the page source or the sitemap and make sure the set of versions is identical on each of them.
  2. Run the site through a crawler (Screaming Frog, Sitebulb, Serpstat Audit): they show missing return links, invalid codes and hreflang pointing to non-canonical addresses in one report.
  3. Google Search Console has not had a dedicated hreflang report for a long time, but URL Inspection shows which version Google treats as canonical and whether the page is indexed. If the canonical is not what you expected, look for a conflict with canonical.
  4. Type the query into Google over a VPN or with the parameters &gl=gb&hl=en and see which version appears. This is the most honest test.

The official requirements and examples for all three methods are collected in Google's documentation on localized versions. Where a validator and the documentation disagree, Google is right.

A multilingual site for Ukraine: uk, ru, en

The typical setup for a Ukrainian business: Ukrainian as the primary language, Russian for part of the audience, English for export or foreign clients. A few practical recommendations we give in such projects.

  • Make Ukrainian the primary version, either without a prefix or with /ua/, but consistently across the whole site. A mixed structure where some pages have the prefix and others do not destroys the markup.
  • Label the Russian version ru with no region. ru-UA is justified only when there is another ru version for a different country.
  • The English version has to be genuinely translated, with localised prices and contacts. Google sees machine translation with half the strings still in Ukrainian, and such a version does more harm than good. If there is no in-house resource, it is easier to order English copywriting up front than to redo it later.
  • Point x-default to English if you count on foreign visitors, or to Ukrainian if the site serves the domestic market.
  • Exclude untranslated pages from the hreflang set instead of linking to the Ukrainian page disguised as English.

Where to start

  1. List all language versions and make sure each lives on its own URL, returns 200 and is canonical to itself.
  2. Pick one markup method: the link tag in the head for small sites, the sitemap for large catalogues.
  3. Generate the sets from a single source so that reciprocity is guaranteed rather than "remembered".
  4. Add x-default and double-check the codes: uk, not ua.
  5. Run a crawler, fix the errors, and check country-level search results in three to four weeks.

Hreflang does not add rankings, it removes losses. When the right version is shown to the right user, CTR grows and the "wrong language" bounces disappear. For a site with two or three languages this is one or two days of developer work plus half a day of checks, and that investment pays back reliably.

Other articles

Other services

Get in touch
Messengers