Как настроить 301 редиректы при смене URL и структуры сайта

Когда я меняю URL-структуру сайта, 301 редиректы у меня идут не «по остаточному принципу», а в числе первых задач. И это правильно: если пустить миграцию на самотёк, можно за пару дней потерять трафик, накопленные ссылки и половину поведенческих факторов. На деле 301 — это не просто техническая настройка, а страховка SEO, которая спасает проект после редизайна, переезда на новую CMS или нормальной чистки структуры.

У меня был клиент на Bitrix 8.1 + MySQL 8.0, у которого после смены каталога с /catalog/ на /shop/ органика просела примерно на 28% за две недели. Причина оказалась банальная: старые адреса отдавали 404, а часть редиректов вела на главную. Исправили карту переноса, выкатили корректные 301, и через 3-4 недели позиции начали возвращаться. Поэтому если вам нужен аккуратный переезд без боли, я бы советовал сразу смотреть и в сторону поддержки Bitrix, и в сторону поддержки WordPress, если проект именно на этой CMS.

Что такое 301 редирект и когда он нужен

301 редирект — это постоянное перенаправление со старого URL на новый. Браузер, поисковик и внешние сервисы понимают: страница переехала окончательно, старый адрес больше не основной. Для SEO это самый безопасный вариант при смене структуры сайта, домена, протокола или CMS.

Я обычно объясняю клиентам просто: если URL изменился, а контент остался тем же или почти тем же, 301 должен вести пользователя и робота на новую страницу. Не на главную, не на категорию «похожих товаров», а именно туда, где лежит замена. Иначе поисковик начинает путаться, а это уже прямой путь к потере индексации.

301 нужен в очень конкретных случаях:

И тут есть один момент, который часто игнорируют. 301 — это не «волшебная кнопка SEO». Он работает только тогда, когда у вас есть логика сопоставления старого и нового адреса. Если карта редиректов собрана на коленке, Google и Яндекс быстро это увидят. На практике я видел, как после неаккуратного переезда с WordPress на Bitrix весь хвост старых URL редиректился в одну категорию. Это плохая идея. Плохая и довольно дорогая.

ℹ️
Совет: перед настройкой 301 всегда фиксируйте старую структуру. Экспортируйте список URL из sitemap.xml, из логов, из Screaming Frog, из Яндекс.Вебмастера и Google Search Console. Потом сопоставляйте адреса вручную или полуавтоматически.

Как подготовить сайт к смене URL

Самая большая ошибка — сначала поменять адреса, а потом думать, куда редиректить. Я обычно делаю наоборот: сначала собираю полный список старых URL, потом проектирую новую структуру, и только затем пишу правила редиректов. Если сайт небольшой, это можно сделать за вечер. Если это интернет-магазин на 10 000 товаров, тут уже нужен нормальный план миграции, иногда вместе с переездом на другую CMS или отдельной работой по редизайну сайта.

Что я проверяю перед запуском:

У одного клиента на WordPress была классическая история: каталог товаров переехал с /product-name/ на /catalog/product-name/, но старая генерация sitemap продолжала отдавать старые URL. В итоге мы получили и редиректы, и старые ссылки в карте сайта, и несколько недель путаницы в индексации. Пришлось одновременно править редиректы, sitemap и внутренние ссылки. Это лишний раз подтверждает: 301 — только часть цепочки. Если интересна смежная тема, у меня есть отдельная статья про настройку robots.txt и про XML sitemap для SEO.

⚠️
Ошибка: не редиректите всё подряд на главную. Это убивает релевантность. Для SEO страница товара должна вести на товар, статья — на статью, категория — на категорию или ближайший аналог.

Как собрать карту редиректов без хаоса

Карта редиректов — это таблица соответствий: старый URL, новый URL, тип редиректа, комментарий. Я обычно делаю её в Google Sheets или Excel, а потом уже переношу в конфиг, в БД или в код. На проектах под Bitrix и Laravel у меня это вообще обязательный артефакт, без которого миграция не начинается.

Минимальная структура таблицы выглядит так:

