Давно бились над проблемой с SEO и применением стандартных комплексных компонентов (bitrix:news, bitrix.catalog) при использовании ЧПУ.
Проблема заключалась вот в чем: при отдаче страницы с отсутствующим элементом или секцией инфоблока выставляется статус «404 Not Found» (в теле компонентов bitrix:news.list, bitrix:news.detail, bitrix:catalog.section, bitrix:catalog.element есть соответствующие строки, но к сожалению не было способа показать тело 404-ой страницы (мы обычно создаем страницу /404.php) с ее оформлением и пр.
Поначалу нас устраивал редирект на эту страницу вида:
LocalRedirect("/404.php", "404 Not Found");
но чтобы им воспользоваться приходилось создавать дубликаты компонентов в своем пространстве имен (anima:catalog.section, например).
Потом было найдено более изящное решение, не задевающее компоненты. В стандартных компонентах используется определение константы ERROR_404 в случае проблем с поиском инфоблока, секии, элемента во время выполнения компонента, но по заверениям разработчиков она используется исключительно для статистики. Однако, отображение стрницы – единый runtime и определенные константы можно использовать практически в самом его (runtime-a) конце. Результатом этих роазмышлений стал код в init.php:
/* Неочевидное перенаправление на страницу 404-ой ошибки */ AddEventHandler("main", "OnEpilog", "Redirect404"); function Redirect404() { if(defined("ERROR_404") ) { LocalRedirect("/404.php", "404 Not Found"); } }
Довольно легко для понимания и универсально и работает везде, но… У данной конструкции (у редиректа) естьи темные стороны.
- Пользователь сайта, случайно вбив ошибочный длинный URL перебрасывался на /404.php без возможности увидеть и исправить ошибку в строке адреса.
- Поисковой робот, придя на ошибочную страницу видел странную последовательность: при обращении к несуществующей странице он получал статус 301 Moved Permanently (в редких случаях «404 Not found»
и переадресацию на страницу /404.php, которая выставляла статус «404 Not found». Немного путано.
Тогда появилась идея: в функции Redirect404() очистить буфер вывода с помощью $APPLICATION->RestartBuffer(); и «заинклюдить» /404.php. Но тут на словах оказалось проще, чем на деле. Беда крылась в том, что пролог и эпилог сайта вызываются через конструкцию require_once и повторно вызвать их (для отображения шапки, футера, стилей на заветной 404-ой странице) оказалось невозможно; другими словами мы теряли, к примеру, меню, вставленное в визуальную часть пролога (header.php шаблона).
Путем экспериментов, проб и ошибок мы пришли к довольно универсальной записи:
AddEventHandler("main", "OnEpilog", "Redirect404"); function Redirect404() { if( !defined('ADMIN_SECTION') && defined("ERROR_404") && defined("PATH_TO_404") && file_exists($_SERVER["DOCUMENT_ROOT"].PATH_TO_404) ) { //LocalRedirect("/404.php", "404 Not Found"); global $APPLICATION; $APPLICATION->RestartBuffer(); CHTTP::SetStatus("404 Not Found"); include($_SERVER["DOCUMENT_ROOT"].SITE_TEMPLATE_PATH."/header.php"); include($_SERVER["DOCUMENT_ROOT"].PATH_TO_404); include($_SERVER["DOCUMENT_ROOT"].SITE_TEMPLATE_PATH."/footer.php"); } }
Внимательный зритель заметит, что в функции появилась константа PATH_TO_404. Определять данную константу предлагается первой строкой в визуальной части пролога:
<? $bIndexPage = ($_SERVER["SCRIPT_NAME"] == "/index.php" ? true : false); define("PATH_TO_404", "/404.php"); ?> ... <!DOCTYPE html>
Кстати, переменная $bIndexPage может сослужить полезную службу при выводе шаблона с различными наборами компонентов на главной и внутренних страницах при единообразии прочего содержимого и стилей.
Есть физический раздел — НОВОСТИ.
В нем мы вызываем компонент:
$APPLICATION->IncludeComponent(
"bitrix:news.list",
"articles",
array(
"ACTIVE_DATE_FORMAT" => "d.m.Y",
"ADD_SECTIONS_CHAIN" => "Y",
"AJAX_MODE" => "Y",
"AJAX_OPTION_ADDITIONAL" => "",
"AJAX_OPTION_HISTORY" => "Y",
"AJAX_OPTION_JUMP" => "N",
"AJAX_OPTION_STYLE" => "Y",
"CACHE_FILTER" => "N",
"CACHE_GROUPS" => "Y",
"CACHE_TIME" => "36000000",
"CACHE_TYPE" => "A",
"CHECK_DATES" => "Y",
"DETAIL_URL" => "",
"DISPLAY_BOTTOM_PAGER" => "Y",
"DISPLAY_DATE" => "N",
"DISPLAY_NAME" => "Y",
"DISPLAY_PICTURE" => "Y",
"DISPLAY_PREVIEW_TEXT" => "Y",
"DISPLAY_TOP_PAGER" => "N",
"FIELD_CODE" => array(
0 => "ID",
1 => "CODE",
2 => "NAME",
3 => "PREVIEW_TEXT",
4 => "PREVIEW_PICTURE",
5 => "",
),
"FILTER_NAME" => "",
"HIDE_LINK_WHEN_NO_DETAIL" => "N",
"IBLOCK_ID" => "15",
"IBLOCK_TYPE" => "custom",
"INCLUDE_IBLOCK_INTO_CHAIN" => "N",
"INCLUDE_SUBSECTIONS" => "Y",
"MESSAGE_404" => "",
"NEWS_COUNT" => "12",
"PAGER_BASE_LINK_ENABLE" => "N",
"PAGER_DESC_NUMBERING" => "Y",
"PAGER_DESC_NUMBERING_CACHE_TIME" => "36000",
"PAGER_SHOW_ALL" => "N",
"PAGER_SHOW_ALWAYS" => "N",
"PAGER_TEMPLATE" => ".default",
"PAGER_TITLE" => "Советы",
"PARENT_SECTION" => "",
"PARENT_SECTION_CODE" => "",
"PREVIEW_TRUNCATE_LEN" => "",
"PROPERTY_CODE" => array(
0 => "",
1 => "",
),
"SET_BROWSER_TITLE" => "Y",
"SET_LAST_MODIFIED" => "N",
"SET_META_DESCRIPTION" => "Y",
"SET_META_KEYWORDS" => "Y",
"SET_STATUS_404" => "Y",
"SET_TITLE" => "Y",
"SHOW_404" => "Y",
"SORT_BY1" => "SORT",
"SORT_BY2" => "ID",
"SORT_ORDER1" => "DESC",
"SORT_ORDER2" => "ASC",
"COMPONENT_TEMPLATE" => "articles"
),
false
);
Параметр SHOW_404 не должен работать в том случае, когда мы вводим неправильный url в детальном описании новости?
Если это не помогает, как тогда сделать? (нужно вместо «элемент не найден» выводить 404 ошибку)
Почитал посты, говорят — нужно прописать некую функцию в init.php и в шаблоне компонента проверять…
Только таким способом? Штатными методами не решить проблему?
Версия битрикс: 17.0.5
Проблема — компоненты при возникновении 404й ошибки не отдают 404.php.
Проблема 404-ой страницы на сайтах под управлением 1С-БУС известна давно, и до недавнего времени не имела валидного решения. Сегодня я расскажу о текущем способе перехвата 404-ой ошибки и вывода пользователю нужной страницы.
Начнем по порядку.
404 & Bitrix:catalog.
Первичная настройка.
Для начала пройдемся по настройкам ИБ и компонента.
Настройки инфоблока
- «URL страницы информационного блока» — тут вроде все понятно, просто указываем каталог из которого происходит вызов компонента для этого ИБ.
- «URL страницы раздела» — тут нужно быть аккуратным, если все элементы ИБ лежат в корне раздела, то мы не можем использовать.
- «#SECTION_CODE#» — при такой настройке роутер компонента будет путать разделы и элементы ИБ. Чтобы этого не происходило мы используем «#SECTION_CODE_PATH#».
- «URL страницы детального просмотра» — т.к. мы кладем все элементы в корень, то здесь используется только «#ELEMENT_CODE#».
На этом с настройками ИБ закончили.
Настройки компонента
- «Каталог ЧПУ» — соответственно раздел в котором происходит вызов компонента
- «Раздел» — повторяем настройку из ИБ, но перед «#» не ставим слеш «/», в противном случаи компонент будет работать не верно!
- «Детальная информация» — повторяем настройку из ИБ, но перед «#» не ставим слеш «/», в противном случаи компонент будет работать не верно!
- И не забудем про «волшебную галочку».
С настройками компонента закончили.
Теперь о грустном — 404й статус мы вроде как получаем, но компонент не спешит перебрасывать нас на 404.php, а просто пишет что раздел или элемент не найден.
А нам то нужно отобразить 404ю, чтобы юзер понял что что-то пошло не так, показать ему доп менюшку и т.д.
Решение проблемы.
Для решения этой проблемы мы воспользуемся механизмом событий 1С-БУС.
//событие "ловушка" для 404й AddEventHandler('main', 'OnEpilog', '_Check404Error', 1); function _Check404Error(){ if(defined('ERROR_404') && ERROR_404=='Y' || CHTTP::GetLastStatus() == "404 Not Found"){ GLOBAL $APPLICATION; $APPLICATION->RestartBuffer(); require $_SERVER['DOCUMENT_ROOT'].SITE_TEMPLATE_PATH.'/header.php'; require $_SERVER['DOCUMENT_ROOT'].'/404.php'; require $_SERVER['DOCUMENT_ROOT'].SITE_TEMPLATE_PATH.'/footer.php'; } }
В эпилоге мы запускаем проверку на установку константы «ERROR_404» и ее текущее значение, а также проверяем последний выставленный статус, это позволяет выловить всевозможные проявления 404й ошибки у 1С-БУС. Далее мы рестартуем HTML буфер подготовленный системой для вывода. Подключаем хедер текущего шаблона, подгружаем тело 404й страницы, а затем подключаем футер текущего шаблона.
Данный подход позволяет сохранить текущий URL, шаблон и навигацию, поэтому пользователь легко сможет перейти обратно в рабочий раздел, а также в контентной области отображаем тело 404й страницы, это дает понять что запрошенной страницы действительно нет.
404 & Bitrix:news.
К сожалению компонент Bitrix:news пока не умеет адекватно отдавать хотя бы голый 404й статус, мы в поиске решения.
Одна из проблем, которая возникает при настройке 404 ошибки для Битрикс: движок наотрез отказывается отдавать 404 ошибку, если секция (раздел) не существует. Вместо 404 мы видим список всех элементов. Например:
Существующий адрес /news/about/
выводит новости только раздела about, а не существующий адрес /news/blablabla/
выдаст абсолютно все элементы из всех категорий. Причем параметры для вывода ошибки установлены верно:
"SET_STATUS_404" => "Y", "SHOW_404" => "Y",
Как оказалось, сообщения об этом баге можно встретить на форуме еще в 2009 году. А исправить ошибку достаточно просто: просто добавьте параметр "STRICT_SECTION_CHECK" => "Y",
в компонент news.list.
Например, если этот баг встречается в компоненте bitrix:news, то переходим в шаблон, находим файл section.php, который отвечает за вывод раздела и в параметрах компонента news.list добавляем «STRICT_SECTION_CHECK» => «Y». Все, страница с неверным адресом будет отдавать ошибку.
Самое забавное, что такой параметр даже не описывается в документации, что крайне прискорбно.
Очень важным вопросом при SEO продвижении сайта является 404 статус несуществующих страниц сайта.
В Битрикс при заходе на страницы, где не размещен комплексный компонент, ошибка 404 отдается нормально. А вот где есть комплексный компонент, есть проблемы, поэтому нужно знать как правильно сделать настройки.
Первым делом в настройках комплексного компонента bitrx:news или bitrix:catalog устанавливаем отдачу 404 ошибки:
Далее нужно правильно настроить ЧПУ инфоблока из которого выводится контент и включить поддержку ЧПУ в комплексном компоненте. Будем рассматривать компонент bitrix:catalog.
Установим следующие настройки в инфоблоке и тоже самое зададим в настройках компонента.
Если для вывода раздела использовать шаблон #SECTION_CODE#, то получим следующее:
/catalog/section/element/ - элемент. 200 OK /catalog/section/element123/ - элемент. ошибка 404 /catalog/section123/element/ - элемент. 200 OK
/catalog/section/ - раздел. 200 OK
/catalog/section123/ - раздел. 200 OK
Поэтому правильным вариантом будет использовать шаблон #SECTION_CODE_PATH#.
С этим шаблоном получим следующее:
/catalog/section/element/ - элемент. 200 OK /catalog/section/element123/ - элемент. ошибка 404 /catalog/section123/element/ - элемент. ошибка 404 /catalog/section/ - раздел. 200 OK /catalog/section123/ - раздел. ошибка 404
Результат отличный. Делаем вывод, что лучше использовать #SECTION_CODE_PATH#. Однако при использовании компонента bitrix:news, даже с такой настройкой будут некоторые неисправимые проблемы:
/news/section/element/ - элемент. 200 OK /news/section/element123/ - элемент. ошибка 404
/news/section123/element/ - элемент. 200 OK
/news/section/ - раздел. 200 OK
/news/section123/ - раздел. ошибка 404