Hreflang Configuration
Setting up hreflang alternate language tags so Google serves the correct language version to each user — critical for multi-locale sites at launch.
Why
If your site has /launch (English) and /zh/launch (Chinese), Google might serve the English version to a Chinese user and the Chinese version to an English user, because it guesses based on signals that are often wrong. Hreflang tags tell Google explicitly: 'this URL is the English version, this other URL is the Chinese version, serve the one that matches the user's language preference'. This improves UX (users see their language), increases conversion (users bounce less), and consolidates ranking signal across the language variants (Google treats them as a group, not competitors). Without hreflang, the English and Chinese /launch pages compete in the index and neither ranks as well as a properly-hreflang'd pair. Hreflang is especially critical at launch because new pages need to be paired with their alternates from day 1 — adding hreflang later means re-crawling and re-indexing, delaying the ranking benefit by weeks.
When
During the build, in the BaseLayout head, for every page that has language alternates. Verify with a crawl before launch and in Search Console post-launch.
How
1. List all locale variants of each page: /launch (en), /zh/launch (zh), /ja/launch (ja), /es/launch (es), etc. — every locale your site supports 2. In the BaseLayout head, for each page, output an hreflang tag for every locale variant: <link rel="alternate" hreflang="en" href="https://ez4code.com/launch"> <link rel="alternate" hreflang="zh" href="https://ez4code.com/zh/launch"> <link rel="alternate" hreflang="ja" href="https://ez4code.com/ja/launch"> 3. Include an x-default hreflang pointing to the default locale (usually en): <link rel="alternate" hreflang="x-default" href="https://ez4code.com/launch"> 4. Each hreflang tag must be bidirectional: if /launch declares /zh/launch as alternate, /zh/launch must declare /launch as alternate — missing the return link is the most common hreflang error 5. The hreflang values must be valid ISO language codes (en, zh, ja, es) or language-region codes (en-US, zh-CN) — invalid codes like "english" or "chinese" are ignored 6. Every hreflang URL must return 200 (not 404 or redirect) — if /ja/launch doesn't exist yet, don't declare it in hreflang; only declare alternates that are live 7. Verify with Screaming Frog: it has an 'Hreflang' report that flags missing return tags, invalid codes, and non-200 targets 8. In Google Search Console, check the 'International Targeting' report post-launch — any hreflang errors appear here within 2 weeks 9. For pages that exist in only one locale (no translation), do not use hreflang — a single self-referencing canonical is enough; hreflang is only for pages with actual alternates
Example
# Hreflang Configuration — ez4code v2.0 /launch ## Supported locales: en, zh, ja, es, fr, de, pt, ko, ru ## /launch (English) head <link rel="alternate" hreflang="en" href="https://ez4code.com/launch"> <link rel="alternate" hreflang="zh" href="https://ez4code.com/zh/launch"> <link rel="alternate" hreflang="ja" href="https://ez4code.com/ja/launch"> <link rel="alternate" hreflang="es" href="https://ez4code.com/es/launch"> <link rel="alternate" hreflang="fr" href="https://ez4code.com/fr/launch"> <link rel="alternate" hreflang="de" href="https://ez4code.com/de/launch"> <link rel="alternate" hreflang="pt" href="https://ez4code.com/pt/launch"> <link rel="alternate" hreflang="ko" href="https://ez4code.com/ko/launch"> <link rel="alternate" hreflang="ru" href="https://ez4code.com/ru/launch"> <link rel="alternate" hreflang="x-default" href="https://ez4code.com/launch"> ## /zh/launch (Chinese) head — bidirectional <link rel="alternate" hreflang="en" href="https://ez4code.com/launch"> <link rel="alternate" hreflang="zh" href="https://ez4code.com/zh/launch"> ... (all 9 locales + x-default) ## Verification (Screaming Frog) 77 URLs × 10 hreflang tags = 770 hreflang links 0 missing return tags ✓ 0 invalid codes ✓ 0 non-200 targets ✓ ## Post-launch (Search Console) International Targeting report: 0 errors ✓ ## Result (after 4 weeks) Google serves /zh/launch to zh-CN users (was serving /launch before) Bounce rate for zh users: 32% → 18% (correct language served)
Common Problems
- ⚠Missing the return hreflang link — /launch declares /zh/launch as alternate but /zh/launch doesn't declare /launch; Google ignores the one-way hreflang and serves the wrong language to both audiences.
- ⚠Declaring hreflang for locales that don't exist — /launch declares /ja/launch but the Japanese page returns 404; Google sees a broken hreflang and may ignore all hreflang signals on the page.
- ⚠Using hreflang instead of canonical for language variants — hreflang tells Google about alternates, canonical tells it which is authoritative; each language version needs a self-referencing canonical AND hreflang to the others, not one or the other.
- ⚠Forgetting x-default — without x-default, Google doesn't know which version to serve to users whose language isn't in the hreflang list (e.g. a French user on a site with only en and zh); x-default is the fallback.
Best Practices
- ✓Generate hreflang tags from a single locale config (the same array that drives route generation) — this ensures every page declares the same set of alternates and none are missed.
- ✓Include x-default on every page — it's the fallback for unmatched languages and costs nothing; omitting it is the most common reason hreflang 'doesn't work' for non-listed locales.
- ✓Verify bidirectionality with a script: for every hreflang A→B, check that B→A exists; this catches the one-way link error that Screaming Frog sometimes misses on large sites.
- ✓Only add hreflang for locales that are fully translated and live — partial translations (a page exists in en and zh but not ja) should have hreflang only for en and zh, not a broken ja link.