In 2018, John Mueller said this on Twitter (now X):

“TBH hreflang is one of the most complex aspects of SEO (if not the most complex one). Feels as easy as a meta-tag, but it gets really hard quickly.”

Nothing has changed after 6 years: hreflang remains still one of the most complex aspects of SEO. Proof of this are the very frequent questions I publicly or privately receive about it from other SEOs, and the time needed to debug its implementation on a multilingual/multi-country website.

For these reasons, I think that this guide can be useful for all SEOs searching for answers to the most common questions about hreflang. And not only for people starting their adventure in the SEO industry but also for many senior ones who still find themselves scratching their heads when it comes to this aspect of International SEO.

I recommend you save the link to this page also because I will update this guide whenever something new about hreflang is communicated by Google and other search engines, which use it (i.e.: Bing).

Hreflang: definition.

Hreflang=”x” is an attribute that indicates to Google (and other search engines) what URL to serve to users searching in a given language and – if explicitly indicated – from a given country (hreflang=”x-X”).

For instance, if domain.es targets Spanish-speaking users in Spain and domain.co.uk targets English-speaking ones in Great Britain, then the following hreflang annotations will specify these recommendations to Google:

  • <link rel=”alternate” href=”https://domain.es/” hreflang=”es-ES” />
  • <link rel=”alternate” href=”https://domain.co.uk/” hreflang=”en-GB” />

Hreflang: the elements composing it.

Let’s see what elements compose an hreflang annotation:

<link rel=”alternate” href=”https://domain.es/” hreflang=”es-ES“ />

  1. The hreflang is a rel=”alternate”, which means that it always indicates an alternative URL to the one the same alternate annotation is implemented in.
  2. The href element indicates the alternative URL.
  3. The hreflang attribute always presents the language or the language. If needed, it also indicates the country targeted by the page indicated in the href field.
  4. To indicate the targeted language, we must use the ISO 639-1 language codes.
  5. To indicate the country we target, we must use the ISO 3166-1 Alpha 2 country codes.

However, Google advises us that there is an exception to point 4:  in fact, we can use the ISO 15924 to indicate that we are using a specific language script on our page and that we can use this ISO code in combination with a country one.

This means that it is correct to have an hreflang like hreflang=”zh-Hans” for telling Google that we are using Simplified Chinese instead of Traditional Chinese (zh-Hant).

Nevertheless, even if Google admits this exception, this does mean that we can use an ISO 15924 language script code like es-419 (Spanish for Latin America), even if Google itself uses it, for instance, in theStructured data markup that Google Search supports“:

Example of hreflang implementation by Google with "incorrect" use of hreflang="es-419" for Latin American Spanish.

Why? Because it will not consider it, as explained several times by Googlers.

Remember: avoid overcomplicating the implementation of hreflang. This markup is already complicated enough without us making it even more complicated.

When the hreflang should be used?

Google is very precise in telling when we should use the hreflang:

  1. When our website has a full translation version (i.e.: www.domain.com is in English and www.domain.com/es/ is its Spanish version).
  2. When our website has different versions in the same language and targets different countries, hence there are very slight differences mainly due to localization (i.e.: www.domain.com is the American-English version of our website and www.domain.co.uk is the British-English one).
  3. When we offer the same content to different audiences but:
      • the main content is always in the same language despite the specific version targeting an audience using a different one.
      • the template is translated into the language used by the audience we are targeting.
      • and/or the page has UGC content in the language used by the audience we are targeting.

This last case – as Google says – may happen on websites like forums… but another example can be a blog that exists only in English but – for some weird reasons that should be addressed – it is also republished in other language versions (i.e.: the Spanish one).

ALWAYS FOLLOW THIS RECOMMENDATION: The hreflang only must be implemented on URLs that respond 200 (OK), are indexable, and are not blocked via robots.txt.

Moreover, ideally the URLs should always be canonical URLs.

As you will see later in this guide, practically every hreflang mistake is caused by its implementation in non-200, not indexable, not crawlable and not canonical URLs, therefore try always to stick to this recommendation.

Reality check: the page I linked from Google is very old (I mean, Maile Ohye exited from Google in 2017), which means that many things have changed since it was published.

