Дубли в WordPress обычно появляются не из-за одной ошибки, а из-за набора мелких причин: импорт контента, повторная публикация, кривые редиректы, одинаковые slug, архивы с разными URL и копии записей после миграции. На живом сайте это быстро превращается в лишние страницы в индексе, путаницу в админке и проблемы с внутренней перелинковкой.
Если задача не в том, чтобы «почистить всё подряд», а в том, чтобы найти именно дубли и убрать их без лишнего риска, лучше идти по схеме: сначала диагностировать источник, потом выбрать способ удаления, затем проверить, что старые URL действительно исчезли из обхода и не ломают сайт.
Как понять, что у вас именно дубли, а не похожий контент
Сначала стоит отделить настоящие дубли от просто похожих материалов. В WordPress это разные случаи:
- одинаковый заголовок и почти одинаковый текст у двух записей;
- одинаковый
post_nameу старой и новой версии материала; - копии страниц после импорта или переноса сайта;
- архивы автора, рубрик, тегов и пагинации, которые повторяют основной контент;
- дубли в базе, когда одна и та же запись была создана повторно, а не обновлена.
Если в индексе поисковика есть несколько URL с одним смыслом, это уже не косметическая проблема. Поисковый робот тратит обход на лишние страницы, а сайт сам себе конкурирует в выдаче.
Быстрая диагностика в админке и базе
Для начала проверьте список записей и страниц по одинаковым заголовкам. Это самый простой признак, но он не всегда точный: заголовки могут совпадать, а контент — отличаться. Более надежно смотреть на slug и даты публикации.
Если есть доступ к базе, можно быстро найти одинаковые slug для записей:
SELECT post_name, COUNT(*) AS cnt
FROM wp_posts
WHERE post_type IN ('post', 'page')
AND post_status NOT IN ('trash', 'auto-draft')
GROUP BY post_name
HAVING cnt > 1;Этот запрос не покажет все дубли контента, но хорошо ловит повторяющиеся URL-имена. Если у вас нестандартный префикс таблиц, замените wp_ на свой.
Еще один полезный признак — одинаковый post_title у нескольких опубликованных записей:
SELECT post_title, COUNT(*) AS cnt
FROM wp_posts
WHERE post_type = 'post'
AND post_status = 'publish'
GROUP BY post_title
HAVING cnt > 1;Это уже не доказательство дубля, но хороший список для ручной проверки.
Что делать: сравнение подходов
Убирать дубли можно тремя способами. У каждого есть компромисс.
| Подход | Когда подходит | Плюсы | Минусы |
|---|---|---|---|
| Ручное удаление в админке | 1–10 дублей | Безопасно, не требует кода | Долго, неудобно при массовой чистке |
Скрипт через functions.php или mu-plugin | Нужно удалить много повторов по правилу | Можно автоматизировать и логировать | Нужна аккуратность и бэкап |
| Плагин для очистки дублей | Если нужен разовый аудит без разработки | Быстрее для редактора | Лишняя зависимость, не всегда прозрачно, что именно удаляется |
Если задача разовая и у вас есть доступ к коду, практичнее сделать точечный скрипт. Если контентом управляет редакция и проблема повторяется, лучше сначала исправить процесс: импорт, шаблоны, автосохранение, публикацию по расписанию.
Пошаговое решение без плагинов
Ниже — безопасный сценарий для случая, когда нужно найти записи с одинаковым slug и удалить лишние копии, оставив одну актуальную версию. Перед запуском сделайте резервную копию базы.
Шаг 1. Сначала пометить дубли, а не удалять их сразу
Лучше не удалять записи молча. Сначала переведите лишние копии в черновик или корзину, чтобы можно было откатиться. Для этого удобнее использовать небольшой код в mu-plugin или временно в functions.php.
<?php
add_action('admin_init', function () {
if ( ! current_user_can('manage_options') ) {
return;
}
if ( ! isset($_GET['find_duplicate_posts']) ) {
return;
}
global $wpdb;
$duplicates = $wpdb->get_results(
"SELECT post_name, COUNT(*) AS cnt
FROM {$wpdb->posts}
WHERE post_type = 'post'
AND post_status = 'publish'
GROUP BY post_name
HAVING cnt > 1"
);
echo '<pre>';
foreach ( $duplicates as $row ) {
echo esc_html($row->post_name . ' — ' . $row->cnt) . "\n";
}
echo '</pre>';
exit;
});После добавления кода откройте /wp-admin/?find_duplicate_posts=1 под администратором. Вы получите список slug, которые повторяются. Это не удаление, а аудит.
Шаг 2. Удалить лишние копии по понятному правилу
Если дубль определяется по slug, можно оставить самую свежую запись, а остальные отправить в корзину. Ниже пример, который работает только для записей и только для опубликованных материалов с одинаковым slug.
<?php
add_action('admin_init', function () {
if ( ! current_user_can('manage_options') ) {
return;
}
if ( ! isset($_GET['cleanup_duplicate_posts']) ) {
return;
}
global $wpdb;
$rows = $wpdb->get_results(
"SELECT post_name
FROM {$wpdb->posts}
WHERE post_type = 'post'
AND post_status = 'publish'
GROUP BY post_name
HAVING COUNT(*) > 1"
);
foreach ( $rows as $row ) {
$posts = get_posts([
'post_type' => 'post',
'post_status' => 'publish',
'name' => $row->post_name,
'numberposts' => -1,
'orderby' => 'date',
'order' => 'DESC',
'fields' => 'ids',
]);
if ( count($posts) <= 1 ) {
continue;
}
// Оставляем самую свежую запись, остальные отправляем в корзину.
array_shift($posts);
foreach ( $posts as $post_id ) {
wp_trash_post($post_id);
}
}
wp_die('Дубли отправлены в корзину. Проверьте список записей вручную.');
});Запускать такой код нужно один раз и только после бэкапа. После выполнения удалите его, чтобы не оставить в админке рабочую «кнопку» для случайного запуска.
Шаг 3. Если дубли появились после импорта
После миграции часто дублируются не только записи, но и медиа, категории, теги. В этом случае чистить нужно не только wp_posts, но и сопутствующие связи. Если просто удалить записи, а термины и вложения оставить, мусор останется в базе и в медиатеке.
Практически это выглядит так:
- сначала сверить количество записей до и после импорта;
- проверить, не создались ли дубли страниц «О нас», «Контакты», «Политика»;
- просмотреть медиатеку на повторяющиеся файлы с одинаковым названием;
- убедиться, что старые URL не остались в sitemap и внутренних ссылках.
Проверка результата после очистки
Удалить дубли недостаточно. Нужно проверить, что сайт не продолжает отдавать старые адреса и что поисковик не видит две версии одной страницы.
Что проверить в первую очередь
- открывается ли основной URL записи без цепочки редиректов;
- нет ли в админке второго материала с тем же slug;
- исчезли ли удаленные записи из sitemap;
- не ведут ли внутренние ссылки на корзину или 404;
- не осталось ли старых URL в кэше страницы и CDN;
- не создается ли дубль снова при повторной публикации или импорте.
Если у вас включен кэш, очистите его после удаления дублей. Иначе можно увидеть старую версию страницы даже после того, как запись уже удалена.
Для быстрой проверки ответа сервера используйте curl:
curl -I https://example.com/staryj-url/Если URL удален правильно, вы должны увидеть либо 301 на актуальную страницу, либо 410 Gone, если адрес намеренно убран без замены. Для дублей это важный момент: поисковику нужно явно показать, что старый адрес больше не является каноническим.
Частые ошибки и как их исправить
Удаляют не дубль, а нужную версию записи
Это случается, когда ориентируются только на заголовок. Один и тот же title может быть у разных материалов. Перед удалением сравните slug, дату, автора, содержимое и входящие ссылки.
Оставляют старый URL без редиректа
Если удалить запись и не настроить редирект, внутренние ссылки и внешние переходы начнут вести на 404. Для страниц, которые уже были в индексе, это плохой сценарий. Если у дублирующейся записи есть замена, лучше сделать 301 на актуальный адрес.
Чистят только записи, но не архивы и таксономии
Иногда дубли создаются не в записях, а в архивных страницах: авторы, теги, рубрики, пагинация. Если проблема именно в индексации, удаление одной записи ничего не изменит. Тогда нужно отдельно проверить robots, sitemap и канонические URL.
Запускают код без бэкапа
Любой массовый скрипт в WordPress должен идти после резервной копии базы и файлов. Это не формальность: если логика отбора дублей ошибочна, откат будет только через бэкап.
Оставляют временный код в продакшене
Код для поиска и удаления дублей не должен висеть в functions.php постоянно. Лучше вынести его в временный mu-plugin, выполнить задачу и удалить файл. Так вы не оставите случайный административный триггер на сайте.
Что можно улучшить после чистки
Если дубли появляются регулярно, проблема обычно не в контенте как таковом, а в процессе. Проверьте:
- не создаются ли записи повторно через импорт из CSV или XML;
- не дублирует ли редактор материал вручную вместо обновления;
- не генерируются ли одинаковые URL из-за шаблона slug;
- не плодятся ли архивы и служебные страницы, которые лучше закрыть от индексации;
- не мешает ли кэш показывать старые версии после удаления.
Если нужна не разовая чистка, а системное удаление дублей, удобно сочетать аудит контента с настройкой SEO-правил и очисткой служебных страниц. В таких задачах часто помогает связка из ручной проверки и инструментов для удаления дублей, например Clearfy Pro, если вам нужен именно набор SEO- и cleanup-настроек без написания собственного кода.
Главное правило простое: сначала найти источник дубля, потом удалить лишнее, потом проверить, что старый URL больше не участвует в обходе и не возвращается из кэша.