Skip to main content
CodeRocket
Internationalizationmediumtext

Add hreflang tags for multilingual sites

rule · hreflang

Hreflang tags help search engines serve the correct language version to users.

Code Example

HTML
<link rel="alternate" hreflang="language-region" href="URL" />
CodeMeaning
enEnglish (any region)
en-USEnglish (United States)
en-GBEnglish (United Kingdom)
esSpanish (any region)
es-ESSpanish (Spain)
es-MXSpanish (Mexico)
x-defaultDefault/fallback page

Why It Matters

Without hreflang, users searching in French might see your English page—proper implementation ensures the right language version appears in search results for each region.

Basic Implementation

HTML
<head>
  <!-- Current page is English (US) -->
  <link rel="alternate" hreflang="en-US" href="https://example.com/en/about" />
  <link rel="alternate" hreflang="es-ES" href="https://example.com/es/sobre" />
  <link rel="alternate" hreflang="fr-FR" href="https://example.com/fr/a-propos" />
  <link rel="alternate" hreflang="x-default" href="https://example.com/about" />
</head>

Next.js Implementation

TSX
// app/[lang]/about/page.tsx
import { Metadata } from 'next'
 
const LANGUAGES = {
  'en-US': '/en/about',
  'es-ES': '/es/sobre',
  'fr-FR': '/fr/a-propos',
}
 
export async function generateMetadata(): Promise<Metadata> {
  return {
    alternates: {
      languages: LANGUAGES,
    },
  }
}
TSX
// Dynamic hreflang generation
// lib/seo.ts
interface HreflangConfig {
  baseUrl: string
  path: string
  translations: Record<string, string>
}
 
export function generateHreflang({ baseUrl, path, translations }: HreflangConfig) {
  const hreflangTags = Object.entries(translations).map(([locale, localePath]) => ({
    hreflang: locale,
    href: `${baseUrl}${localePath}`,
  }))
 
  // Add x-default pointing to main language
  hreflangTags.push({
    hreflang: 'x-default',
    href: `${baseUrl}${path}`,
  })
 
  return hreflangTags
}
HTML
<!-- On English page (/en/about): -->
<link rel="alternate" hreflang="en-US" href="https://example.com/en/about" />
<link rel="alternate" hreflang="es-ES" href="https://example.com/es/sobre" />
 
<!-- On Spanish page (/es/sobre): -->
<link rel="alternate" hreflang="en-US" href="https://example.com/en/about" />
<link rel="alternate" hreflang="es-ES" href="https://example.com/es/sobre" />
 
<!-- Both pages must include both links! -->

XML Sitemap Alternative

XML
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
        xmlns:xhtml="http://www.w3.org/1999/xhtml">
  <url>
    <loc>https://example.com/en/about</loc>
    <xhtml:link rel="alternate" hreflang="en-US" href="https://example.com/en/about"/>
    <xhtml:link rel="alternate" hreflang="es-ES" href="https://example.com/es/sobre"/>
    <xhtml:link rel="alternate" hreflang="fr-FR" href="https://example.com/fr/a-propos"/>
    <xhtml:link rel="alternate" hreflang="x-default" href="https://example.com/about"/>
  </url>
  <url>
    <loc>https://example.com/es/sobre</loc>
    <xhtml:link rel="alternate" hreflang="en-US" href="https://example.com/en/about"/>
    <xhtml:link rel="alternate" hreflang="es-ES" href="https://example.com/es/sobre"/>
    <xhtml:link rel="alternate" hreflang="fr-FR" href="https://example.com/fr/a-propos"/>
    <xhtml:link rel="alternate" hreflang="x-default" href="https://example.com/about"/>
  </url>
</urlset>

Common Mistakes

HTML
<!-- ❌ Bad: Invalid language code -->
<link rel="alternate" hreflang="english" href="..." />
 
<!-- ✅ Good: ISO 639-1 code -->
<link rel="alternate" hreflang="en" href="..." />
 
<!-- ❌ Bad: Non-reciprocal (missing on Spanish page) -->
<!-- English page links to Spanish, but Spanish doesn't link back -->
 
<!-- ❌ Bad: Self-referencing missing -->
<!-- Page doesn't include hreflang for its own language -->
 
<!-- ❌ Bad: Different domains without proper setup -->
<link rel="alternate" hreflang="de" href="https://example.de/about" />
<!-- Requires proper domain verification -->

Regional Targeting Strategies

StrategyExampleUse When
Language onlyhreflang="es"Same content for all Spanish speakers
Language + regionhreflang="es-MX"Different content per region
Region with language fallbackBoth es-MX and esRegional variations with fallback

Standards

  • Use these references as the standard for the rendered internationalization behavior, not just the source strings or config.
  • Check the implementation against Google Search Central: Search Essentials before treating the rule as satisfied.
  • Check the implementation against Google Search Central documentation before treating the rule as satisfied.

Verification

Automated Checks

  • Use Google Search Console International Targeting report
  • Validate with hreflang testing tools
  • Check all pages have reciprocal links
  • Test search results from different regions

Manual Checks

  • Verify x-default is present