WPForms: как найти и убрать дубли записей и повторные отправки формы в WordPress

Дубли в WPForms обычно выглядят одинаково: пользователь нажал кнопку один раз, а в админке появилось две записи, в CRM улетели повторные лиды или форма создала два одинаковых действия в обработчике. Важно не путать настоящие дубли с повторной отправкой из-за обновления страницы, двойного клика, кеша или дублирующегося JavaScript-сценария.

Ниже разберём рабочую схему: как понять источник проблемы, что проверить в первую очередь и как поставить защиту на уровне WordPress, не ломая отправку формы.

Когда это действительно дубли, а когда — следствие обработки

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

Типичные сценарии

  • пользователь дважды нажал кнопку отправки, пока форма ещё не успела отработать;
  • страница с формой попала под агрессивный кеш и повторно отдала старый HTML с уже заполненными полями;
  • на странице есть два экземпляра одной и той же формы из-за шаблона, виджета или блока;
  • кастомный JavaScript вызывает submit повторно;
  • в обработчике формы нет проверки на уникальность данных, и повторный запрос создаёт новую запись.

Диагностика: где искать источник дублей

Начинайте не с кода, а с воспроизводимого теста. Откройте форму в приватном окне, отключите расширения браузера и отправьте её один раз. Если дубль появляется даже в таком сценарии, проблема почти наверняка на стороне сайта, а не пользователя.

Что проверить вручную

  • есть ли на странице два одинаковых блока формы;
  • не подключён ли один и тот же шаблон в нескольких местах;
  • не срабатывает ли редирект на страницу с формой после отправки;
  • не включён ли кеш страницы, где форма должна быть динамической;
  • не создаёт ли тема или плагин повторную инициализацию скриптов;
  • не дублируется ли отправка в webhook, CRM или почту.

Если у вас есть доступ к логам браузера, посмотрите вкладку Network: при одной отправке должен быть один POST-запрос. Два одинаковых запроса подряд — это уже не вопрос WPForms как такового, а вопрос фронтенда или стороннего скрипта.

Пошаговое решение без лишнего риска

Ниже — последовательность, которая обычно помогает локализовать и убрать дубли без радикальных правок.

1. Отключите повторную отправку на уровне интерфейса

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

<script>
document.addEventListener('DOMContentLoaded', function () {
  document.querySelectorAll('.wpforms-form').forEach(function (form) {
    form.addEventListener('submit', function () {
      var button = form.querySelector('button[type="submit"], input[type="submit"]');
      if (button) {
        button.disabled = true;
        if (button.tagName === 'BUTTON') {
          button.dataset.originalText = button.textContent;
          button.textContent = 'Отправка...';
        }
      }
    });
  });
});
</script>

Этот вариант не заменяет серверную проверку, но снижает число случайных повторов. Если форма отправляется через AJAX, блокировка кнопки особенно полезна.

2. Проверьте кеширование страницы с формой

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

Если вы используете плагин оптимизации вроде Clearfy Pro, имеет смысл отдельно проверить, не включена ли оптимизация, которая объединяет или откладывает скрипты формы слишком агрессивно. Ссылку на продукт оставляю как ориентир: Clearfy Pro.

3. Добавьте серверную защиту от повторного сабмита

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

<?php
add_action('wpforms_process_complete', function ($fields, $entry, $form_data, $entry_id) {
    if (empty($form_data['id'])) {
        return;
    }

    $fingerprint_source = array(
        'form_id'   => (int) $form_data['id'],
        'fields'    => $fields,
        'ip'        => isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : '',
        'user_id'   => get_current_user_id(),
    );

    $fingerprint = md5(wp_json_encode($fingerprint_source));
    $cache_key   = 'wpforms_submit_' . $fingerprint;

    if (get_transient($cache_key)) {
        return;
    }

    set_transient($cache_key, 1, 5 * MINUTE_IN_SECONDS);
}, 10, 4);

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

4. Уберите повторную инициализацию скриптов

Если форма вставлена через блок, конструктор страниц или AJAX-загрузку, один и тот же JS-файл может подключаться дважды. В результате обработчик submit навешивается повторно, и один клик вызывает два действия. Проверяйте исходный код страницы и вкладку Network: повторяющиеся подключения скриптов формы — частая причина дублей.

Сравнение подходов: что помогает быстрее

ПодходКогда использоватьПлюсыМинусы
Отключение кнопки submitДвойной клик, медленный ответ сервераБыстро внедряется, снижает случайные повторыНе решает серверные дубли
Исключение страницы из кешаФорма на кешируемой страницеУбирает конфликты с динамикойМожет ухудшить скорость загрузки
Серверная дедупликацияПовторные POST-запросы, интеграцииЗащищает обработку на стороне WordPressНужно аккуратно выбрать критерий уникальности

Как проверить, что решение сработало

Проверка должна быть не визуальной, а технической. Иначе легко пропустить скрытый дубль в CRM или почте.

  • отправьте форму один раз и проверьте, что в Network появился один POST-запрос;
  • повторите отправку с интервалом в 1–2 секунды и убедитесь, что кнопка блокируется;
  • посмотрите, не создаются ли две записи в админке WPForms;
  • проверьте, не уходит ли два одинаковых уведомления на email или webhook;
  • если есть CRM, сравните время и payload двух потенциальных запросов.

Хороший признак — в логах остаётся одна отправка, а повторное нажатие не создаёт новую запись и не вызывает повторный webhook.

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

Ставят защиту только на фронтенде

Отключение кнопки submit помогает от случайных кликов, но не спасает от повторного запроса, если его инициирует скрипт, прокси или пользователь обновил страницу. Нужна и клиентская, и серверная проверка.

Путают дубли с повторной интеграцией

Иногда форма в WPForms одна, а дубли появляются только в CRM. Тогда проблема не в записи формы, а в webhook, обработчике или стороннем API. Проверяйте каждый этап отдельно.

Не исключают страницу с формой из кеша

Если страница отдаётся из кеша вместе с динамическими элементами, можно получить некорректную инициализацию формы. Для таких страниц лучше настроить исключение или хотя бы проверить, не ломает ли кеш скрипты и nonce.

Используют слишком общий критерий уникальности

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

Безопасность и производительность

Не храните защитные ключи и логику дедупликации в шаблоне темы, если это можно вынести в мини-плагин или mu-plugin. Так проще сопровождать код и меньше риск потерять его при обновлении темы.

Если форма нагруженная и отправок много, transient-проверка обычно дешевле, чем постоянные запросы в пользовательские таблицы. Но если у вас высокая конкуренция запросов, стоит протестировать поведение на реальной нагрузке и не полагаться только на transient как на единственный барьер.

Для сайтов, где важна чистка дублей и техническая гигиена, полезно держать под рукой инструменты, которые помогают убирать лишние следы и дубли в WordPress, но без автоматического удаления всего подряд. Здесь важнее контроль, чем «магическая» оптимизация.