The most important change is related to point 1: the recommendation to implement the hreflang for multilingual (aka, languages only) websites. Google has improved very much in understanding if a query is in one language or another, therefore it will serve English content in your search in English and Italian if you search in Italian. TL;DR: with very few exceptions, using the hreflang for multilingual-only websites is overcomplicating International SEO.

How to implement the hreflang?

Hreflang is a single URL-based signal; therefore it must be implemented URL by URL. In other words, we cannot simply tell Google: “All the URLs in the /es/ subfolder target the Spanish-speaking users and, instead, all URLs under /de/ target German-speaking ones”.

There are 3 ways (+1) to implement the hreflang:

  1. In the <head> section of a page.
  2. Via Sitemaps.xml.
  3. In the HTTP Header for non-HTML files like, for instance, PDFs.
  4. Alternative (+1) way: using Tag Manager.

Implementing the hreflang in the <head> section of the HTML.

This is the best solution if the number of versions is relatively few, and if our CMS allows us to modify the hreflang easily whenever necessary.

This is how it would look on a standard International SEO setup that consists of two ccTlds:

  1. <link rel=’’alternate’’ href=‘’https://dominio.it/’’ hreflang=’’it-IT’’ />
  2. <link rel=’’alternate’’ href=‘’https://dominio.es/’’ hreflang=’’es-ES’’ />

However, things can be a little more complicated in these two cases:

  • m. mobile subdomains (some still exist):

hreflang implementation for independent mobile websites (m. subdomains).

Source: Aleyda Solís

  • AMP websites:

Hreflang implementation for AMP webistes

Source: Sergio Redondo

Implementing the hreflang in the XML Sitemap.

This is the ideal solution for very large websites with many language or country versions.
It is also optimal when we cannot access the code or the direct implementation in the <head> is complicated.

This is how it would look on a standard International SEO setup that consists of three “country-level” subfolders (en-US, en-GB and en-AU”)

Hreflang implementation in XML Sitemap

I recommend you look at the official documentation from Google and see also the sources linked by it.

Implementing the hreflang in the HTTP Header.

This is the method to use for all non-HTML document URLs, such as PDF, DOC, XLSX, etc. etc.
For example, in the case of having a PDF with the characteristics of a product but in different language or country versions for reasons of localization, legislation or other.

Here below is an example for marking up the HTTP Headers of three URLs (PDF in global English, PDF in German for Switzerland, PDF in global German):

Hreflang implementation in HTTP header

Implementing the hreflang using Google Tag Manager.

A few years ago, Eoghan Henn wrote a very detailed article explaining how to use Google Tag Manager for implementing hreflang.

This is a solution for when none of the standard implementations is possible (aka: no access to the code, no possibility of creating and submitting an XML Sitemap).

However, you should also be aware that this solution – which is also used for other things, such as injecting structured data into the code – is somewhat “fragile” and can break.
My advice is to use it only in case of extreme necessity and/or to demonstrate to our clients/managers the importance of implementing hreflang tags (this time using a standard method).

The hreflang=”X-Default”.

One of the things for which the Internet should thank SEO professionals is standardization.

A good example is represented by the hreflang=”X-Default”.

When it was introduced in 2013, Pierre Farr of Google was saying to use it only:

  1. For the country selector page, if exists.
  2. For homepages that dynamically alter their contents based on a user’s perceived geolocation or the Accept-Language headers.

However, International SEOs never used for those reasons (at least not only), but to indicate a wildcard URL that Google should show to all those users who perform a search in a language or from a country not explicitly targeted by any version of our website, and for whom the site might be relevant anyway.
For example, if we are a SAAS and our site has an English, Spanish, French, German and Chinese version, indicate as “x-default” the home page of the English version for those Italian users who search for us with our brand, because – supposedly – Italians understand English better than, I don’t know, Chinese.

After many years, in 2023, Gary Illyes of Google communicated that Google was accepting this widely more popular use of the x-default.

Common hreflang implementation mistakes.

#1 Not using the self-referential hreflang annotation.

We must always implement the self-referral hreflang annotation and not only the ones pointing to the alternative language and country or only-language URLs.

For instance, we have a website, whose root presents the en-US version and that has a subfolder dedicated to target en-AU.

The hreflang of the home page will be this:

<link rel=”alternate” href=”https://www.domain.com/” hreflang=”en-US” /> [self-referential hreflang]
<link rel=”alternate” href=”https://www.domain.com/en-au/” hreflang=”en-AU” [alternative URL for Australian English-speaking users]

