Как исправить 404 на старом URL после смены slug в WordPress

Смена slug у записи, страницы или произвольного типа постов почти всегда оставляет после себя хвост из старых адресов. Если редирект не настроен, пользователь видит 404, а поисковик продолжает держать в индексе устаревший URL. На небольшом сайте это быстро превращается в шум в отчётах Search Console и лишние запросы к серверу.

Ниже разберём рабочий сценарий: как найти старые адреса, где именно ставить редирект, как не сломать каноникал и как проверить, что проблема действительно закрыта.

Когда проблема видна сразу, а когда она прячется

Самый очевидный симптом — страница по старому адресу отдаёт 404. Но на практике есть ещё несколько признаков:

  • в логах много запросов к старым URL после редактирования контента;
  • в Search Console растёт число страниц с ошибкой «Не найдено»;
  • внутренние ссылки в старых материалах ведут на уже изменённый адрес;
  • после смены slug пост перестаёт открываться по старому адресу, хотя в выдаче ещё висит прежний URL.

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

Диагностика: что проверить до правки редиректов

Сначала нужно понять, откуда берётся старый адрес. В WordPress это обычно один из трёх вариантов: ручная смена slug в редакторе, импорт контента с новым URL или изменение структуры постоянных ссылок.

Проверьте, есть ли старый URL в базе и в контенте

Если доступен WP-CLI, быстро найдите упоминания старого slug в контенте:

wp search-replace 'https://example.com/old-slug' 'https://example.com/new-slug' --dry-run

Команда в режиме --dry-run ничего не меняет, но показывает, где старый адрес встречается в базе. Это полезно, если ссылка зашита в тексте, в метаполях или в настройках темы.

Если WP-CLI нет, проверьте хотя бы:

  • редактор записи — не остались ли вручную вставленные ссылки;
  • меню и блоки в редакторе сайта;
  • виджеты и шаблонные части темы;
  • SEO-поля плагина, если там задан canonical вручную.

Посмотрите, как отвечает старый адрес

Проверить статус можно через curl:

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

Нужный результат — 301 Moved Permanently и переход на новый URL. Если видите 404, редиректа нет. Если 302, редирект временный, и для постоянной смены slug это обычно не лучший вариант.

Какой способ редиректа выбрать: плагин, код или сервер

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

СпособКогда подходитПлюсМинус
Плагин редиректовРазовые правки, редакторский сайтБыстро настраивается без кодаПоявляется ещё один слой логики в админке
Код в теме или мини-плагинеПостоянные правила, разработка под контролемВерсионируется и не теряется при обновлении темыНужен доступ к коду
.htaccess / nginxВысокая нагрузка, много редиректовОтрабатывает до WordPressНужен доступ к серверу и аккуратность

Если речь о нескольких конкретных URL, я бы начинал с кода в мини-плагине. Так правило не исчезнет после смены темы и не будет зависеть от редактора.

Пошаговое решение через template_redirect

Для точечного редиректа можно добавить правило в мини-плагин или в functions.php дочерней темы. Лучше всё же мини-плагин: меньше шансов потерять код при обновлении темы.

<?php
/**
 * Plugin Name: Old Slug Redirects
 */

add_action( 'template_redirect', function () {
    $uri = isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '';

    if ( $uri === '/old-slug/' || $uri === '/old-slug' ) {
        wp_redirect( home_url( '/new-slug/' ), 301 );
        exit;
    }

    if ( $uri === '/category/old-section/post-name/' ) {
        wp_redirect( home_url( '/blog/post-name/' ), 301 );
        exit;
    }
} );

Здесь важно не сравнивать только $_SERVER['REQUEST_URI'] «как есть» без нормализации. У пользователя может прийти адрес без завершающего слеша, с параметрами или в другом регистре. Для точечных правил лучше явно перечислять допустимые варианты.

Если старых URL много, используйте массив соответствий

Когда адресов несколько десятков, удобнее хранить карту редиректов в массиве:

<?php
add_action( 'template_redirect', function () {
    $uri = isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '';

    $redirects = array(
        '/old-slug/'        => '/new-slug/',
        '/old-about/'       => '/about-us/',
        '/news/old-post/'   => '/blog/new-post/',
    );

    if ( isset( $redirects[ $uri ] ) ) {
        wp_safe_redirect( home_url( $redirects[ $uri ] ), 301 );
        exit;
    }
} );