old_url | new_url | type | note
/catalog/old-product/ | /shop/new-product/ | 301 | renamed product
/blog/old-article/ | /articles/new-article/ | 301 | updated structure
/about-us.html | /about/ | 301 | static page moved

Если страниц много, я делаю карту по группам:

  1. точечные редиректы для самых важных страниц;
  2. шаблонные редиректы для однотипных URL;
  3. правила для слэшей, регистра, www, http/https;
  4. правила для старых разделов, которые переехали целиком;
  5. отдельные исключения для удалённых страниц.

На моей практике лучше всего работают два подхода. Первый — ручная карта для ключевых URL, которые реально дают трафик и продажи. Второй — автоматизация правил для типовых шаблонов. Например, если все статьи были в /news/ и переехали в /blog/, то не надо писать тысячу строк вручную. Но и бездумно делать один общий шаблон нельзя. Иначе часть адресов начнёт попадать не туда.

Если у вас сайт на 1С-Битрикс, я бы ещё отдельно посмотрел статью как обновить Битрикс без потери данных, потому что при обновлении и изменении структуры часто всплывают именно URL-коллизии. А если проект на WordPress, то полезно свериться с как ускорить WordPress, чтобы миграция не усугубила уже существующие проблемы со скоростью.

Настройка 301 редиректов в Nginx

Если сайт работает на Nginx, я почти всегда предпочитаю настраивать редиректы на уровне сервера. Это быстрее, чище и надёжнее, чем гонять всё через PHP. Особенно если у вас PHP 8.2 или 8.3 и высокий трафик. Nginx обрабатывает такие правила без участия приложения, и это разгружает сервер.

Для простых случаев достаточно пары строк:

server {
    listen 80;
    server_name example.com www.example.com;

    return 301 https://example.com$request_uri;
}

Если нужно перенести конкретные страницы, я часто использую отдельные location или map. Вот пример для точечного переноса старых адресов:

location = /old-page/ {
    return 301 /new-page/;
}

location = /catalog/old-product/ {
    return 301 /shop/new-product/;
}

Но у Nginx есть один нюанс: если редиректов много, хаотично распихивать их по конфигу — это плохая идея. Я обычно выношу крупную карту в отдельный include-файл. Так проще сопровождать. Например:

include /etc/nginx/redirects.conf;

Внутри файла уже держу набор правил. Для больших интернет-магазинов это особенно удобно. Был случай на проекте с 40 000 URL, где после редизайна поменялась логика категорий. Мы вынесли редиректы в отдельный файл и поддерживали его ещё почти месяц после релиза, потому что в логах регулярно всплывали старые ссылки из Яндекс.Маркета, писем и закладок пользователей.

💡
Практика: для Nginx сначала ставьте точные совпадения, а потом уже шаблоны. Иначе общий regex может перехватить URL, который должен идти в другое место.

И ещё один момент. Если у вас одновременно есть HTTPS-редирект, редирект с www и редиректы старых страниц, не смешивайте всё в один нечитаемый блок. Сначала приводите домен к одному каноническому варианту, а потом переносите старую структуру. Об этом я подробно писал в отдельной статье про настройку HTTPS редиректов и HSTS.

301 в .htaccess для WordPress и обычных сайтов

На Apache и в окружениях, где сайт завязан на .htaccess, редиректы часто делают именно там. Для WordPress это вообще типичная история. На деле это удобно, если у вас нет доступа к основному конфигу сервера. Но я всегда говорю честно: если редиректов много, .htaccess превращается в свалку. Тогда лучше либо мигрировать логику на Nginx, либо выносить её в приложение.

Простой редирект в .htaccess выглядит так:

RewriteEngine On

RewriteRule ^old-page/?$ /new-page/ [R=301,L]

Если нужно перенаправить целый раздел:

RewriteEngine On

RewriteRule ^news/(.*)$ /blog/$1 [R=301,L]

А вот редирект с http на https и с non-www на www или наоборот лучше делать аккуратно, чтобы не словить цепочку из двух-трёх переходов. Если уже есть отдельная логика в CMS, проверьте, не создаёт ли она дубль. Часто вижу ситуацию, когда WordPress плагином делает редирект, Nginx делает ещё один, а .htaccess — третий. Итог: долгий ответ сервера и лишняя нагрузка. Для Core Web Vitals это неприятно, особенно если у проекта и так показатели на грани. Если тема скорости для вас актуальна, посмотрите ещё как улучшить Core Web Vitals.