And vice versa in https://www.domain.com/en-au/:

<link rel=”alternate” href=”https://www.domain.com/” hreflang=”en-US” /> [alternative URL for English-speaking users in the US]
<link rel=”alternate” href=”https://www.domain.com/en-au/” hreflang=”en-AU” /> [self-referential hreflang]

#2 “Forgetting” the return hreflang annotation (no-return mistake).

If the Spanish URL A suggests URL B as its alternative German version, then URL B must suggest back URL A as its alternative version for Spanish-speaking users.

This is a basic rule of every “alternate” and one of the implementation mistakes that Google explicitly indicate in its guidelines.

If this rule is not respected, Google will not consider the specific hreflang annotation, hence it will ignore it with obvious highly probable misalignment problems in the regional SERPs.

#3 Not using the ISO codes correctly.

This kind of mistake is more common than we may think.

Examples:

  • “en-UK” (UK is not a valid ISO 3155-1 Alpha 2 country code).
  • eng-GB (eng is not a valid ISO 639-1 language code)
  • GB” (you cannot indicate only the country code ISO value).
  • GB-en” (you cannot invert the ISO codes).
  • any other possible combination of the mistakes here above.

#4 Indicating as alternate URLs that respond with 4XX, 5XX or 3XX server status.

All the URLs that we indicate as alternatives must respond 200 (OK).

#5 Indicating alternate URLs that have the meta robots (HTML) or the X-Robots tag (HTTP Header) set as “noindex”.

Not only the alternative URLs must respond 200 (OK), but also they must be indexable.

#6 Indicating alternate URLs that are blocked via robots.txt.

The reason why this is a mistake is very logical: if we indicate as an alternative a URL, whose access is blocked to crawlers, then the crawlers cannot see its code including the hreflang annotations it may have. In other words, this is a sort of expanded version of the no-return mistake.

#7 Indicating canonicalized URLs as alternates.

The hreflang must always indicate the canonical URL.

For example, the URL: https://www.dominio.com/widget?color=blue is canonicalized toward https://www.dominio.com/widget.

Therefore, the hreflang annotation of https://www.dominio.com/widget?color=blue must be these:

  1. <link rel=“alternate” href=“https://www.dominio.com/widget”> hreflang=“es” />
  2. <link rel=“alternate” href=“https://www.dominio.com/en/widget”> hreflang=“en” />
  3. <link rel=“alternate” href=“https://www.dominio.com/de/widget”> hreflang=“de” />
  4. <link rel=“alternate” href=“https://www.dominio.com/fr/widge”> hreflang=“fr” />
Beware that rel=”canonical” and the hreflang serve two very different purposes.

  • The rel=”canonical” indicates to Google what URL is the one it must index in a list of “duplicates” or “substantially duplicated” pages.
  • The hreflang indicates to Google what URL to present to users searching for a given language or in a given language and from a given country.

However, the classic question is: “What if I have a page for en-GB that is practically identical to the original version targeting en-US?”.

Formally, in these cases, Google would recommend not canonicalising the en-GB page toward the en-US. The duplication problem would still exist, but the hreflang would “somehow” save it and still present the correct URLs in their locales.

Nevertheless, if despite this you still see misalignments in the local SERPs because of the complete or substantial duplication between pages targeting different countries in the same language, then you can try the so-called “canonical trick”.

The canonical trick has existed since the very beginning of the hreflang implementation (2011) and practically consists of not following Google’s best practice of not canonicalizing duplicate cross-versions URLs. This article Glenn Gabe wrote in 2018 about the “canonical trick” is still a valid source, if you are interested in it.

As a final note, though, it is also true that in the past years, Google has improved a lot in dealing with this kind of problem, therefore recurring to the “canonical trick” should be a classic last resort solution.

#8 Not having resolved all the classic technical SEO issues related to crawling and indexing.

“Generic” technical issues on our website can negatively impact the effectiveness of our hreflang implementation.

It is always important to keep in mind that, regardless of the implementation method, Google must visit each page to verify the tags and the reciprocity of the alternate, so if crawlers encounter bottlenecks in their crawling, the effectiveness of hreflang will be reduced.
For larger websites with JavaScript or with significant crawling problems, this cluster validation can take a long time.

Answers to classic doubts about the hreflang.

