В блоге шестьдесят постов, по двенадцать на странице, — значит, страниц пять. На первой двенадцать постов, до остальных сорока восьми добираются через пагинацию. Если поисковый робот не может по ней пройти, старые посты доступны ему только через карту сайта и ссылки из других мест. А пост, на который ничто не ссылается, поисковику почти незачем показывать высоко.
В большинстве блогов пагинация либо устроена так, что робот по ней не пройдёт, либо прямо говорит ему не утруждаться. Одну из этих ошибок я нашёл в собственном блоге, когда переделывал его в этом месяце. Ниже четыре частые ошибки, что делать вместо них, а в конце — чек-лист.
Ошибка 1: «Показать ещё» без адресов
Кнопка «Показать ещё» или бесконечная прокрутка, которая подгружает следующую страницу через JavaScript, приятна людям и невидима для роботов. В документации Google сказано, что он, как правило, обходит только URL из атрибута href у элементов <a>, что его роботы не нажимают на кнопки и что поиск Google не прокручивает страницу и никак иначе с ней не взаимодействует.
Если до тринадцатого поста можно добраться только кнопкой «Показать ещё», то для робота ваш блог на него вообще не ссылается.
Вместо этого: дайте каждой странице свой URL, /blog?page=2 или /blog/page/2, и ссылайтесь на неё настоящим <a href>. Кнопку «Показать ещё» можно оставить поверх: отрисуйте ссылки пагинации в HTML, а JavaScript пусть перехватывает клик и дописывает следующую страницу на месте. Робот идёт по ссылке, люди нажимают кнопку.
Ошибка 2: пагинация на кнопках
Та же проблема в другом виде:
<button onClick={() => setPage(page + 1)}>Next</button>
Кнопка меняет содержимое страницы, а URL остаётся прежним. Робот по ней не пройдёт, посетитель не сможет поделиться третьей страницей или вернуться к ней, а кнопка «Назад» в браузере проскочит её целиком.
Вместо этого: пагинация — это навигация, поэтому делайте её ссылками. Во фреймворке с серверным рендерингом это ещё и значит, что страница для ?page=2 рендерится на сервере и посты уже есть в HTML — а робот читает именно его.
Ошибка 3: все страницы указывают canonical на первую
Эта ошибка похожа на хорошую гигиену, поэтому она повсюду:
<!-- на /blog?page=2, /blog?page=3, ... -->
<link rel="canonical" href="https://example.com/blog" />
Тег canonical говорит: «эта страница — дубль, настоящая вон там». Но вторая страница не дубль первой: на ней другие посты. Если сказать поисковику обратное, он может выкинуть вторую страницу из индекса, а вместе с ней — единственные ссылки на эти посты.
В рекомендациях Google по пагинации так и написано: не указывайте первую страницу последовательности как каноническую, дайте каждой странице собственный канонический URL.
У меня была эта ошибка. До этого релиза каждая страница моего блога на kookee.dev, включая ?page=2, указывала /blog как каноническую. Теперь каждая страница без фильтров указывает canonical на себя: первая — на /blog, вторая — на /blog?page=2.
Вместо этого: на каждой странице последовательности canonical указывает на неё саму.
Ошибка 4: noindex на всех страницах после первой
Более старая версия того же рефлекса: убрать «малоценные» страницы-списки из индекса через noindex, follow, чтобы в индекс попали посты, а списки нет.
Подвох в follow. Джон Мюллер из Google говорил, что страницу, которая достаточно долго стоит под noindex, поисковик выкидывает совсем и перестаёт ходить по её ссылкам, так что noindex, follow в итоге работает как noindex, nofollow. А эти ссылки — путь к вашим старым постам.
Вместо этого: пусть страницы индексируются. Страница с двенадцатью заголовками и анонсами постов — не малоценный контент, а по запросу на тему поста поисковик скорее покажет сам пост, чем список, который на него ссылается. В документации Google также сказано, что у страниц последовательности могут быть одинаковые title и description, так что проблемы с дублями заголовков здесь нет.
А фильтры?
Теги, категории, поиск и сортировки множат URL: /blog?tag=react&page=3&q=hooks — тоже страница. Не все такие страницы нужны в индексе, а робот, который перебирает все сочетания, тратит время на вашем сайте самым бесполезным образом.
Есть два разумных варианта:
Canonical с отфильтрованных страниц на список без фильтров. Так делаю я:
/blog?tag=reactи/blog?tag=react&page=2указывают/blogкак каноническую, а страницы без фильтров — сами себя. Каждый пост остаётся доступен через последовательность без фильтров, а сочетания фильтров не путаются под ногами.Свои пути для фильтров, которые должны ранжироваться. Если страница тега — самостоятельная посадочная страница, так её и оформите: по адресу
/blog/tag/react, с canonical на себя и своей пагинацией. А фильтры в query-строке оставьте для всего остального.
Рекомендации Google допускают и noindex на отфильтрованных и пересортированных страницах. Что бы вы ни выбрали, применяйте это к фильтрам, а не к пагинации основного списка.
rel="next" и rel="prev"
В 2019 году Google объявил, что больше их не использует. В его документации отмечено, что другие поисковики могут их учитывать, но ссылок на странице они не заменяют.
На какие страницы ставить ссылки
Пагинация со всеми номерами страниц не масштабируется, а с одними «Назад» и «Далее» превращает путь до сороковой страницы в сорок кликов. Обычный компромисс: первая страница, последняя и по одной с каждой стороны от текущей, а на месте каждого пропуска — многоточие.
‹ Назад 1 … 6 [7] 8 … 15 Далее ›
По ссылке на последнюю страницу и люди, и роботы сразу попадают к самым старым постам, а последовательность можно пройти с любого конца. И всё же пагинация не гарантирует, что робот доберётся до всего, — для этого есть карта сайта: перечислите в ней каждый пост, а lastmod берите из даты, когда пост в последний раз заметно менялся.
В тот же компонент стоит заложить две детали доступности:
Оберните его в
<nav>с подписью вроде «Навигация по страницам» и отметьте текущую страницу атрибутомaria-current="page".На краях показывайте «Назад» и «Далее» неактивным текстом, а не ссылками в никуда или на страницу, где посетитель уже находится.
Чек-лист
У каждой страницы списка свой URL, а её посты есть в HTML, отрисованном на сервере.
Пагинация состоит из ссылок
<a href>. Кнопка «Показать ещё», если она есть, дополняет эти ссылки, а не заменяет их.У каждой страницы списка без фильтров canonical указывает на неё саму. Вторая страница не указывает canonical на первую.
На страницах основного списка нет
noindex.Отфильтрованные и отсортированные страницы указывают canonical на список без фильтров, закрыты
noindexили вынесены на собственные пути, если должны ранжироваться.В карте сайта есть каждый пост.
Компонент Pagination в React-пакете Kookee отрисовывает эту схему ссылками: первая и последняя страницы, по одной с каждой стороны от текущей, многоточия, подписанная навигация и неактивные края. Он работает в Server Component и до загрузки JavaScript, а getPaginationItems отдаёт тот же набор страниц для вашей собственной разметки. Полную страницу списка с фильтром по тегам и поиском смотрите в статье Блог на React-компонентах.