И да, плагинами редиректы в WordPress я пользуюсь только как временным решением или для контент-менеджеров, которым нужно быстро заводить единичные правила. Для массовой миграции это не лучший вариант. Однозначно стоит проверять, не конфликтует ли плагин с кешем и SEO-расширениями. На WordPress это особенно заметно, если стоит что-то вроде Yoast SEO, Rank Math и ещё отдельный редирект-модуль.

Как делать редиректы в Bitrix, WordPress и Laravel

На уровне CMS и фреймворка редирект тоже можно настроить, и иногда это даже правильнее, чем править сервер. Например, если URL строится динамически, а сопоставление зависит от данных из базы. Но тут уже нужна дисциплина: не делать костыли в шаблонах, а выносить логику в отдельный слой.

В Bitrix я часто использую обработчики в init.php или отдельный include-файл с правилами. Если нужно массово сопоставлять старые и новые адреса, можно хранить таблицу редиректов в базе и подтягивать её по мере необходимости. Главное — не превращать проверку в тяжёлый запрос на каждый хит. Если проект большой, лучше держать кеш. У меня был интернет-магазин на Bitrix 8.2, где редиректы хранились в инфоблоке. Работало, но потом мы перевели это в отдельную таблицу MySQL 8.0 и кеширование — стало в разы стабильнее.

Для Laravel я обычно делаю middleware или отдельный middleware-redirect resolver. Примерно так:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class RedirectOldUrls
{
    public function handle(Request $request, Closure $next)
    {
        $path = '/'.$request->path();

        $map = [
            '/old-page' => '/new-page',
            '/catalog/old-product' => '/shop/new-product',
        ];

        if (isset($map[$path])) {
            return redirect($map[$path], 301);
        }

        return $next($request);
    }
}

Но если сопоставлений тысячи, лучше не держать всё в массиве в коде. Я бы вынес это в таблицу SQL и кэшировал результат. На практике так проще сопровождать. Пример таблицы:

