Canonical в Next.js указывает на другой домен: проверенные причины
Neaptide · 4 октября 2026 г. · 9 мин чтения · Обновлено: 13 октября 2026 г.
Проверили восемь конфигураций метаданных Next.js по HTML и DOM браузера. Показываем причины неверного canonical, исправления и данные эксперимента.
В этой статье

Если страница Next.js выдаёт canonical на старом домене, изменение metadataBase может ничего не исправить. В нашем сценарии с абсолютным URL старый адрес сохранился при правильной базе. Помогло изменение alternates.canonical страницы. Сначала посмотрите, какой адрес приложение действительно выдаёт, затем найдите настройку, из которой он берётся.
Что мы проверили
4 октября 2026 года мы собрали отдельный стенд App Router на Next.js 15.5.22, React 19.2.6 и Node.js v25.2.1. До замеров задали восемь конфигураций: одну исправную контрольную и семь с намеренно внесёнными ошибками. В одной production-сборке у каждой есть варианты до и после изменения. В каждой паре меняли одну настройку метаданных; контроль оставили прежним.
Каждый адрес запросили дважды: 32 HTTP-ответа для 16 URL. Затем проверили все 16 документов в браузере. Во всех ответах был статус 200 и ровно один canonical в head; повторные запросы и DOM совпали. После соответствующих изменений семь намеренных расхождений исчезли. Это проверка заданных конфигураций, а не исследование распространённости ошибок на сайтах.
Пути /cXX/before и /cXX/after разделяют сценарии стенда. Заданные canonical используют зарезервированные домены example.com и демонстрационные пути товаров, а не повторяют локальные URL. Сам стенд имеет noindex, nofollow.
Восемь конфигураций и фактические адреса
| Сценарий / конфигурация | До: выданный canonical | После: выданный canonical |
|---|---|---|
| C01 · Правильная база и относительный путь — контроль | https://www.example.com/products/widget | https://www.example.com/products/widget |
| C02 · Неверный домен базы | https://preview.example.com/products/widget | https://www.example.com/products/widget |
| C03 · Старый абсолютный canonical | https://old.example.com/products/widget | https://www.example.com/products/widget |
| C04 · Canonical главной унаследован от layout | https://www.example.com | https://www.example.com/products/widget |
| C05 · Вложенный layout заменяет корневую базу | https://legacy.example.com/products/widget | https://www.example.com/products/widget |
| C06 · Лишний путь в metadataBase | https://www.example.com/catalog/products/widget | https://www.example.com/products/widget |
| C07 · Пропущен языковой префикс /fr | https://www.example.com/products/widget | https://www.example.com/fr/products/widget |
| C08 · Preview-домен из окружения сборки | https://preview.example.com/products/widget | https://www.example.com/products/widget |
Статус HTTP 200 не отличал правильные метаданные от ошибочных: его вернули все страницы стенда. Проверяйте полный адрес, включая путь и язык. В C04 Next.js выдал адрес главной без завершающего слеша; для заданной карточки товара он всё равно оставался неверной целью.
Найдите настройку, которая задаёт неверную часть URL

Другой домен при относительном canonical — C02, C05 и C08. Проверьте metadataBase в корневом и вложенных layout. В C05 удаление вложенного переопределения вернуло правильную корневую базу. В C08 контролируемая переменная сборки задавала preview-домен; замена этого источника на нужный production-домен исправила результат.
Другой домен при абсолютном canonical — C03. Страница уже содержала полный старый URL, поэтому правильная metadataBase его не заменила. Исправьте это значение или источник, который его формирует, и снова проверьте выданный тег.
Карточка товара указывает на главную — C04. Дочерняя страница унаследовала canonical из layout. Собственное alternates.canonical страницы вернуло нужный путь товара. Проверьте затронутые шаблоны: настройка главной сама не становится адресом каждой страницы.
Домен правильный, путь неверный — C06 и C07. Префикс /catalog в базе остался в итоговом URL, хотя значение canonical начиналось с /. Удаление лишнего пути базы исправило C06. Добавление пропущенного /fr исправило C07. Нужные вашему размещению префиксы сохраняйте.
Небольшая явная конфигурация для адаптации
Для сайта в корне домена задайте базовый адрес в layout, а путь страницы — в её метаданных. Ниже исправленный вариант C02. Замените демонстрационные домен и путь своими; для сайта в подпапке отдельно определите правила путей.
// app/layout.tsx
export const metadata = {
metadataBase: new URL("https://www.example.com"),
};
// app/products/widget/page.tsx
export const metadata = {
alternates: { canonical: "/products/widget" },
};Если страница содержит старый абсолютный URL из следующего примера, одной правки layout недостаточно. В C03 мы изменили только это значение canonical.
// C03 — before
alternates: {
canonical: "https://old.example.com/products/widget"
}
// C03 — after
alternates: {
canonical: "https://www.example.com/products/widget"
}Проверьте собранную страницу и документ браузера
- Соберите production-версию с той конфигурацией публичного домена, которая нужна при размещении. Если хостинг, middleware или CDN меняют ответ, проверьте и опубликованный URL.
- Сохраните HTTP-ответ и проверьте canonical в head: полный href, число тегов и заголовок ответа Link, если он задаёт дополнительный canonical.
- В инструментах разработчика браузера проверьте итоговый документ. Выражение ниже перечисляет теги и их расположение. Расхождение HTML и DOM требует отдельного разбора.
- Повторите проверку после изменения. Возьмите карточки, вложенные пути и переводы, а не только главную. Рядом с каждым результатом сохраните фактический и ожидаемый адрес.
Array.from(document.querySelectorAll('link[rel="canonical"]'))
.map(link => ({
href: link.getAttribute("href"),
inHead: link.closest("head") !== null
}));C08 проверяет значение переменной, а не инфраструктуру Vercel. Управление индексацией preview — отдельная задача: Vercel описывает стандартный noindex для preview и исключение для собственных доменов на непроизводственных ветках. Для вывода о хостинге проверьте реальные заголовки размещённой версии.
Чего эксперимент не показывает
Результаты относятся к одной установленной версии, статическим экспортам метаданных и локальному production-серверу. Мы не проверяли streaming metadata, Pages Router и все платформы размещения. Совпадение canonical с заданным адресом не доказывает, что Google выберет его, проиндексирует страницу или повысит позиции. Google описывает канонизацию как процесс с несколькими сигналами; выбранный им URL проверяйте отдельно в Search Console при наличии доступа.
Данные, стенд и повторение эксперимента
Дополнительное повторение 13 октября 2026 года: точную архивную копию стенда зафиксировали Git-коммитом перед новой сборкой. Все 32 HTTP-наблюдения canonical и 16 проверок DOM совпали с исходными результатами. Отдельно датированные доказательства включены в архив; исследование от 4 октября сохранено без изменений.
В комплекте — зафиксированный протокол, хеши исходников, результаты и запускаемый стенд. Скрипт собирает HTTP-ответы; проверка браузера описана отдельным шагом. Прямые зависимости закреплены, но все транзитивные зависимости отдельного пакета полностью не зафиксированы.
Если проблема затрагивает несколько шаблонов
Передайте разработчику конкретную запись: URL страницы, выданный canonical, нужный адрес, ответственную настройку и повторную проверку. Если задействованы layout, переводы и окружения размещения, наш SEO-аудит Next.js поможет составить карту зависимостей и очередь внедрения.
Если метаданные оказались в body, наш эксперимент с девятью условиями Next.js поможет разделить исходный HTML и DOM, а также проверить положение canonical с учётом требований Google.