После импорта товаров в WooCommerce дубликаты affiliate-ссылок обычно появляются не из-за одной ошибки, а из-за цепочки: импорт пишет URL в несколько полей, тема выводит ссылку в разных шаблонах, а кэш или фильтры дублируют кнопку еще раз. В итоге одна и та же партнерская ссылка встречается в карточке товара дважды, а иногда и трижды — в кнопке, в тексте описания и в блоке «Купить».
Ниже разберем рабочий сценарий: как найти источник дублей, как убрать их без поломки импорта и как проверить, что проблема действительно закрыта.
Как выглядит проблема на практике
Чаще всего дубли появляются в одном из таких сценариев:
- импорт записывает affiliate URL в
_product_url, а тема дополнительно выводит кнопку из этого же поля; - в описание товара попадает ссылка из CSV/XML, и рядом WooCommerce показывает собственную кнопку внешнего товара;
- плагин импорта повторно создает мета-поля при каждом запуске, не проверяя, есть ли уже значение;
- в шаблоне темы или в конструкторе страницы ссылка вставлена вручную, а потом еще подтягивается из метаполя;
- после обновления импорта старые и новые значения не синхронизируются, и в базе остаются две версии одной ссылки.
Диагностика: где именно рождается дубль
Перед правкой кода важно понять, дублируется ли сама ссылка в базе или только ее вывод на странице. Это разные проблемы, и лечатся они по-разному.
Проверьте метаполя товара
Для внешних товаров WooCommerce обычно использует _product_url и _button_text. Если импорт пишет туда одно и то же несколько раз, проблема уже в данных. Быстро проверить можно через админку товара или через SQL-запрос к мета-таблице.
SELECT post_id, meta_key, meta_value<br>FROM wp_postmeta<br>WHERE meta_key IN ('_product_url', '_button_text')<br>AND post_id = 123;Если у товара есть еще кастомные поля импорта, проверьте и их. Часто дубли прячутся в отдельном поле вроде affiliate_url, а тема потом берет его для кнопки и одновременно показывает стандартную кнопку WooCommerce.
Проверьте шаблон вывода
Если в базе одна ссылка, а на странице она видна дважды, смотрите шаблон товара, хуки темы и блоки конструктора. Для внешнего товара WooCommerce сам выводит кнопку через стандартную логику, поэтому ручная кнопка в шаблоне часто оказывается лишней.
Сравнение подходов: убрать дубли в данных, в шаблоне или на этапе импорта
| Подход | Когда подходит | Минус |
|---|---|---|
| Исправить импорт | Если дубли появляются после каждого обновления каталога | Нужно править маппинг или обработчик импорта |
| Убрать лишний вывод в шаблоне | Если ссылка одна в базе, но дважды показывается на странице | Нужно знать, где тема добавляет кнопку |
| Нормализовать метаполя кодом | Если данные приходят из нескольких источников | Потребуется аккуратная проверка на совместимость |
Пошаговое решение без поломки каталога
Шаг 1. Оставьте один источник правды для ссылки
Если товар внешний, лучше хранить affiliate URL в стандартном поле WooCommerce, а не дублировать его в отдельном кастомном поле без необходимости. Тогда тема и плагины будут работать предсказуемо.
Если импорт уже пишет в кастомное поле, можно синхронизировать его со стандартным _product_url и перестать выводить ссылку вручную в шаблоне.
Шаг 2. Не перезаписывайте мета-поля без проверки
Ниже пример, который можно использовать в небольшом плагине или в functions.php, если нужно синхронизировать URL только при импорте и не создавать дубль в метаданных.
add_action('save_post_product', function ($post_id, $post, $update) {
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
if (wp_is_post_revision($post_id)) {
return;
}
$source_url = get_post_meta($post_id, 'affiliate_url', true);
if (!$source_url) {
return;
}
$current_url = get_post_meta($post_id, '_product_url', true);
if ($current_url === $source_url) {
return;
}
update_post_meta($post_id, '_product_url', esc_url_raw($source_url));
}, 10, 3);Этот вариант полезен, если импорт кладет ссылку в affiliate_url, а WooCommerce должен использовать ее как основную. Важно: не делайте такой хук бездумно на всех сохранениях, если у вас есть ручное редактирование карточек — иначе редактор будет перетирать изменения импорта.
Шаг 3. Уберите лишнюю кнопку из шаблона
Если тема уже выводит кнопку для внешнего товара, не добавляйте рядом еще одну через woocommerce_single_product_summary. Частая ошибка — вставить собственную кнопку, а потом удивляться, почему на странице их две.
Если нужно оставить только один CTA, можно удалить стандартный вывод и заменить его своим вариантом:
remove_action('woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30);
add_action('woocommerce_single_product_summary', function () {
global $product;
if (!$product || !$product->is_type('external')) {
return;
}
$url = $product->get_product_url();
if (!$url) {
return;
}
echo '<p><a class="button alt" href="' . esc_url($url) . '" rel="nofollow sponsored noopener" target="_blank">Перейти к продавцу</a></p>';
}, 30);Здесь важно не забыть rel="nofollow sponsored noopener" для affiliate-ссылок и target="_blank", если это соответствует вашей политике переходов.
Шаг 4. Очистите старые дубликаты в базе
Если импорт уже несколько раз записал одинаковые данные, исправление шаблона не уберет мусор из мета-таблицы. Для этого нужен разовый проход по товарам: сравнить значения и удалить лишние поля, если они полностью совпадают или если одно поле явно устарело.
Пример безопасной проверки перед массовым обновлением:
global $wpdb;
$rows = $wpdb->get_results(
"SELECT post_id, meta_value FROM {$wpdb->postmeta} WHERE meta_key = 'affiliate_url'"
);
foreach ($rows as $row) {
$product_url = get_post_meta($row->post_id, '_product_url', true);
if ($product_url && $product_url === $row->meta_value) {
// Здесь можно удалить дублирующее поле после бэкапа.
// delete_post_meta($row->post_id, 'affiliate_url');
}
}Удаление делайте только после резервной копии базы и сначала на тестовой копии сайта. Если у вас несколько источников импорта, не удаляйте поле, пока не убедитесь, что оно нигде больше не используется.
Как проверить, что решение сработало
Проверка должна быть не визуальной «на глаз», а по нескольким точкам:
- откройте карточку товара в режиме инкогнито и убедитесь, что кнопка одна;
- посмотрите исходный HTML страницы и найдите все вхождения домена affiliate-ссылки;
- проверьте метаполя товара в админке или через SQL: у ссылки должен быть один актуальный источник;
- запустите повторный импорт и сравните, не создает ли он новые дубликаты;
- если используется кэш, очистите его и проверьте страницу без кэшированного HTML.
Если после очистки кэша дубли исчезли только временно, значит проблема не в данных, а в шаблоне или в плагине, который повторно вставляет кнопку при рендере.
Частые ошибки и как их исправить
Импорт пишет ссылку в два поля сразу
Это типичная ошибка маппинга. Один и тот же URL попадает и в _product_url, и в кастомное поле, а затем тема выводит оба значения. Решение — оставить одно поле для вывода и одно поле для служебных данных, если оно действительно нужно.
Кнопка добавлена и темой, и конструктором
Если карточка собрана в Elementor, Gutenberg или другом конструкторе, стандартная кнопка WooCommerce может остаться внизу страницы. Уберите либо блок конструктора, либо стандартный action WooCommerce, но не оба одновременно.
Редирект- или affiliate-плагин дублирует ссылку
Некоторые плагины оборачивают ссылку в собственный редирект, а потом тема еще раз строит кнопку по исходному URL. В таком случае проверьте, не включен ли повторный вывод ссылки в настройках плагина или в шаблоне.
Кэш показывает старую версию страницы
После исправления в базе страница может еще какое-то время отдавать старый HTML. Очистите page cache, object cache и, если есть, CDN-кэш. Иначе будет казаться, что дубли остались, хотя на самом деле вы смотрите старую копию.
Что делать, если дубли появляются только после обновления импорта
Тогда проблема почти всегда в логике синхронизации. Импорт должен либо обновлять существующее поле, либо пропускать запись, если значение не изменилось. Если плагин импорта не умеет этого делать, добавьте проверку в свой обработчик или используйте фильтр/хук конкретного импортера, если он есть в документации.
Для больших каталогов полезно вести один технический идентификатор товара и обновлять данные по нему, а не по названию. Иначе импорт может создавать новые записи вместо обновления старых, а вместе с ними — новые affiliate-ссылки и новые дубли.
Практические советы по безопасности и производительности
- перед массовой чисткой метаданных сделайте бэкап базы;
- не запускайте SQL-удаление без фильтра по конкретному типу записей;
- если каталог большой, выполняйте очистку пакетами, а не одним тяжелым запросом;
- проверяйте, не использует ли тема кэшированные мета-значения;
- при работе с внешними ссылками используйте
esc_url_raw()на записи иesc_url()на выводе.
Если вам нужно не только убрать дубли, но и навести порядок в лишних мета-полях, удобно сначала почистить сайт от технического мусора, а потом уже править импорт и шаблоны. Для этого часто хватает аккуратной ревизии структуры данных и отключения лишних дублей в шаблоне, без тяжелой переделки каталога.