Hreflang трактується як екзотична частина міжнародного SEO. Це насправді чеклист з шести речей, три з яких збивають кожну команду при першому впровадженні.
Це робоче налаштування. Баги, які варто знати. Випадки, коли воно вам не потрібне.
Для чого hreflang
Hreflang каже Google, яку версію сторінки показувати якому користувачу, коли у вас той самий контент кількома мовами чи регіонами. Він робить дві речі:
- Уникає штрафу за дублі контенту для тієї самої статті різними мовами.
- Маршрутизує правильного користувача до правильної мовної версії, тож англомовний не натрапить на французьку сторінку з пошуку Google.
Якщо у вас одномовний сайт — hreflang не потрібен. Якщо мультимовний — потрібен. Проміжний випадок (мультирегіональний, але одномовний — US English vs UK English) — це там, де відбувається більшість багів.
Три режими провалу
1. Правило взаємності
Hreflang має бути взаємним. Якщо сторінка A посилається на сторінку B як на французьку версію, сторінка B має посилатись на A як на англійську. Якщо лише один бік оголошує зв'язок, Google ігнорує обидва.
<!-- На example.com/en/about -->
<link rel="alternate" hreflang="en" href="https://example.com/en/about" />
<link rel="alternate" hreflang="fr" href="https://example.com/fr/about" />
<!-- На example.com/fr/about — МАЄ бути присутнім, ті самі теги -->
<link rel="alternate" hreflang="en" href="https://example.com/en/about" />
<link rel="alternate" hreflang="fr" href="https://example.com/fr/about" />Баг, який ми бачимо: команди генерують hreflang-теги з масиву locales, але забувають включити поточну сторінку у її ж список. Кожна сторінка перелічує «інші локалі» замість «всі локалі, включно з цією». Взаємність ламається, Google ігнорує усе.
Правило великого пальця: кожна сторінка перелічує кожну версію, включно з собою. Self-референс виглядає надлишковим, але обов'язковий.
2. Пастка x-default
x-default — це fallback. Коли Google не може підібрати локаль під користувача (його мови немає у вашому списку), він повертається до x-default URL.
Баг: команди ставлять x-default на англійську версію. Тоді французький користувач з браузером, налаштованим на французьку, потрапляє на англійську замість французької, бо логіка Google перевіряє x-default до того, як вичерпати всі мовні відповідності.
Правильний паттерн: x-default має вести на «language picker» сторінку, якщо вона у вас є, або на найзагальніший URL (наприклад, корінь /, що автодетектить локаль і редиректить). Не на конкретну мовну версію.
<link rel="alternate" hreflang="x-default" href="https://example.com/" />
<link rel="alternate" hreflang="en" href="https://example.com/en/about" />
<link rel="alternate" hreflang="fr" href="https://example.com/fr/about" />Виняток: якщо ваш дефолт справді є англійською версією (немає language picker, англійська — канонічний сайт), тоді x-default і en можуть вказувати на той самий URL. Просто зробіть це явним.
3. Регіональні vs. мовні коди
Hreflang використовує двобуквені мовні коди (ISO 639-1) опційно з двобуквеним регіональним кодом (ISO 3166-1). Комбінації мають більше значення, ніж люди думають.
en— англомовні всюдиen-US— англомовні у США конкретноen-GB— англомовні у Великій Британії конкретноen-us(неправильний регістр) — Google має це прийняти, але стандарт — uppercase для регіону
Якщо у вас одна англомовна версія — використайте en. Якщо окремі US і UK — en-US і en-GB (і поставте обидва у список тегів кожної сторінки, з взаємністю).
Баг: команди оголошують en-US і en-GB, але без простого en. Користувач у Канаді (англомовний, але не US і не GB) маршрутизується кудись непередбачувано, бо немає мовного fallback. Або додайте en, що вказує на ту версію, яку хочете як англійський fallback, або налаштуйте x-default правильно.
Правильне налаштування від початку до кінця
Для маркетингового сайту англійською і німецькою:
<!-- На кожній сторінці, обидві локалі -->
<link rel="alternate" hreflang="en" href="https://example.com/en/services" />
<link rel="alternate" hreflang="de" href="https://example.com/de/services" />
<link rel="alternate" hreflang="x-default" href="https://example.com/" />Корінь / або автодетектить і редиректить (з Accept-Language заголовком), або показує language picker. Будь-що нормально для x-default.
У Next.js з App Router це зазвичай живе у generateMetadata:
export async function generateMetadata({ params }) {
const { locale, slug } = await params;
return {
alternates: {
canonical: `https://example.com/${locale}/services/${slug}`,
languages: {
en: `https://example.com/en/services/${slug}`,
uk: `https://example.com/uk/services/${slug}`,
"x-default": `https://example.com/`,
},
},
};
}Next.js рендерить правильні <link rel="alternate"> теги у head. Усе, що треба зробити — дати URL-паттерн.
Нотатка про canonical URL
Hreflang і canonical URL мають погоджуватись.
- Canonical URL кожної сторінки — це вона сама (locale-специфічний URL).
hreflang="x"кожної сторінки для своєї власної локалі вказує на той самий URL, що й canonical.
Баг: у сторінки canonical /en/services, але її hreflang="en" вказує на /services (без локального префікса). Google бачить конфлікт і може проігнорувати обидві директиви. Обидва мають збігатись.
Як тестувати
Три інструменти, що ловлять більшість того, що ручний огляд пропускає:
Google Search Console. Звіт «International Targeting» перелічує hreflang-помилки, виявлені під час сканування. Відсутня взаємність, конфліктуючі alternate, невалідні коди. Перевіряйте цей звіт щотижня перший місяць після запуску.
Чекер `hreflang.org` (або подібний). Вставте будь-який URL, він сканує hreflang-теги, проходить за ними і повідомляє mismatch. Корисно для першої перевірки.
Теги `<link>` у dev tools. Відкрийте будь-яку сторінку, інспектуйте <head>, шукайте alternate. Підтвердіть взаємність вручну для кількох сторінок.
Запустіть усі три, перш ніж вважати імплементацію готовою. Жоден з них окремо недостатній.
Коли він насправді потрібний
Hreflang обов'язковий, коли:
- У вас той самий контент двома або більше мовами (наприклад, блог-пост англійською і німецькою).
- У вас той самий контент для двох або більше регіонів тієї ж мови (US vs UK English).
Hreflang не потрібний, коли:
- У вас одномовний сайт (незалежно від країни).
- У вас мультимовний сайт, де кожна мова — це справді інший контент (не переклади один одного).
- У вас language picker, але всі мовні URL на одному шляху (це зламано для SEO; виправте URL спочатку).
Проміжний випадок «у мене англійський сайт, і я хочу, щоб він ранкувався у різних країнах» — вирішується налаштуванням гео-таргетингу Search Console, не hreflang. Не плутайте.
Edge cases, які варто знати
Варіанти валюти або контенту. Та сама мова, різні ціни для US/UK/EU. Використовуйте en-US, en-GB, en-EU. Контент може бути на 95% той самий; варіант для SEO — це ціна/валюта, які локалізовані.
Сабдомени vs. сабдиректорії. Hreflang працює однаково для обох. en.example.com і fr.example.com працюють так само, як example.com/en/ і example.com/fr/. Використовуйте те, що ваш CMS підтримує чисто.
Середина роллауту (частина сторінок перекладена, частина ні). Не оголошуйте hreflang для сторінок, яких не існує у цільовій мові. 404 з hreflang гірше за відсутній hreflang.
Авто-перекладений контент. Не ставте на нього hreflang. Google тепер карає авто-переклади, показані як «native». Або використовуйте справжні переклади, або пропускайте мову повністю.
Чеклист перед запуском
- Кожна сторінка перелічує кожну локаль, включно з собою.
x-defaultвказує на language picker або загальний корінь, не на конкретну мову.- Мовні коди правильні (
en, неen_USз underscore;en-GB, неen_GB). - Canonical URL кожної сторінки збігається з її ж hreflang-записом.
- Звіт International Targeting у Search Console без помилок.
- Сторінки, яких немає у цільовій локалі, не оголошуються у hreflang цієї локалі.
П'ять пунктів перевірено правильно — ви покрили випадки, що насправді мають значення. Решта edge cases (середина роллауту, авто-переклад, region-only варіанти) розв'язується по мірі надходження.
Якщо будуєте мультимовний сайт і хочете hreflang зашитим з початку, подивіться, як ми працюємо із сайтами. Це частина кожного проєкту, який ми відвантажуємо, а не upsell.