Для внутренних переходов лучше использовать wp_safe_redirect(), а не wp_redirect(). Это не панацея, но дополнительная проверка на безопасный хост здесь уместна.

Что делать, если slug менялся у записей автоматически

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

Пример: сохраняем старый slug при обновлении записи и потом редиректим с него на новый адрес.

<?php
add_action( 'save_post', function ( $post_id, $post, $update ) {
    if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) {
        return;
    }

    if ( ! $update ) {
        return;
    }

    $old_slug = get_post_meta( $post_id, '_old_slug', true );
    if ( empty( $old_slug ) ) {
        return;
    }

    update_post_meta( $post_id, '_redirect_from_slug', sanitize_title( $old_slug ) );
}, 10, 3 );

add_action( 'template_redirect', function () {
    $uri = trim( parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH ), '/' );
    $path = '/' . $uri . '/';

    $posts = get_posts( array(
        'post_type'      => 'post',
        'post_status'    => 'publish',
        'meta_key'       => '_redirect_from_slug',
        'meta_value'     => sanitize_title( basename( $path ) ),
        'posts_per_page' => 1,
        'fields'         => 'ids',
    ) );

    if ( ! empty( $posts ) ) {
        wp_safe_redirect( get_permalink( $posts[0] ), 301 );
        exit;
    }
} );

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

Проверка результата после внедрения

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

  • Выполните curl -I https://example.com/old-slug и убедитесь, что ответ 301.
  • Проверьте, что Location указывает сразу на новый адрес, а не на промежуточный.
  • Откройте новый URL и убедитесь, что canonical ведёт на него же.
  • Посмотрите логи сервера или отчёт плагина редиректов: старый адрес должен перестать отдавать 404.

Если используете SEO-плагин, проверьте, не создаёт ли он собственный canonical на старый адрес. Такое бывает, когда запись открывается по новому URL, а в метаданных осталась старая ссылка.

Частые ошибки и как их исправить

Редирект поставили на 302 вместо 301

Для постоянной смены slug нужен 301. Временный редирект не даёт поисковику нормального сигнала о замене адреса и может оставить в индексе старую версию дольше, чем нужно.

Сделали цепочку из нескольких редиректов

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

Забыли про внутренние ссылки

Редирект закрывает внешний трафик, но не исправляет ссылки внутри сайта. После смены slug найдите и обновите ссылки в меню, блоках, шаблонах и старых статьях.

Сломали правило из-за неверного слеша

WordPress часто различает адреса со слешем и без него в зависимости от настроек постоянных ссылок. Если правило не срабатывает, проверьте оба варианта и сравните их с тем, как сайт реально формирует URL.

Положили редирект в тему, а потом обновили её

Если код лежит в functions.php активной темы, он исчезнет при замене темы. Для постоянных правил используйте мини-плагин или mu-plugin.

Что учесть для безопасности и производительности

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

  • Не делайте запросы к базе на каждом хите, если можно обойтись статической картой.
  • Не подставляйте в wp_redirect() непроверенный внешний URL.
  • Не храните редиректы в произвольном пользовательском вводе без валидации.
  • Если редиректов много, перенесите часть правил на уровень nginx или Apache.

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

Когда нужно быстро убрать мусорные URL, дубли и лишние технические страницы, удобно опираться на связку из правил редиректа, проверки canonical и контроля robots. Для этого можно использовать и отдельные SEO-инструменты, например Clearfy Pro: https://wpshop.ru/plugins/clearfy?utm_source=wppartner.ru&utm_medium=article&utm_campaign=kak-ispravit-404-na-starom-url-posle-smeny-slugov-v-wordpress

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

Вам также может быть интересно:

Как создать подробный отчет по ошибкам в WordPress: практическое руководство
12.01.2026
Как использовать REST API в WordPress для создания настроенных запросов
05.11.2025
Как автоматизировать удаление старых записей в WordPress по дате
10.04.2026
Как удалить пустые категории и теги в WordPress: практическое руководство
17.03.2026
Как настроить страницу входа в WordPress без плагинов: практическое руководство
31.01.2026
×
Quizle
Получите больше лидов и увеличьте продажи!
-15%

на премиум плагин WordPress

Получить скидку ⋙