/ Hreflang Fixes / x-default

How to Fix Missing x-default

Your site targets en-GB, fr-FR, de-DE. A user in Brazil visits. None of your locales match. What does Google show them? Without x-default, Google guesses — often picking the wrong page. With x-default, you tell Google exactly which page to serve as fallback. One extra annotation per page, big international UX improvement.

1. What x-default does

x-default is a special hreflang value meaning "serve this URL to any user who doesn't match my other locales". Acts as the catch-all fallback. Without it, Google's behaviour for unmatched users is inconsistent.

Typical use cases

2. Pick the x-default target

Pattern 1: Language picker landing page

https://example.com/

The root URL shows a country/language picker. User explicitly chooses. Best for sites with 5+ locales, complex regional differences, e-commerce with currency/shipping variations.

<link rel="alternate" hreflang="en-GB" href="https://example.com/uk/about" />
<link rel="alternate" hreflang="en-US" href="https://example.com/us/about" />
<link rel="alternate" hreflang="fr-FR" href="https://example.com/fr/about" />
<link rel="alternate" hreflang="de-DE" href="https://example.com/de/about" />
<link rel="alternate" hreflang="x-default" href="https://example.com/" />

Pattern 2: English-international

https://example.com/en/about

Point x-default at your English-language version without region. Best for sites where English serves international users adequately and most users would prefer "just give me English" over picking explicitly.

<link rel="alternate" hreflang="en" href="https://example.com/en/about" />
<link rel="alternate" hreflang="fr-FR" href="https://example.com/fr/about" />
<link rel="alternate" hreflang="de-DE" href="https://example.com/de/about" />
<link rel="alternate" hreflang="x-default" href="https://example.com/en/about" />

What NOT to do

<!-- BAD: x-default to a country-specific version -->
<link rel="alternate" hreflang="x-default" href="https://example.com/us/about" />
<!-- US English shown to French Canadian users? They'd prefer fr-CA fallback or picker -->

3. Add to every page in the cluster

Same x-default URL on every variant page. Treat it like another locale entry in your cluster config.

// locales-config.js
export const aboutCluster = {
  'en': 'https://example.com/en/about',
  'fr-FR': 'https://example.com/fr/about',
  'de-DE': 'https://example.com/de/about',
  'x-default': 'https://example.com/en/about'  // ← fallback
};

// Generator function
function renderHreflang(cluster) {
  return Object.entries(cluster).map(([lang, href]) =>
    `<link rel="alternate" hreflang="${lang}" href="${href}" />`
  ).join('\n');
}

// Output on EVERY page in the cluster, including the x-default target itself

4. WordPress (WPML / Polylang)

Most WordPress translation plugins generate x-default automatically. If missing, check plugin settings:

WPML → Languages → SEO options
  - "Add alternate language links to the head" → enabled
  - "Send default language as x-default" → enabled

Polylang → Languages → Settings
  - "Generate hreflang" → enabled
  - "Default language is x-default" → enabled

5. Next.js i18n

// app/[locale]/about/page.tsx
export async function generateMetadata({ params }) {
  return {
    alternates: {
      canonical: `https://example.com/${params.locale}/about`,
      languages: {
        'en': 'https://example.com/en/about',
        'fr-FR': 'https://example.com/fr/about',
        'de-DE': 'https://example.com/de/about',
        'x-default': 'https://example.com/en/about'
      }
    }
  };
}

6. Static sites (Hugo / Astro / Eleventy)

Hugo

{{ range .Translations }}
  <link rel="alternate" hreflang="{{ .Lang }}" href="{{ .Permalink }}" />
{{ end }}
<link rel="alternate" hreflang="{{ .Lang }}" href="{{ .Permalink }}" />
<link rel="alternate" hreflang="x-default" href="{{ .Site.BaseURL }}{{ .RelPermalink | replaceRE "^/[a-z]{2}/" "/en/" }}" />

Astro

---
const locales = {
  'en': '/en/about',
  'fr-FR': '/fr/about',
  'de-DE': '/de/about'
};
---
{Object.entries(locales).map(([lang, path]) => (
  <link rel="alternate" hreflang={lang} href={`https://example.com${path}`} />
))}
<link rel="alternate" hreflang="x-default" href="https://example.com/en/about" />

7. Verify the fix

Step 1
View source on each variant
Each page in the cluster should show the same x-default URL. Use DevTools or curl + grep:
curl -s https://example.com/en/about | grep hreflang
curl -s https://example.com/fr/about | grep hreflang
# Both should include the same hreflang="x-default" line
Step 2
Re-run Hreflang Checker
x-default warnings clear. Cluster validates as complete.
💡 The single rule: x-default points at the page you'd want a confused international user to see — language picker for "let them choose" sites, English-international for "they probably want English" sites. Don't point it at a regional version like en-US — that confuses fallback with explicit targeting.

🌍 Re-run the Hreflang Checker

Verify x-default present on every variant.

Run Hreflang Checker →
Related Guides: Hreflang Fixes  ·  Fix Return Tags  ·  Fix Self-Reference  ·  Hreflang Guide
💬 Got a problem?