hreflang for Bilingual Sites: Implementation and Validation

hreflang for Bilingual Sites: Implementation and Validation

hreflang is simple to describe and easy to get wrong. This is the implementation that holds up, and the crawl that proves it, for an English and Arabic site.

hreflang is a single line of HTML that says "this page also exists in this other language at this address". It is easy to describe, and on most bilingual sites we audit it is wrong in at least one of five predictable ways. The cost of getting it wrong is that the two language versions compete with each other, or the wrong one shows in results, or the search engine quietly ignores the whole set. This is the implementation that holds up, and the crawl that proves it.

Decide the URL structure first

hreflang describes URLs, so the URLs have to be settled before you write a tag.

For a bilingual business site the structure that preserves the most and confuses the least is: the primary language at the root with no prefix, the second language in a subfolder.

https://example.com/services/        English
https://example.com/ar/services/     Arabic

Three reasons. Every existing English URL keeps its address and its link equity. The folder makes the language visible to humans and crawlers without a subdomain's separate reputation. And the pairing is mechanical: strip or add /ar/ and you have the twin.

Do not put the language in a parameter (?lang=ar) and do not switch language by cookie or browser setting without changing the URL. A crawler and a human must always receive the same document at the same address; a page that changes language based on who is asking cannot be indexed reliably in either.

Choose one way to emit it

There are three valid places for hreflang. Pick one and use it consistently across the site.

  1. <link> tags in the HTML head. The most common, and the easiest to inspect in view-source. Each page lists every version of itself.
  2. The XML sitemap, with xhtml:link alternates on every URL entry. Better for very large sites where adding tags to templates is hard.
  3. HTTP headers, for non-HTML files such as PDFs.

For a Next.js, WordPress or similar site, use the head tags, and consider emitting them in the sitemap as well; both is fine as long as they agree.

The rules that make it work

Every page lists all versions, including itself

On the English page:

<link rel="alternate" hreflang="en" href="https://example.com/services/" />
<link rel="alternate" hreflang="ar" href="https://example.com/ar/services/" />
<link rel="alternate" hreflang="x-default" href="https://example.com/services/" />

On the Arabic page, the exact same three lines. Not "the other one", all of them. A page that omits itself breaks the set.

The pairs must be reciprocal

If the English page points at the Arabic page, the Arabic page must point back. One-directional annotations are ignored. This is the mistake that a template bug produces most often: English pages list both, Arabic pages list only themselves.

Only for pages that really exist in both languages

If an English post has no Arabic version, the English page must not claim one. Pointing hreflang at a page that serves English content under /ar/ because the CMS "falls back" is worse than no tag: the search engine finds the same content at two URLs, one of them mislabelled. The rule in code: emit the Arabic alternate only when the Arabic document exists.

Use absolute URLs, and the canonical ones

Full https:// URLs, and the version the page canonicals to. Never point hreflang at a URL that redirects, at an http version, or at a version with or without a trailing slash that differs from the canonical. A redirect in an hreflang target breaks that pair.

Language codes, not region codes, unless you mean it

en and ar. Adding a region (ar-SA, en-US) tells the search engine the page is specifically for people in that country, which narrows the audience to those visitors and makes the page a weaker match for everyone else who reads the language. Use regions only when you truly serve different content per country, such as different prices or products.

x-default is a real page

x-default names the page to show when the visitor's language does not match any alternate. It should be one of the listed alternates, usually the primary language's URL. It must not be a language chooser page, and it must not point at a redirect.

Implementation patterns

One helper, every page

The failure mode on custom sites is that the developer adds hreflang to four templates and forgets the other twelve. Build one function that, given a path and whether the Arabic twin exists, returns the full set, and call it from every page's metadata. On a Next.js site that is a pageMeta helper used by every route; on WordPress it is the multilingual plugin's output, which you then verify rather than trust.

The visible language link on the page should go to the same page in the other language, not to the other language's home page, and not through a redirect. Search engines use it as a cross-check, and humans use it constantly.

Keep hreflang out of noindexed pages

A page you have told the crawler not to index should not participate in an hreflang set. If the staging site or a draft version of a language is noindexed, remove it from the alternates until it is live.

Common mistakes and what they look like

MistakeSymptomFix
Arabic pages list only themselves"No return tags" errors in Search ConsoleEmit the full set from one helper on every page
hreflang points at a redirecting URLPairs silently ignoredPoint at the canonical URL with the right trailing slash
ar-SA on a site serving all Arabic readersWeak visibility for Arabic queries outside that regionUse ar
Arabic alternate on pages that fall back to EnglishDuplicate content across languagesEmit ar only when the Arabic document exists
x-default on a language chooserThe chooser ranks instead of a real pagePoint x-default at the primary language page
hreflang present but <html lang> wrongMixed signals; wrong direction on Arabic pagesSet lang and dir from the locale
Sitemap alternates disagree with head tagsInconsistent annotations, some ignoredGenerate both from the same source of truth

Validate it with a crawl, not a plugin screenshot

A multilingual plugin's settings page saying "hreflang: enabled" is not evidence. The evidence is what the HTML contains.

  1. Crawl the site with a crawler that reports hreflang (Screaming Frog has a dedicated tab). Export the hreflang report.
  2. Check for: missing return links, non-canonical targets, targets that return anything other than 200, pages with no hreflang at all, and inconsistent x-default.
  3. Open Search Console's International Targeting report for legacy properties, or the Pages report for "Duplicate, Google chose different canonical than user" on language pairs, which is what an ignored hreflang set looks like in practice.
  4. Fetch three pages from each template in each language with curl and read the head. Templates lie less than dashboards.
  5. Re-crawl after every deployment that touches routing. hreflang breaks when someone changes a trailing-slash rule, not when someone edits content.

What we do on the sites we build

One helper emits canonical, hreflang and x-default for every route, and it takes a flag for whether the Arabic twin exists so the tag is never a lie. The sitemap is generated from the same data. lang and dir are computed from the locale, never hard-coded. And after every deploy that touches routing, the crawl runs again, because hreflang is the part of a bilingual site that breaks silently and costs the most when it does.

Questions

Do I need hreflang if my site is only in English and Arabic?

Yes. hreflang is what tells the search engine that the Arabic page is the Arabic version of the English page rather than a duplicate or an unrelated document. Without it, the two versions can compete for the same query, and the wrong one can appear.

Should hreflang use ar or ar-SA?

Use the language code alone (ar, en) unless you genuinely serve different content per country. Region codes narrow the audience: an ar-SA page is a weaker match for an Arabic speaker elsewhere. Language-only codes cover everyone who reads that language.

What should x-default point to?

The version you want shown to visitors whose language you do not serve. For most bilingual business sites that is the English page. It must be a real page, not a language-selection screen, and it should be one of the alternates already listed.

Related pages

Work with Alnitak

Our audit validates every hreflang pair on your site with a crawl and tells you which ones the search engine is ignoring and why.

Bilingual technical SEO auditfrom $1,700 (5–7 days)

WhatsApp this offerSee packagesContact Us

Related reading