Дублированный контент — тихий убийца мультиязычных сайтов и страниц с параметрами. Лечится двумя механизмами.
Canonical говорит поисковикам, какой URL «настоящий», когда один контент доступен по нескольким адресам (трекинг-параметры, слэши, пагинация):
export async function generateMetadata({ params }): Promise<Metadata> {
return {
alternates: {
canonical: `/blog/${params.slug}`,
},
};
}
hreflang сообщает, какие языковые версии страницы существуют, чтобы польский пользователь получил в выдаче польскую страницу:
export async function generateMetadata({ params }): Promise<Metadata> {
const { lang, slug } = params;
return {
alternates: {
canonical: `/${lang}/blog/${slug}`,
languages: {
en: `/en/blog/${slug}`,
pl: `/pl/blog/${slug}`,
ru: `/ru/blog/${slug}`,
"x-default": `/en/blog/${slug}`,
},
},
};
}
Ошибки, которые стоят реального трафика:
- hreflang должен быть взаимным. Если EN-страница ссылается на PL-версию, PL-страница обязана ссылаться обратно — иначе Google игнорирует всю группу.
- Каждая страница должна включать саму себя в карту
languages. - Локализованные слаги: если польский пост живёт по другому слагу, hreflang должен указывать на реальный локализованный URL, а не на механический
/pl/+ тот же слаг. Генерируйте карту из источника контента, не хардкодьте. x-default— для пользователей, чей язык вы не поддерживаете; направьте его на основную локаль.- Canonical должен вести на страницу с кодом 200 и без
noindex— canonical на редиректящий URL игнорируется.
Чеклист:
- Самоссылающийся canonical на каждой индексируемой странице
- hreflang сгенерирован из реальных локализованных слагов и взаимен во все стороны
- Есть
x-default - URL-параметры (utm, фильтры, сортировки) канонизируются на чистый URL