# Hreflang tags are present and structurally valid for multilingual sites

- **Pattern:** `ab-001686` (`marketing-advanced-seo.technical-seo.hreflang-valid`)
- **Severity:** medium
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001686
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001686)

## Why it matters

Multilingual sites without hreflang tags serve the wrong language to the wrong audience: French users see the English page in search results, bounce rates spike, and Google interprets the engagement signal as a quality problem. Missing `x-default` means Google has no fallback for locales outside your declared set, so international queries return nothing. Relative URLs in hreflang are ignored entirely by crawlers.

## Severity rationale

Medium because impact scales with international traffic and only affects multilingual deployments.

## Remediation

In `generateMetadata`, set `alternates.languages` with an entry per supported locale plus an `x-default` pointing to your primary language. Use absolute HTTPS URLs and valid BCP-47 codes (`en`, `fr-CA`, not `english`). Verify the set is bidirectional — every localized page must reference every other locale.

```tsx
// app/[locale]/layout.tsx
export const metadata = { alternates: { languages: { en: 'https://yoursite.com/en', fr: 'https://yoursite.com/fr', 'x-default': 'https://yoursite.com' } } }
```

## Detection

- **ID:** `hreflang-valid`
- **Severity:** `medium`
- **What to look for:** Count all language variants served by the site. Enumerate hreflang tags found per page and verify x-default is present. Detect whether the project is multilingual by looking for: internationalization libraries (next-intl, next-i18next, i18next, react-i18next, linguiJS in `package.json`), locale-based route structures (`app/[locale]/`, `pages/[lang]/`), or i18n config in framework config files (e.g., `i18n` block in `next.config.*`). If multilingual signals are detected, check for hreflang link tags: `<link rel="alternate" hreflang="[lang]" href="[url]">`. Verify: (1) each locale page has hreflang tags for all available locales plus `x-default`, (2) hreflang values use valid BCP-47 language codes, (3) URLs are absolute and use HTTPS.
- **Pass criteria:** For multilingual projects, all locale pages have a complete set of hreflang tags (one per locale plus x-default), using valid language codes and absolute HTTPS URLs. For single-language projects, this check passes automatically. At least 90% of multilingual pages must have complete hreflang tags including x-default.
- **Fail criteria:** Multilingual signals detected but no hreflang tags found. Or hreflang tags present but missing `x-default`, using relative URLs, using invalid language codes, or not forming a complete bidirectional set.
- **Skip (N/A) when:** No internationalization library, locale-based routing, or i18n configuration detected. Signal: no `[locale]` or `[lang]` dynamic route segments, no `i18n` config block in framework config, no i18n-related package dependencies.

- **Cross-reference:** For URL structure across locales, see `url-structure`.
- **Detail on fail:** `"Multilingual routing detected (next-intl, [locale] route segments) but no hreflang tags found in page metadata. Without hreflang, Google cannot correctly serve localized content to the right language audiences."`
- **Remediation:** Hreflang tells search engines which language version of a page to show to users in different locales. For Next.js with next-intl, generate hreflang links in `generateMetadata` using the `alternates.languages` field — provide one entry per supported locale plus an `x-default` entry pointing to your primary language. All URLs must be absolute HTTPS.

  ```tsx
  // app/[locale]/layout.tsx — hreflang tags
  export const metadata = { alternates: { languages: { en: '/en/page', fr: '/fr/page', 'x-default': '/page' } } }
  ```

Taxons: findability

HTML version: https://auditbuffet.com/patterns/ab-001686
