Hreflang Tags

Hreflang tags tell search engines which language and regional versions of a page exist. Wash automatically generates hreflang data for multilingual WordPress sites syncing to Shopify.

What are hreflang tags?

Hreflang is an HTML attribute that tells search engines:

  • Which language a page is written in
  • Which geographic region it targets
  • Where to find alternate language versions

Example hreflang tags

<link rel="alternate" hreflang="en" href="https://store.com/blogs/news/article" />
<link rel="alternate" hreflang="de" href="https://store.com/de/blogs/news/article" />
<link rel="alternate" hreflang="fr" href="https://store.com/fr/blogs/news/article" />
<link rel="alternate" hreflang="x-default" href="https://store.com/blogs/news/article" />

Why hreflang matters for SEO

Without HreflangWith Hreflang
Search engines may show wrong language versionCorrect language shown to each user
Duplicate content penalties possibleSearch engines understand it's translations
Users land on wrong language pagesUsers see content in their language
Wasted crawl budgetEfficient crawling of all versions

Supported WordPress plugins

Wash extracts hreflang data from popular multilingual plugins:

PluginSupportNotes
WPMLFullAutomatic translation detection, language codes
PolylangFullLocale detection, translation links
TranslatePressPartialURL-based translations
WeglotPartialAPI-based translations
LokaliseVia WPMLWorks through WPML integration

Enabling hreflang sync

Hreflang sync is part of the Pro plan and above.

  1. Go to Settings > Wash Connector and open the Hreflangs tab
  2. Check Multilingual Plugin Status. Wash finds WPML, Polylang, TranslatePress or Weglot on its own and shows which one it detected
  3. Tick Enable Hreflangs
  4. Click Save Changes
  5. Add the Liquid code below to your theme

The same setting is in the Shopify app, under the connection's Settings > Hreflangs. Both edit the same value.

How it works

WordPress (WPML, Polylang, TranslatePress or Weglot)
        ↓
Wash reads the post's translations
        ↓
One metafield per language on the Shopify article
        ↓
Your theme prints the hreflang tags

Metafield structure

Each language becomes its own metafield in the wash_hreflang namespace. The key is hreflang_ followed by the language code, with _ in place of -:

Metafield keyNamespaceExample value
hreflang_en_uswash_hreflanghttps://store.myshopify.com/blogs/news/article-en
hreflang_de_dewash_hreflanghttps://store.myshopify.com/blogs/news/artikel-de
hreflang_pl_plwash_hreflanghttps://store.myshopify.com/blogs/news/artykul-pl
hreflang_x_defaultwash_hreflanghttps://store.myshopify.com/blogs/news/article-en

When you remove a translation in WordPress, its metafield is cleared in Shopify on the next sync.

Displaying in Shopify theme

Shopify doesn't output hreflang tags for blog articles by itself, so the theme has to. In Shopify, go to Online Store > Themes > Edit code, open layout/theme.liquid and paste this inside <head>, before </head>:

{% if article %}
  {% assign ns = 'wash_hreflang' %}
  {% for metafield in article.metafields[ns] %}
    {% if metafield.key contains 'hreflang_' %}
      {% assign lang_code = metafield.key | remove: 'hreflang_' | replace: '_', '-' %}
      <link rel="alternate" hreflang="{{ lang_code }}" href="{{ metafield.value }}" />
    {% endif %}
  {% endfor %}
{% endif %}

It prints every language, including x-default. The Hreflangs tab in WordPress shows the same code. Save, then view the source of an article to check the tags are there.

If you use Shopify Markets translations

If your blog-mapping rules send translations into Shopify Markets, there's one article per post and Shopify Markets already adds hreflang tags for its language URLs. You don't need this feature as well. It's meant for setups with a separate article per language.

Language codes

Use ISO 639-1 language codes, optionally with ISO 3166-1 region:

CodeLanguageRegion
enEnglishGlobal
en-USEnglishUnited States
en-GBEnglishUnited Kingdom
deGermanGlobal
de-ATGermanAustria
frFrenchGlobal
esSpanishGlobal
x-defaultFallbackNo match

Troubleshooting

Hreflang tags not appearing

  • Check Enable Hreflangs is ticked
  • Check Multilingual Plugin Status shows your plugin
  • Check the post has translations in WordPress
  • Sync the article again after enabling
  • Check the Liquid code is in layout/theme.liquid, inside <head>

Wrong language codes

  • Check your multilingual plugin's language settings
  • Verify ISO language codes are correct
  • Sync the articles again after changing codes

Validation tools

Best practices

  1. Always include x-default as the fallback for languages you don't match.
  2. Use the same URL format in every language.
  3. Have each page list itself among its alternates.
  4. Link every translation to every other one; hreflang links must go both ways.
  5. Make the canonical URL match the page's own hreflang URL.