International SEO
Serving multiple languages or countries multiplies your pages - and your ways to fail. International SEO is the architecture that ensures the right variant ranks for the right audience, without the variants competing against or duplicating each other. Site Architecture introduced hreflang; this guide is the full treatment.
Language targeting vs. country targeting#
Two different problems, often conflated:
- Language targeting: one site, multiple languages (
/en/,/de/) - serve users in their language wherever they are - Country targeting: distinct offerings per market (prices, stock, legal) -
example.deor/de-DE/should win in Germany even against your own/en-US/
Decide which you're doing per section before touching URLs; the machinery below serves both but is configured differently.
URL structure options#
| Structure | Example | Trade-offs |
|---|---|---|
| Subdirectories | example.com/de/ | One domain's authority shared; easiest to maintain - the default choice |
| Subdomains | de.example.com | Looser authority sharing; sometimes forced by infrastructure |
| ccTLDs | example.de | Strongest country signal + local trust; splits authority across domains entirely |
hreflang, properly#
hreflang annotations tell engines which URL serves which language/region, preventing wrong-locale rankings and cross-locale duplicate clustering:
export async function generateMetadata({
params,
}: PageProps<"/[lang]/blog/[slug]">): Promise<Metadata> {
const { lang, slug } = await params;
return {
alternates: {
canonical: `https://example.com/${lang}/blog/${slug}`,
languages: {
"en-US": `https://example.com/en/blog/${slug}`,
"de-DE": `https://example.com/de/blog/${slug}`,
"fr-FR": `https://example.com/fr/blog/${slug}`,
"x-default": `https://example.com/en/blog/${slug}`,
},
},
};
}The rules that, when broken, silently void the whole setup:
- Bidirectional and self-referencing: every variant lists all variants including itself, identically. One-way annotations are ignored.
- Absolute URLs, pointing at canonical, indexable,
200pages - hreflang to redirects or noindexed pages is discarded. x-defaultnames the fallback for unmatched users (often your English page or a language selector).- Codes are ISO 639-1 language + optional ISO 3166-1 region:
de,de-AT,pt-BR. There is noen-EU; region codes are countries. - hreflang doesn't consolidate signals - variants rank on their own merits; it only fixes which variant shows where.
For very large sites, hreflang in XML sitemaps (each URL listing its alternates) scales better than per-page tags.
Translation and duplication#
- Same language, different regions (
en-USvsen-GB) with near-identical content is legitimate - hreflang exists exactly for this; engines cluster them and show the right one. Don't canonicalize one region to another unless you want only one indexed. - Translate, don't mirror: titles, meta, slugs, schema and internal anchors all need localization. Half-translated templates ("Buy now" buttons in English on the German page) erode quality signals and conversions equally.
- Machine translation at scale without review is risky on two fronts: quality verdicts from engines, and brand damage from wrong terminology. Human-reviewed MT is the workable middle.
- Local keyword research beats translated keyword research - Germans don't search a literal translation of the English head term ("mobile phone" → "Handy"). Re-run the research process per market.
Common failure patterns#
✗ Auto-redirecting by IP Googlebot (US IPs) never escapes /en/;
users can't reach other variants either.
→ suggest, don't force (dismissible banner)
✗ hreflang to noindexed pages annotations silently dropped
✗ Canonical across locales /de/ canonicalized to /en/ deindexes German
✗ One sitemap, no alternates, slow/incomplete locale discovery
no hreflang
✗ Translated content, untranslated duplicate-looking head data across locales
titles/metaValidate with a crawler's hreflang report (Screaming Frog checks reciprocity automatically) after every locale launch - international setups break quietly when templates change.
Next: Off-Page SEO, or jump ahead to AEO.
