Universally Documentation

Step-by-step guides, multilingual SEO tips, and best practices to help you translate and scale your WordPress website.

hreflang tags

On WordPress, hreflang tags are added for you. Enable a language and its pages start declaring each other as alternates, which is the part of multilingual SEO people most often get wrong by hand.

What the tags do

An hreflang tag tells a search engine that two URLs are the same page in different languages. Without them, /pricing/ and /es/pricing/ look like competing pages with similar content. With them, they read as one page in two languages, and each gets served to the right audience.

Real output on a page in a project with Spanish (Spain) and French (France) added, from an English (US) source, looks like this:

<!-- Universally hreflang tags -->
<link rel="alternate" hreflang="en-us" href="https://example.com/pricing/" />
<link rel="alternate" hreflang="es-es" href="https://example.com/es/pricing/" />
<link rel="alternate" hreflang="fr-fr" href="https://example.com/fr/pricing/" />
<link rel="alternate" hreflang="x-default" href="https://example.com/pricing/" />

Three things to note in that: every language is declared with its full region code rather than a bare es or fr, the source language gets an alternate of its own, and an x-default line points at the source URL.

What you get without configuring anything

Tags that follow your languages. Add a language and it joins the set. Remove one and it drops out. There is no list to maintain and nothing to regenerate after a change.

URLs that match your structure. Each alternate points at the language's real URL, built from the segment you configured. See Add and remove languages.

Region codes, not bare language codes. Every language is stored with a region, and that is what is declared. See Language variants and regional targeting.

Two cases where a tag points somewhere it should not

Both are worth knowing if you are auditing your own markup:

  • A disabled language is still declared. Disabling hides a language from the switcher, but the alternate link for it is still emitted, and the URL no longer serves a translation. If search engines must not see a language, remove it rather than disabling it. See Add and remove languages.
  • An excluded page still declares alternates. A path under Exclude Pages gets alternate links for every language, and each of those URLs redirects back to the source page. See Exclude pages.

Checking them

View source on a translated URL and look in the <head> for the <!-- Universally hreflang tags --> comment, followed by rel="alternate" lines. Expect one per language, plus one for your source language, plus x-default: three languages means five links.

Google Search Console's International Targeting report is the slower but more thorough check, since it reports mismatches rather than just presence.

Tags are added independently of translation, so a page that is not translated, or is excluded, still gets them. If they are missing entirely, the cause is one of these:

  • The site is not connected, or its API key is missing or invalid
  • Universally could not be reached when the language list was last fetched, so the list is empty. Use Refresh under Universally » General » Languages, which can take up to 15 minutes to expire on its own
  • Your theme does not call wp_head(), so nothing in the <head> is added by any plugin

If you have your own SEO plugin

Universally does not touch hreflang links that are already in your markup: an element carrying an hreflang attribute is excluded from link localization, so whatever your SEO plugin wrote is what ships. If you would rather it owned the tags entirely, that keeps working.

Through the API

An API integration serves its own pages, so it emits its own <head>. Universally supplies the translated content and the URL structure; adding the alternate links is part of the integration. See Integrate using the API.

Was this helpful?