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

Редиректы внутри сайта - 301 на раздел, https и старые адреса

Настраиваем переходы со старых адресов на новые так, чтобы поисковая система поняла переезд, а посетитель не собирал цепочку из трёх переходов.

Решение

Ставим правило на веб-сервере:

location = /old-catalog/ { return 301 /catalog/; }
location ^~ /news/ { rewrite ^/news/(.*)$ /articles/$1 permanent; }
# правило веб-сервера отрабатывает до PHP и не тратит процесс на запрос
# порядок блоков важен: точное совпадение выигрывает у префикса

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

Переносим старые адреса таблицей соответствий:

$map = [
'/katalog/' => '/catalog/',
'/o-kompanii/' => '/about/',
];
$uri = $APPLICATION->GetCurPage();
if (isset($map[$uri])) {
LocalRedirect($map[$uri], false, '301 Moved Permanently'); // без третьего параметра будет 302
}

Третий параметр обязателен: без него уходит временный переход, и поисковая система старый адрес из выдачи не убирает. Сотни правил в таком виде держат в файле или таблице, а не в коде страницы.

Включаем https одним правилом:

server {
listen 80;
server_name example.com www.example.com;
return 301 https://example.com$request_uri; # сразу на нужный домен и протокол
}

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

Проверяем, что получилось:

Окно терминала
curl -sIL https://example.com/old-catalog/ | grep -E 'HTTP/|location'
# в выводе должна быть одна строка перехода, а не три подряд
curl -sI http://example.com/old-catalog/ | head -3
# отдельно проверяем адрес без шифрования: он тоже должен вести на конечный

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

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

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

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

Поисковая система держит в выдаче старый адрес.

Переход со старого адреса отдаётся временным кодом вместо постоянного. Временный переход означает «адрес ещё вернётся», и замену адреса в индексе он не запускает.

Правило в коде не срабатывает.

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

Между старым и новым адресом три перехода.

Правила протокола, домена и самого адреса написаны отдельными шагами. Их объединяют в одно правило, ведущее сразу на конечный адрес.

Старый адрес открывается без перехода.

Страница отдаётся композитным кэшем ещё до попадания запроса в PHP. Композитный кэш сбрасывают после каждой смены правил перехода.

Ошибочный переход остался после отката правила.

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

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

Где лучше ставить правила: на сервере или в коде?

На сервере, если правил немного и они статичны. Код нужен там, где адрес считается по данным сайта.

Сколько правил выдержит конфигурация веб-сервера?

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

Нужен ли редирект при смене адреса раздела?

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

Что делать со страницами фильтра в выдаче?

Закрывать от индексации ненужные сочетания, а не переводить их переходами. Переход с рабочей страницы фильтра ломает саму фильтрацию.

Смежное

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