CREATE TABLE url_redirects (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    old_url VARCHAR(255) NOT NULL UNIQUE,
    new_url VARCHAR(255) NOT NULL,
    status_code SMALLINT UNSIGNED NOT NULL DEFAULT 301,
    created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_old_url ON url_redirects (old_url);

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

ℹ️
Опыт: если редиректы меняются часто, храните их не в коде, а в конфиге или таблице. Но только с кешированием. Иначе при каждом запросе вы будете лишний раз трогать БД.

Как избежать плохой SEO-логики при редиректах

Самая частая ошибка — неправильное соответствие старых и новых страниц. И вот тут уже можно реально потерять поисковый трафик. 301 не должен быть «куда-нибудь похожее». Он должен быть смысловым. Если старый адрес был про конкретную услугу, новый адрес должен быть про ту же услугу, а не про общий раздел.

Я обычно держу несколько правил:

С цепочками вообще отдельная боль. Был случай на проекте, где старый URL редиректился на промежуточный адрес, а тот — ещё на новый. В сумме получалось три перехода. Для пользователя это почти незаметно, а вот для поискового робота и PageSpeed — уже нет. Я это сразу сокращаю до одного шага. Если сайт после смены структуры ещё и медленно открывается, имеет смысл проверить почему сайт медленно работает и не перегружен ли сервер лишними правилами.

Ещё одна частая проблема — редирект на URL с новым, но неканоническим вариантом. Например, человек настроил 301 с /page на /page/, а потом canonical у страницы указывает обратно на /page без слэша. Это уже конфликт сигналов. Поисковики такое не любят. Поэтому после миграции я всегда проверяю все связанные элементы: canonical, sitemap, внутренние ссылки, hreflang, если есть мультиязычность. Кстати, если проект мультиязычный, пригодится статья как настроить многоязычный сайт.

Как проверить редиректы после внедрения

На словах всё всегда красиво. На деле редиректы надо проверять. И не один раз, а сразу в нескольких местах: браузер, curl, логи сервера, Google Search Console, Яндекс.Вебмастер, краулер типа Screaming Frog. Я обычно ещё смотрю access.log, потому что именно там всплывают неожиданные старые URL из закладок, писем и внешних сайтов.

Проверка через curl — самый простой и честный способ:

curl -I https://example.com/old-page

В ответе вы должны увидеть что-то вроде:

HTTP/2 301
location: https://example.com/new-page/

Что я проверяю после запуска:

  1. код ответа — должен быть 301, не 302 и не 200;
  2. Location — ведёт ли туда, куда надо;
  3. нет ли цепочки из нескольких редиректов;
  4. нет ли циклов;
  5. не ломается ли мобильная версия;
  6. не возникают ли ошибки 404 на новых URL.

И да, после миграции я всегда держу под рукой мониторинг. Потому что первые 3-7 дней после изменения структуры — самые нервные. И если вы не видите, какие URL продолжают приходить, можно не заметить проблему вовремя. У меня для таких случаев обычно связка с логами и алертами, а ещё статья как настроить мониторинг сайта помогает выстроить нормальный контроль.

⚠️
Проверка: не ограничивайтесь главными страницами. Прогоняйте редиректы по товарам, статьям, фильтрам, пагинации и старым служебным URL. Именно там чаще всего вылезают сюрпризы.

Частые ошибки при настройке 301

Если коротко, то у большинства проблемы повторяются одни и те же. И я это вижу почти на каждом втором проекте, где редиректы делали без разработчика. Вот список того, что ломает миграцию чаще всего:

Честно говоря, самая вредная ошибка — это вера в то, что «поисковик сам разберётся». Нет, не разберётся в нужные вам сроки. Он может переобходить сайт неделями. И если вы хотите сохранить позиции, лучше помочь ему нормальными сигналами: 301, обновлённые ссылки, новый sitemap, корректный canonical. А ещё — не затягивать с обновлением старых ссылок в контенте. Если сайт часто меняется, полезно иметь налаженную систему бэкапов и отката, о чём я писал в статье бэкапы сайта: как делать правильно.

На проектах с высокой нагрузкой я иногда вижу и более неприятную проблему: редирект написан нормально, но из-за кеша или CDN он отрабатывает не везде одинаково. Поэтому после выката я всегда проверяю и origin, и CDN, и edge-логи. Если у вас есть CDN, то его тоже надо учитывать — особенно если вы ещё и меняли SSL, HSTS или заголовки безопасности. Тут полезно заглянуть в материалы про настройку CDN и заголовки безопасности HTTP.

Что делать после запуска редиректов

После запуска 301 работа не заканчивается. Наоборот, начинается период наблюдения. Я обычно держу проект под контролем минимум 2-4 недели, а на крупных переездах — и дольше. Смотрю отчёты по сканированию, поведение роботов, изменения трафика и количество 404 в логах.

После запуска обязательно:

Если всё сделано правильно, редиректы со временем станут просто фоном. Пользователь даже не заметит, что структура менялась. И это лучший сценарий. Потому что хороший редирект — это незаметный редирект. А если он заметен, значит, где-то уже что-то пошло не так.

На моей практике самые спокойные миграции были там, где клиент сразу закладывал время на подготовку, тестирование и постконтроль. И наоборот, самые тяжёлые — когда структуру меняли за один вечер, без карты, без логов и без нормальной проверки. Если вам нужен аккуратный перенос, доработка или аудит после переезда, это как раз тот случай, когда имеет смысл смотреть в сторону доработки сайта и регулярной поддержки сайта. Иначе исправлять последствия обычно дороже, чем сделать нормально с первого раза.

Нужна помощь с настройкой 301 редиректов?

Мы поможем безопасно перенести сайт, настроить редиректы и сохранить SEO-позиции при смене структуры.

П
Павел
Веб-разработчик · 10+ лет опыта · Bitrix, WordPress, Laravel

Читайте также

Оптимизация загрузки шрифтов на сайте: руководство 2026 Бэкапы сайта: как делать правильно и не терять данные Настройка Google Analytics и Яндекс.Метрики на сайте