После импорта сайта, переноса с другой CMS или массовой синхронизации контента в WordPress часто появляются дубли: одинаковые страницы, записи с одинаковыми заголовками, копии с разными slug и черновики, которые случайно стали опубликованными. Проблема не только в «мусоре» в админке. Дубли ломают внутреннюю перелинковку, размывают SEO-сигналы и усложняют поддержку сайта.
Ниже разберём рабочий сценарий: как сначала понять, что именно дублируется, потом безопасно удалить лишнее и проверить, что вы не задели нужный контент.
Когда это действительно дубли, а не похожие материалы
Сначала стоит отделить технические копии от нормальной структуры сайта. У WordPress это частая ловушка: одинаковые заголовки могут быть у разных типов записей, а похожий контент — это не всегда дубль. Ищите именно те случаи, где совпадает смысл и источник появления:
- одинаковые записи появились после импорта из CSV, XML или через плагин миграции;
- страницы продублировались из-за повторного запуска импорта;
- у записей совпадает заголовок и почти полностью совпадает содержимое;
- остались старые копии с другим
post_name, но тем же текстом; - в админке видны серии записей с одинаковыми названиями и разными датами создания.
Если у вас просто несколько материалов на одну тему, но они отвечают на разные запросы, это не дубль. Удалять такие записи нельзя — сначала проверьте, есть ли у них разные цели, категории и поисковый интент.
Диагностика проблемы: где искать дубли в WordPress
Самый надёжный способ — посмотреть на данные в базе, а не только в списке записей. Для начала проверьте, какие записи и страницы имеют одинаковые заголовки. Это не идеальный критерий, но он быстро показывает подозрительные группы.
SQL-запрос для поиска одинаковых заголовков
SELECT post_title, post_type, COUNT(*) AS cnt
FROM wp_posts
WHERE post_status IN ('publish', 'draft', 'private', 'pending')
AND post_type IN ('post', 'page')
GROUP BY post_title, post_type
HAVING COUNT(*) > 1
ORDER BY cnt DESC, post_title ASC;Если префикс таблицы у вас не wp_, замените его на свой. Запрос покажет группы, где одинаковый заголовок встречается несколько раз. Дальше нужно открыть каждую группу и сравнить содержимое, даты и slug.
Что смотреть в админке
В списке записей обратите внимание на три вещи:
slugв URL — часто именно он показывает, что запись была создана как копия;- дата публикации — дубль обычно создаётся в один день с оригиналом или сразу после импорта;
- автор и статус — импортированные копии нередко остаются в черновиках или «на проверке».
Если дубликаты появились после переноса сайта, полезно проверить и вложения, и кастомные типы записей. Но в этой статье мы фокусируемся на post и page, потому что именно они чаще всего создают SEO-проблемы.
Пошаговое решение: как удалить лишние копии без лишнего риска
Лучше идти в два прохода: сначала собрать список подозрительных ID, потом удалить только подтверждённые дубли. Не начинайте с массового удаления по заголовку — это самый частый способ снести нужные страницы.
Шаг 1. Сформируйте список кандидатов
Если у вас есть доступ к WP-CLI, можно быстро вывести записи с одинаковыми заголовками и руками проверить каждую группу:
wp db query "
SELECT ID, post_title, post_name, post_type, post_status, post_date
FROM wp_posts
WHERE post_type IN ('post', 'page')
AND post_status IN ('publish', 'draft', 'private', 'pending')
ORDER BY post_title ASC, post_date DESC;
"Дальше удобно выгрузить результат в таблицу и отметить, какая запись оригинал, а какая копия. Обычно оригинал — это более старая запись с нормальным slug и историей правок.
Шаг 2. Удалите только подтверждённые дубли
Если список уже проверен, удалять можно через админку или через WP-CLI. Для массовой работы WP-CLI безопаснее: вы точно видите ID и можете сначала отправить записи в корзину, а не удалять навсегда.
wp post delete 123 124 125 --forceЕсли хотите сначала оставить возможность отката, уберите флаг --force. Тогда записи уйдут в корзину, и вы сможете восстановить их при ошибке.
Шаг 3. Удаление дублей по правилу, а не вручную
Когда дублей много, можно использовать небольшой PHP-скрипт в виде разового сниппета в плагине или mu-plugin. Ниже пример: он ищет записи с одинаковым заголовком и оставляет самую старую, а остальные переводит в корзину. Перед запуском обязательно сделайте резервную копию базы.
<?php
add_action('admin_init', function () {
if (!current_user_can('manage_options')) {
return;
}
if (empty($_GET['dedupe_posts'])) {
return;
}
global $wpdb;
$rows = $wpdb->get_results(
"
SELECT post_title, post_type, GROUP_CONCAT(ID ORDER BY post_date ASC) AS ids, COUNT(*) AS cnt
FROM {$wpdb->posts}
WHERE post_type IN ('post', 'page')
AND post_status IN ('publish', 'draft', 'private', 'pending')
GROUP BY post_title, post_type
HAVING cnt > 1
"
);
foreach ($rows as $row) {
$ids = array_map('intval', explode(',', $row->ids));
$keep_id = array_shift($ids);
foreach ($ids as $duplicate_id) {
wp_trash_post($duplicate_id);
}
}
wp_die('Проверка завершена. Дубли отправлены в корзину.');
});Этот вариант грубый, поэтому используйте его только после ручной проверки. Он подходит, если у вас уже есть правило: одинаковый заголовок в рамках одного типа записи считается дублем.
Сравнение подходов: плагин, SQL или код
| Способ | Когда подходит | Плюсы | Минусы |
|---|---|---|---|
| Админка | Дублей мало | Просто, без кода | Долго и легко ошибиться |
| SQL | Нужно быстро найти группы | Точно показывает данные | Требует аккуратности |
| WP-CLI | Много записей и нужен контроль | Удобно для массовых операций | Нужен доступ к серверу |
| Код | Нужна повторяемая логика | Можно автоматизировать | Нужна проверка условий |
Если вы регулярно чистите импортированный контент, имеет смысл вынести проверку в разовый инструмент или админский скрипт. Для разовой задачи обычно достаточно SQL + WP-CLI.
Проверка результата после удаления
После очистки не ограничивайтесь просмотром списка записей. Проверьте, что сайт не потерял нужные URL и что поисковая структура осталась целой.
- откройте удалённые URL и убедитесь, что они либо ведут на нужную запись, либо возвращают 404, если это действительно лишняя копия;
- проверьте, не осталось ли в меню, хлебных крошках и внутренних ссылках старых адресов;
- если дубли были проиндексированы, обновите sitemap и отправьте его в Search Console;
- пройдитесь по списку записей с одинаковыми заголовками ещё раз и убедитесь, что группы исчезли или сократились до одного оригинала.
Для технической проверки удобно снова выполнить SQL-запрос из блока диагностики. Если он больше не возвращает группы с COUNT(*) > 1, значит, по выбранному правилу дубли убраны.
Частые ошибки и как их исправить
Удаляют по одному только заголовку
Это самая типичная ошибка. У двух записей может совпадать заголовок, но отличаться содержимое, язык, тип страницы или назначение. Исправление простое: сравнивайте не только title, но и текст, slug, дату, автора и таксономии.
Стирают записи без корзины и без бэкапа
Если использовать --force или удалять напрямую из базы, откат становится сложным. Перед чисткой сделайте резервную копию базы и сначала отправляйте сомнительные записи в корзину.
Не учитывают вложенные ссылки и меню
Даже если дубль удалён правильно, на него могут вести ссылки из меню, блоков, шаблонов и старых статей. После удаления проверьте ссылки через поиск по базе или хотя бы через админку меню и редактор контента.
Путают дубль с редиректом
Иногда вместо удаления нужен 301-редирект со старого URL на оригинал. Это актуально, если дубль уже индексировался и имеет внешние ссылки. В таком случае удаление без редиректа может дать лишние 404.
Что делать, если дубли появляются снова
Если проблема возвращается после каждого импорта, нужно чинить не последствия, а источник. Обычно причина одна из трёх: повторный импорт без очистки старых данных, плагин синхронизации, который создаёт новые записи вместо обновления, или неверно настроенный ключ сопоставления в CSV/XML.
Практический чек-лист для профилактики:
- проверяйте, по какому полю импортёр ищет существующую запись: ID, slug, внешний идентификатор;
- не запускайте импорт повторно без теста на копии сайта;
- ограничьте права на массовое создание записей у редакторов и внешних интеграций;
- после импорта сразу сверяйте количество новых записей с ожидаемым;
- если контент приходит из внешней системы, храните стабильный внешний ID и обновляйте запись по нему, а не по заголовку.
Безопасность и производительность при чистке дублей
Массовые операции по базе лучше выполнять в низкую нагрузку. На больших сайтах запросы к wp_posts и массовое удаление могут дать заметную нагрузку, особенно если одновременно работают импортеры, кэш и поисковые роботы. Не запускайте чистку в пик трафика.
Если вы используете плагины для очистки и оптимизации, выбирайте те, которые не скрывают действия за «магией». Для задач удаления дублей полезнее прозрачный инструмент, где видно, что именно будет удалено. Например, в экосистеме WPShop есть Clearfy Pro, который закрывает часть задач по чистке и SEO-обслуживанию сайта: https://wpshop.ru/plugins/clearfy. Но даже с плагином всё равно нужно сначала понять причину дублей, а не просто «почистить» их вслепую.
Если нужен короткий рабочий порядок, он такой: найти группы дублей, вручную подтвердить оригинал, удалить только копии, проверить ссылки и при необходимости поставить редиректы. Это скучнее, чем массовая автоматизация, зато предсказуемо и безопасно для живого сайта.