Перейти к содержимому

Страница 404 - код ответа, свой шаблон, мягкие ошибки

Делаем страницу 404 так, чтобы посетитель видел понятный текст, а поисковая система - настоящий код ошибки вместо обычной страницы.

Что нужно знать заранее

У ошибки есть две стороны: что видит человек и что видит робот. Человеку нужен понятный текст со ссылками, роботу - код ответа, по которому он поймёт, что страницы больше нет.

Мягкая ошибка - это красивая страница ошибки с кодом успешного ответа. Поисковая система считает её обычной страницей и держит в индексе, а вебмастер потом удивляется тысячам пустых адресов в отчётах.

Страница ошибки живёт отдельным файлом в корне сайта и подключается платформой. Настройка обработки ошибки включается в административном разделе, а сам файл верстают как обычную страницу.

Шаги

  1. Проверить, какой код ответа отдаёт несуществующий адрес сайта прямо сейчас.
  2. Включить обработку ошибки в настройках продукта и завести файл страницы ошибки.
  3. Поставить в этот файл установку кода ответа выше любой строки вывода разметки.
  4. Отдавать ошибку прямо из кода там, где элемент или раздел не найден.
  5. Смотреть журнал веб-сервера и чинить битые ссылки на страницах самого сайта.

Решение

Проверяем код ответа несуществующего адреса:

Окно терминала
curl -sI https://example.com/net-takoy-stranicy/ | head -1
# ожидаем HTTP/1.1 404 Not Found, а не 200 OK и не 302 Found
curl -sI https://example.com/catalog/net-takogo-tovara/ | head -1
# карточку несуществующего товара проверяют отдельно: там своя обработка

Проверка занимает секунду и снимает главный вопрос всего разбора. Красивая страница с кодом успешного ответа - самая частая ошибка: она выглядит правильно в браузере и неверна для поисковой системы.

Ставим код ответа в файле страницы ошибки:

// /404.php в корне сайта, до вывода разметки
define('ERROR_404', 'Y');
require $_SERVER['DOCUMENT_ROOT'] . '/bitrix/header.php';
\CHTTP::SetStatus('404 Not Found'); // настоящий код ответа для робота
$APPLICATION->SetTitle('Страница не найдена');

Установка кода идёт до вывода разметки страницы. После первой строки вывода заголовки ответа уже отправлены, и поменять их не получится ни в шаблоне, ни в компоненте.

Отдаём ошибку из кода при отсутствии элемента:

$element = CIBlockElement::GetList([], ['IBLOCK_ID' => $iblockId, 'ID' => $id], false, false, ['ID'])->Fetch();
if (!$element) {
\Bitrix\Iblock\Component\Tools::process404('', true, true, true, '/404.php');
}
// пустая карточка с кодом успешного ответа хуже, чем честная ошибка

Штатный вызов делает сразу три вещи: показывает страницу ошибки, ставит код ответа и пишет запись в журнал. Свой код с одной установкой заголовка обычно забывает про журнал и про сам вывод страницы.

Смотрим частые ошибки в журнале веб-сервера:

Окно терминала
awk '$9 == 404 {print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
# верхние строки - это чаще всего битые ссылки на самом сайте, а не боты

Верхние адреса в этом списке почти всегда приходят с самого сайта. Их чинят в меню, в карточках товаров и в письмах, а не закрывают правилом перенаправления на главную страницу.

Ставим редирект там, где адрес действительно сменился:

location = /old-catalog/ { return 301 /catalog/; }
# перенаправление уместно для переехавшей страницы, а не вместо ошибки

Перенаправление и ошибка решают разные задачи. Страница переехала - код перенаправления, страница исчезла - код ошибки, и подмена одного другим путает и поисковую систему, и посетителя.

Типичные проблемы

Несуществующий адрес отвечает кодом успешной страницы.

Обработка ошибки включена, но установки кода ответа в файле страницы нет вовсе. Код ответа ставят до вывода разметки, первой же строкой файла ошибки.

Вместо ошибки посетителя уводит на главную страницу.

Настроено перенаправление на главную вместо показа страницы ошибки. Поисковая система при этом считает старые адреса живыми и держит их в индексе.

Карточка несуществующего товара открывается пустой.

Компонент не проверяет наличие элемента и потому не отдаёт ошибку. Отсутствие элемента обрабатывают штатным вызовом страницы ошибки до вывода разметки.

Код ответа не меняется, хотя вызов в коде есть.

Часть страницы уже выведена, и заголовки ответа отправлены браузеру. Проверку наличия элемента делают до вывода, в самом начале страницы.

После включения композита ошибка снова отдаёт успешный код.

Страница ошибки попала в кэш готовых страниц и отдаётся оттуда. Такие страницы из композитного кэша исключают явным образом, отдельной настройкой.

Частые вопросы

Обязательно ли делать свою страницу ошибки?

Да, иначе посетитель видит служебный текст веб-сервера и уходит. Своя страница со ссылками на разделы и поиском возвращает часть посетителей на сайт.

Чем 404 отличается от 410?

Первый код означает «страницы нет», второй - «удалена навсегда». Для товаров, снятых с продажи, иногда берут второй, но большинству проектов хватает обычной ошибки.

Нужно ли закрывать 404 от индексации?

Нет, правильный код ответа уже говорит роботу всё нужное. Дополнительные запреты только усложняют настройку и ничего не дают.

Что делать со старыми адресами после переезда?

Ставить перенаправление на новый адрес, а не отдавать ошибку. Ошибка уместна там, где замены странице нет вовсе.

Как найти битые ссылки внутри сайта?

По журналу веб-сервера с отбором по коду ошибки и по обходу сайта краулером. Первое дешевле и показывает то, по чему реально ходят посетители.

Смежное

Первоисточник