Скрытое поле в контактной форме — honeypot

запись от - 1 апреля 2024

Honeypot — очень простой и довольно эффективный способ уменьшить количество спама в формах Contact Form 7 без лишних неудобств для пользователей.
Идея в том что в форму помещается скрытое поле, которое заполнять не надо. Тупые (простые) боты заполняют все подряд — соответственно если поле заполнено, форму не отправляем, содержимое считаем спамом.

Скачать можно здесь — https://github.com/vvhromov/cf7honeypot

Так выглядит форма в панели редактирования Contact Form 7
<div class="simple-form">
<label> Просто текстовое поле
    [text simple-text] </label>
[honeypot extra]
[submit "Отправить"]
</div>

А так выглядит эта форма на странице — проще некуда, текстовое поле и кнопка «Отправить»

    Но если посмотреть форму Инспектором (DevTools) можно увидеть что есть еще одно скрытое поле.
    Делается это так

    function cf7_honeypot_form_tag_handler( $tag ) {
        return '<input type="text" name="'.esc_attr( $tag->name ).'" value="" style="display:none!important" autocomplete="off" tabindex="-1" />';
    }
    // Добавляется тег [honeypot {name-tag}] в CF7
    // function cf7_honeypot_form_tag_handler определяет как honeypot будет выводится на веб странице
    add_action( 
      'wpcf7_init', 
      function () {
        wpcf7_add_form_tag( 'honeypot', 'cf7_honeypot_form_tag_handler', [ 'name-attr' => true ] );
        } 
    );

    Шоткод [honeypot extra] добавил в форму поле типа text с именем extra. Подробней можно почитать здесь — https://contactform7.com/2015/01/10/adding-a-custom-form-tag/
    Теперь при получении формы остается проверить что это поле не заполнено, тогда считаем что форма заполнена человеком. Человек просто не увидит это поле. Если поле заполнено, считаем что заполнял робот и отправляем информацию в спам.

    А проверяем так

    // Custom validation - https://contactform7.com/2015/03/28/custom-validation/
    function cf7_validate_honeypot( $result, $tag ) {
        $name = $tag->name;
        $value = isset( $_POST[$name] ) ? trim( $_POST[$name] ) : '';
        if ( $value !== '' ) {
            $result->invalidate( $tag, "Ошибка: форма заполнена неправильно." );
        }
        return $result;
    }
    add_filter( 'wpcf7_validate_honeypot', 'cf7_validate_honeypot', 10, 2 );

    При отладке всей этой радости возникают вопросы.

    Как отменить отправку формы на почту во время экспериментов — можно так

    И еще вопрос. Как заполнить то самое скрытое поле и автоматически отправить форму, чтобы проверить что все работает корректно.

    Вот такая кнопка и JS скрипт решают проблему

    window.addEventListener( 'load', function() {
      // console.log('All assets are loaded');
      // 
      // stupid bot
      // 
      // в редакторе страницы WP к кнопке на вкладке "Дополнительно"
      // надо добавить класс button-fill
      const button_fill = document.querySelector('.button-fill');
      button_fill.onclick = function() {
        // при нажатии на кнопку заполняются поля формы
        // 'extra' - скрытое поле honeypot
        // форма отправляется на сервер
        // если форма единственная на странице, к ней можно обратится const form = document.forms[0];
        // const form = document.forms[0]; 
        // Чтобы обратиться к форме по id в шоткоде нужно добавить html_id
        // [contact-form-7 id="0729efd" title="Test form with one field" html_id="form-with-honeypot"]
        const form = document.forms['form-with-honeypot'];
        form.elements['simple-text'].value = new Date();;
        form.elements['extra'].value = "some text";
        form.submit();
        alert('Форма отправлена на сервер - все поля заполнены');
      };
    } );

    Скачать можно здесь — https://github.com/vvhromov/cf7honeypot

    Если нет времени или желания разбираться самостоятельно – обращайтесь