Here below I present a selection of the classic questions I asked about the “nature” and functioning of the hreflang.

Is hreflang a geotargeting factor?

The short answer is: NO.

Hreflang’s only purpose is to indicate what URL Google should show in a locale to better serve the local searchers.

Using it because so Google will consider our www.domain.com/es-MX/viva-mexico.html URL “Mexican” is not the correct way to think about hreflang, if all the real geo-targeting factors (i.e.: using Mexican Spanish instead of the Spanish used in Spain) are not in place.

Is hreflang a ranking factor?

The first answer should be that we do not know for certain what are the ranking factors of Google but for very few ones.

In the specific case of the hreflang, the answer is: No, it is not a ranking factor.

A more technical answer is this: the hreflang tells Google what URLs to show in a locale Google. That means that if in Google.co.uk we were ranking in position 3 with a .com (en-US) URL, thanks to the hreflang, then, Google will swap the URL it is showing to present the .com/en-gb/ one.

It will, hopefully, still rank in position 3 but not because the hreflang has given it a special ranking boost, simply because it made the swap.

Can I indicate the same URL for different hreflang annotations?

Yes, we can do that.

Let’s say we have to tune in very well to how a certain URL is shown to a specific supranational area like, for instance, less relevant markets for which we do not want to spend budget, effort and time for creating a country-specific version. Therefore we have a generic one that we will serve to those markets.

In this case, the href element can indicate the URL and the hreflang different combinations of language + country codes.

Example:

  1. <link rel=”alternate” href=”https://www.domain.com/” hreflang=”es-MX” />
  2. <link rel=”alternate” href=”https://www.domain.com/es-CO” hreflang=”es-CO” />
  3. <link rel=”alternate” href=”https://www.domain.com/es/” hreflang=”es-HN” />
  4. <link rel=”alternate” href=”https://www.domain.com/es/” hreflang=”es-CR” />
  5. <link rel=”alternate” href=”https://www.domain.com/es/” hreflang=”es-HN” />

However, this does not mean that it is a smart idea to exaggerate in using this possibility, because – once again – that would mean overcomplicating the hreflang implementation, and the more this is complex, the bigger the risk it has to break.

For instance, we target both Spain and Latam, but at this moment we cannot afford the creation of country-specific versions for Mexico, Colombia, Peru and all the other Spanish-speaking countries in the American continent, but only for a generic Spanish language version (hopefully with a certain kind of localization).

Instead of adding as many hreflang annotations as countries are in America, we can simply implement  only these two lines of code with the same effect:

  1. <link rel=”alternate” href=”https://www.domain.com/” hreflang=”es-ES” />
  2. <link rel=”alternate” href=”https://www.domain.com/latam/” hreflang=”es” />

Can using JavaScript in the <head> prevent Google from seeing hreflang tags?

Yes! If JavaScript is present in the <head> before the hreflang annotations, and it is incorrect (i.e.: presents img src like the Facebook pixel <noscript>), then, it will break the DOM, and everything (hence, not only the hreflangs) that follows will be considered part of the JavaScript.

For this reason, it is always safer to present the hreflang markups immediately in the <head> along with the other HTML tags and elements essential for SEO (eg.: title, meta description, rel=”canonical”, meta robots, viewport et al).

What tools can I use to audit the hreflang implementation of my website?

All crawler has a specific section dedicated to International SEO, which is almost synonymous with hreflang.

So, if you use Screaming Frog or Sitebulb (or both) or any other commercial crawler, you will have only to remember to set up the crawl to indicate potentially existing issues in the hreflang implementation.

Example of the hreflang section of JetOctopus

Tools that are specific about International SEO and hreflang are these:

If you want to check/test hreflangs on the go (for instance when preparing a pitch for a client or doing a quick review), you can use:

Plugins, modules, and add-ons for implementing hreflang.

When it comes to plugins, modules, and add-ons for implementing hreflang, we literally can pass from an overwhelming proposal of options to very reduced (and usually very complicated) solutions.

Therefore, the list below cannot be considered exhaustive at all, and it is one of the reasons why I will update this article from time to time.

Here we go:

And this is all for now. Remember to save the link to this guide because I will update it whenever new information about the hreflang is announced.

However, if even after reading this article you think you need help in assessing your hreflang implementation or have to do it and for more general International SEO support, you can always contact me using the form on the homepage.

Share if you care