SEO-оптимизаторы рекомендуют сообщать поисковикам какая страница является предыдущей и следующей через теги rel="next" и rel="prev" (rel=prev/next). В Битриксе штатной такой функции нету. Кто-то пытается сделать rel=next/prev прямо на ссылках в пагинации. Но такая затея довольно сомнительная, т.к гугл просит размещать код в head (https://support.google.com/webmasters/...3744?hl=ru) Можно править шаблоны компонентов каталога и новостей, но что если шаблонов очень много? Хотелось бы всё это ставить в одном месте. И недавно за обедом пришла идея такая реализации.
При прочтении будьте внимательны. Редактор статьи в некоторые link поставил пробелы. В реальности их быть не должно.
Способ размещения rel=prev/next в <head> (работает при кешировании и без) 1) В шаблоне пагинации через html-комментарии ставим признак пагинации и признак последней страницы пагинации. В моём случае признак пагинации это <!-- has_stranation_pagen_1 --> Признак последней страницы пагинации <!-- it_last_page_stranation -->
Код установки признаков в шаблоне пагинации
//Выводим метки для добавления <li nk rel="prev/next">: начало
$nav_index = (int)$arResult['NavNum'];
$quantity_pages = (int)$arResult['NavPageCount'];
//смотрим номер страницы в параметрах. в случае указания неверной страницы, компонент вернёт первый номер страницы,
//а нам нужен введённый номер. для неправильного номера флаг странация не выводится
$current_page = 1;
if(isset($_GET['PAGEN_'.$nav_index]) && (int)$_GET['PAGEN_'.$nav_index]>1) $current_page = (int)$_GET['PAGEN_'.$nav_index];
if($quantity_pages>1 && $current_page>=1 && $current_page<=$quantity_pages)
{
echo '<!-- has_stranation_pagen_'.$nav_index.' -->';
if($current_page >= $quantity_pages) echo '<!-- it_last_page_stranation -->';
}
//Выводим метки для добавления <li nk rel="prev/next">: конец
2) В файле /bitrix/php_interface/init.php в обработчике onepilog смотрим что хранится в буфере страницы. Если там есть признак пагинации, то ставим ссылки rel=prev/next Пример кода обработчика:
AddEventHandler("main", "OnEpilog", "vova_page_epilog");
function vova_page_epilog()
{
global $APPLICATION;
//Проверка на 404 страницу
$is_page_404 = false;
if(defined("ERROR_404")==true) $is_page_404 = true;
//Добавление тегов rel=prev/next: начало
if($is_page_404==false )
{
$page_content = ob_get_contents();
if($page_content!=false && strpos($page_content, '<!-- has_stranation_pagen_1 -->')!==false)
{
//Номер текущей страницы
$current_page = 1;
if(isset($_GET['PAGEN_1']) && (int)$_GET['PAGEN_1']>1) $current_page = (int)$_GET['PAGEN_1'];
//Проверка на последнюю страницу
$it_last_page = false;
if(strpos($page_content, '<!-- it_last_page_stranation -->')!==false) $it_last_page = true;
//Следующая страница
if($it_last_page==false)
{
$element_url = 'http://'.$_SERVER['HTTP_HOST'].$APPLICATION->GetCurPageParam('PAGEN_1='.($current_page+1), array('PAGEN_1'));
$APPLICATION->AddHeadString('<li nk rel="next" href="'.$element_url.'" />', true);
}
//Предыдущая страница
if($current_page>1)
{
if($current_page==2)
{
$element_url = 'http://'.$_SERVER['HTTP_HOST'].$APPLICATION->GetCurPageParam('', array('PAGEN_1'));
//очистка на случай, если останется последний символ ?
$element_url = trim($element_url, '?');
}
else $element_url = 'http://'.$_SERVER['HTTP_HOST'].$APPLICATION->GetCurPageParam('PAGEN_1='.($current_page-1), array('PAGEN_1'));
$APPLICATION->AddHeadString('<li nk rel="prev" href="'.$element_url.'" />', true);
}
}
}
//Добавление тегов rel=prev/next: конец
}
Если у вас на сайте кеш, то после правок его нужно почистить.
Теперь тестируем. тут важно проверить четыре момента: 1) Страницу без пагинации (не должно выводиться rel="next" и rel="prev") 2) Пагинацию на странице 1 (должен вывестись только rel="next") 3) Пагинацию на серединных страницах (должен вывестись rel="prev" и rel="next") 4) Пагинацию на последней странице (должен вывестись только rel="prev")
Добавлено 20 декабря 2016 В комментариях к статье Олег и Евгений дали очень дельные замечания. Поиск по html-коду даёт определённую нагрузку на сервер. Маленькую, но всё-же даёт. Если вы правите своё знакомый сайт и шаблонов не много, то более подходящий способ будет способ Олега через правку шаблона компонента (см. в комментариях)
Владимир Беглецов написал: Но ошибку у вас всё-равно нашёл - если у компонента не указана категория (а это частый случай), то в canonical будет записан адрес главной страницы сайта. То есть выведется неправильный адрес канонической ссылки.
Не-а. В таком случае SECTION_SECTION_PAGE_URL будет равен null, что не выведет canonical вовсе.
Олег Максименко написал: Не-а. В таком случае SECTION_SECTION_PAGE_URL будет равен null, что не выведет canonical вовсе.
Верно, а вместе с каноникал в данном случае не выведутся rel=prev/next. Хотя пагинация там будет.
И второй момент. Если, например, catalog.section использовать для вывода товаров в продвигаемых seo-разделах "Новинки" или "Акции" и там указать категорию, то каноникал укажется неверный. Он поставится от страницы указанной категории. Допустим, страница "Новинки кормов" это не есть раздел "Корма", но в каноникал установится адрес кормов.
Ничего что вы пользуетесь поиском в сгенерированном html? который может быть за 10 000 строк? и что это мможет серьёзно сказаться на происзодительности?
Евгений Микулич написал: Ничего что вы пользуетесь поиском в сгенерированном html? который может быть за 10 000 строк? и что это мможет серьёзно сказаться на происзодительности?
Тут много факторов, которые влияют на решение. Начиная от количества компонентов/сайтов и заканчивая средним объёмом страниц. Если страница большая, то нужно будет замерять скорость и выбирать оптимальное решение. Но 10 тыс строк с длиной строки в 100 символов в кодировке utf-8 это примерно 2 Мб. В таком случае нужно беспокоится не за поиск, а за пользователя и за деньги клиента, которые он, возможно, теряет. При значительном весе (больше 100 кб) нужно либо сокращать документ и делать замеры, либо внедрять rel=next/prev через шаблон.
Владимир Беглецов, pro-poly.ru без должной ранее оптимизации код как раз был 10 000 строк, или 20 я не помню, и такое решение не подошло, но и сейчас на 6000+ строк оно не подойдёт.
Владимир Беглецов, К тому же это всё можно сделать более производительно через отложенные функции, которые в битриксе поддерживаются, и хотя бы обработются за один проход
Евгений Микулич написал: pro-poly.ru без должной ранее оптимизации код как раз был 10 000 строк, или 20 я не помню, и такое решение не подошло, но и сейчас на 6000+ строк оно не подойдёт.
Мы видимо о разных вещах говорим. Под сложностью я понимаю не объём html, а размерность сайта в доменах/компонентах. Большой сайт это типа hyundai-avtomir.ru, к которому прикручены ещё 15 дилерских сайтов (каждый на своём домене). И вот попробуйте для каждого сайта прописать rel=prev/next, ничего не пропустив и не сломав. Безусловно в своём замечании вы абсолютно правы. Поиск значительно медленнее, чем реализация в компоненте через отложенные функции. Но я в статьи не указывал, что решение самое оптимальное. Я писал, что оно наиболее гладкое, т.е меньше вероятность чего-то упустить. Для хорошо знакомого сайта скорее всего идеальное решение будет как у Олега (см. комментарии выше), а для незнакомого с большим количеством шаблонов мне проще использовать способ из статьи. Но тут много побочных факторов (посещаемость, например)
Владимир Беглецов, я ещё раз повторю на каждую страницу вы используете поиск strpos это нифига не простая операция когда входной текст, когда в нём лежит весь html код, к тому же это делается на всех страницах, даже там где пагинациинет. Метод у Олега как раз основан на функциях обратного вызова и не вызывается везде подряд.
когда несколько компонентов постраничных (новости, блог, каталог), лень менять во всех местах, поэтому сделала так: В шаблоне компонента system.pagenavigation
И зачем мучаться с протоколами, ведь HREF может быть в виде абсолютных и относительных ссылок. И если это указано в базе данных в документе, относительные URL будут просчитаны в соответствии с базовыми.
Малышева Вероника, href да, но не каждого SEO'шника получается в этом убедить)))
По вашему коду: у вас на второй странице будет задняя ссылка указывать на PAGEN_1=1. SEO-шник отпишет, что появилась лишняя ненужная ссылка, которая дублирует более важную ссылку
Позволяет красиво обработать постраничную навигацию, создавать страницы типа /page-2/, /stranica-2/ и при этом соблюсти все рекомендации Google для постраничной навигации, добавить теги rel=next/prev/canonical на страницы с постраничкой!
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».