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

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

Быстрый ответ: Контактная форма в WordPress делается тремя способами. Способ 1 — плагин (Contact Form 7, WPForms, Fluent Forms): ставится за 5–10 минут, кода писать не нужно. Способ 2 — свой шорткод с обработчиком в functions.php: полный контроль над разметкой и логикой через wp_mail(). Способ 3 — AJAX-форма на admin-ajax.php: отправка без перезагрузки страницы, лучший UX. В любом случае обязательно защищать форму от спама через wp_nonce_field() и honeypot-поле, а для надёжной доставки писем — настроить SMTP.

Форма обратной связи — первое, что просит добавить почти каждый заказчик сайта. Кажется, что это простая задача, но у неё есть подводные камни: письма не доходят, спам-боты заваливают ящик, форма не работает после обновления темы. В этой статье разберём три рабочих способа сделать контактную форму на WordPress — от установки плагина до собственного AJAX-обработчика с примерами PHP и JavaScript. Если вы только начинаете работать с WordPress, сначала загляните в гайд по созданию дочерней темы — весь кастомный код ниже логично складывать именно туда.

Что должна уметь контактная форма

Прежде чем выбирать способ реализации, сформулируем требования к «правильной» форме обратной связи. Хорошая форма:

  • Отправляет письмо на почту администратора (или в CRM) и не теряет заявки.
  • Защищена от спама — боты не должны заваливать ящик мусором.
  • Проверяет данные на стороне сервера, а не только в браузере.
  • Даёт обратную связь пользователю: «заявка отправлена» или «исправьте ошибку».
  • Не ломается при обновлении темы и ядра WordPress.

Три способа ниже закрывают эти требования по-разному: плагин делает почти всё «из коробки», а собственный код даёт контроль над каждым этапом. Выбор зависит от задачи и вашего уровня: новичку проще начать с плагина, а затем, по мере роста, перейти на свой обработчик.

Способ 1. Форма через плагин: Contact Form 7, WPForms, Fluent Forms

Самый быстрый и надёжный вариант — готовый плагин. Для большинства сайтов его возможностей хватает с запасом: поля, валидация, защита от спама, настройка уведомлений и сохранение заявок в базе.

Порядок действий для Contact Form 7 (самый популярный бесплатный вариант):

  1. В админке откройте Плагины → Добавить новый, найдите «Contact Form 7» и активируйте.
  2. После активации появится пункт меню Contact. Там уже создана форма по умолчанию с полями «Имя», «Email», «Тема» и «Сообщение».
  3. В настройках формы укажите адрес, на который отправлять письма: вкладка Почта, поле «Кому».
  4. Скопируйте шорткод формы и вставьте его в нужную запись или страницу.

Шорткод выглядит так:

[contact-form-7 id="123" title="Форма обратной связи"]

У WPForms и Fluent Forms аналогичный принцип, но есть визуальный конструктор — форму собирают перетаскиванием полей, а не правкой HTML-разметки. Их шорткоды выглядят похоже:

[wpforms id="42"]
[fluentform id="7"]

Плюсы: быстро, без кода, встроенная защита (reCAPTCHA, honeypot), сохранение заявок в админке, экспорт в CSV.

Минусы: зависимость от плагина, лишний вес на сайте, разметка формы «как есть» — тонкая настройка стилей требует CSS-хаков. Если плагин перестанет обновляться, форму придётся переделывать.

Плагины — вообще самый простой путь в WordPress для новичка. Подборку того, что стоит поставить сразу после установки движка, смотрите в статье про топ-10 плагинов WordPress для начинающих.

Способ 2. Свой шорткод и обработчик в functions.php

Когда нужен полный контроль над разметкой и логикой — например, форма встраивается в кастомный блок или нужно писать заявки сразу в несколько мест, — форму делают вручную. Код складываем в functions.php дочерней темы.

Сначала создаём шорткод, который выводит HTML-форму. Шорткоды — удобный механизм вставки кусков кода в контент; если тема для вас новая, почитайте гайд по созданию своих шорткодов в WordPress.

add_shortcode( 'dscw_contact_form', 'dscw_render_contact_form' );

function dscw_render_contact_form() {
    ob_start();
    ?>
    <form method="post" class="dscw-contact-form">
        <?php wp_nonce_field( 'dscw_contact_action', 'dscw_contact_nonce' ); ?>
        <input type="text" name="dscw_name" placeholder="Ваше имя" required>
        <input type="email" name="dscw_email" placeholder="Email" required>
        <textarea name="dscw_message" placeholder="Сообщение" rows="5" required></textarea>
        <input type="text" name="dscw_website" class="dscw-hp" tabindex="-1" autocomplete="off" aria-hidden="true">
        <button type="submit">Отправить</button>
    </form>
    <?php
    return ob_get_clean();
}

Обратите внимание на два важных момента:

  • wp_nonce_field() добавляет скрытое поле с одноразовым ключом безопасности (nonce). Без него форма не пройдёт проверку в обработчике.
  • Поле dscw_website с классом dscw-hp — это honeypot, «ловушка» для ботов. Реальный пользователь его не видит (мы спрячем его через CSS), а бот, который заполняет все поля подряд, попадётся.

Теперь обработчик, который принимает данные и отправляет письмо:

add_action( 'init', 'dscw_handle_contact_form' );

function dscw_handle_contact_form() {
    if ( ! isset( $_POST['dscw_contact_nonce'] ) ) {
        return;
    }
    if ( ! wp_verify_nonce( $_POST['dscw_contact_nonce'], 'dscw_contact_action' ) ) {
        wp_die( 'Ошибка проверки безопасности.' );
    }

    // Honeypot: поле заполнил только бот
    if ( ! empty( $_POST['dscw_website'] ) ) {
        wp_die( 'Спам не пройдёт.' );
    }

    $name    = isset( $_POST['dscw_name'] ) ? sanitize_text_field( wp_unslash( $_POST['dscw_name'] ) ) : '';
    $email   = isset( $_POST['dscw_email'] ) ? sanitize_email( wp_unslash( $_POST['dscw_email'] ) ) : '';
    $message = isset( $_POST['dscw_message'] ) ? sanitize_textarea_field( wp_unslash( $_POST['dscw_message'] ) ) : '';

    if ( ! $name || ! is_email( $email ) || ! $message ) {
        wp_die( 'Заполните все поля корректно.' );
    }

    $to      = get_option( 'admin_email' );
    $subject = 'Новая заявка с сайта';
    $body    = "Имя: {$name}\nEmail: {$email}\n\nСообщение:\n{$message}";
    $headers = array( 'Reply-To: ' . $name . ' <' . $email . '>' );

    wp_mail( $to, $subject, $body, $headers );

    $back = wp_get_referer() ? wp_get_referer() : home_url( '/' );
    wp_safe_redirect( add_query_arg( 'dscw_sent', '1', $back ) );
    exit;
}

Разберём ключевые моменты. wp_verify_nonce() проверяет, что форма отправлена с нашего сайта, а не с чужого домена. Функции sanitize_text_field(), sanitize_email() и sanitize_textarea_field() очищают данные от опасных символов — это базовая гигиена, о которой новички часто забывают. А wp_unslash() убирает лишние обратные слэши, которые WordPress добавляет к данным из $_POST.

Осталось показать пользователю сообщение об успешной отправке. Добавим его в начало контента страницы, если в адресе есть параметр dscw_sent:

add_filter( 'the_content', 'dscw_show_success_message' );

function dscw_show_success_message( $content ) {
    if ( isset( $_GET['dscw_sent'] ) ) {
        $content = '<p class="dscw-success">Спасибо! Заявка отправлена.</p>' . $content;
    }
    return $content;
}

И не забудьте спрятать honeypot-поле от реальных посетителей:

.dscw-hp {
    position: absolute;
    left: -9999px;
}

Этот способ хорош тем, что не зависит от плагинов и работает на любом сайте. Больше готовых решений для functions.php ищите в подборке полезных сниппетов для functions.php.

Способ 3. AJAX-форма без перезагрузки страницы

Минус предыдущего способа в том, что при отправке страница перезагружается. Пользователю это не нравится: он теряет позицию прокрутки и не всегда понимает, ушла ли заявка. AJAX решает проблему — форма отправляется «в фоне», а ответ появляется прямо под кнопкой.

В WordPress для этого используют admin-ajax.php и два хука: wp_ajax_ для авторизованных пользователей и wp_ajax_nopriv_ для гостей. Про сами хуки подробно рассказано в статье про actions и filters в WordPress.

Сначала — шорткод формы (почти тот же, но поле nonce называется nonce, а под формой есть контейнер для статуса):

add_shortcode( 'dscw_contact_form_ajax', 'dscw_render_ajax_form' );

function dscw_render_ajax_form() {
    ob_start();
    ?>
    <form method="post" class="dscw-contact-form--ajax" novalidate>
        <?php wp_nonce_field( 'dscw_contact_action', 'nonce' ); ?>
        <input type="text" name="name" placeholder="Ваше имя" required>
        <input type="email" name="email" placeholder="Email" required>
        <textarea name="message" placeholder="Сообщение" rows="5" required></textarea>
        <button type="submit">Отправить</button>
        <p class="dscw-form-status" role="status"></p>
    </form>
    <?php
    return ob_get_clean();
}

Теперь серверный обработчик AJAX-запроса:

add_action( 'wp_ajax_dscw_contact_ajax', 'dscw_contact_ajax_handler' );
add_action( 'wp_ajax_nopriv_dscw_contact_ajax', 'dscw_contact_ajax_handler' );

function dscw_contact_ajax_handler() {
    check_ajax_referer( 'dscw_contact_action', 'nonce' );

    $name    = isset( $_POST['name'] ) ? sanitize_text_field( wp_unslash( $_POST['name'] ) ) : '';
    $email   = isset( $_POST['email'] ) ? sanitize_email( wp_unslash( $_POST['email'] ) ) : '';
    $message = isset( $_POST['message'] ) ? sanitize_textarea_field( wp_unslash( $_POST['message'] ) ) : '';

    if ( ! $name || ! is_email( $email ) || ! $message ) {
        wp_send_json_error( array( 'message' => 'Заполните все поля корректно.' ), 400 );
    }

    $to      = get_option( 'admin_email' );
    $subject = 'Новая заявка с сайта';
    $body    = "Имя: {$name}\nEmail: {$email}\n\nСообщение:\n{$message}";
    $headers = array( 'Reply-To: ' . $name . ' <' . $email . '>' );

    $sent = wp_mail( $to, $subject, $body, $headers );

    if ( $sent ) {
        wp_send_json_success( array( 'message' => 'Спасибо! Заявка отправлена.' ) );
    }

    wp_send_json_error( array( 'message' => 'Не удалось отправить. Попробуйте позже.' ), 500 );
}

Здесь вместо wp_die() используются wp_send_json_success() и wp_send_json_error() — они отдают ответ в формате JSON, который читает JavaScript на фронтенде.

Подключаем скрипт и передаём ему адрес admin-ajax.php:

add_action( 'wp_enqueue_scripts', 'dscw_enqueue_ajax_form' );

function dscw_enqueue_ajax_form() {
    wp_enqueue_script(
        'dscw-contact-ajax',
        get_stylesheet_directory_uri() . '/js/form.js',
        array(),
        '1.0.0',
        true
    );
    wp_localize_script( 'dscw-contact-ajax', 'dscwAjax', array(
        'url' => admin_url( 'admin-ajax.php' ),
    ) );
}

И сам скрипт — файл js/form.js в дочерней теме:

document.addEventListener( 'DOMContentLoaded', function () {
    var form = document.querySelector( '.dscw-contact-form--ajax' );
    if ( ! form ) {
        return;
    }

    var status = form.querySelector( '.dscw-form-status' );

    form.addEventListener( 'submit', function ( e ) {
        e.preventDefault();

        var data = new FormData( form );
        data.append( 'action', 'dscw_contact_ajax' );

        fetch( dscwAjax.url, {
            method: 'POST',
            body: data,
            credentials: 'same-origin'
        } )
            .then( function ( res ) { return res.json(); } )
            .then( function ( json ) {
                var msg = ( json.data && json.data.message ) ? json.data.message : 'Ошибка';
                status.textContent = msg;
                if ( json.success ) {
                    form.reset();
                }
            } )
            .catch( function () {
                status.textContent = 'Ошибка соединения. Попробуйте ещё раз.';
            } );
    } );
} );

Ключевая деталь — строка data.append( 'action', 'dscw_contact_ajax' ). Параметр action сообщает WordPress, какой обработчик вызвать: именно от его значения зависит, к какому хуку wp_ajax_* попадёт запрос. Nonce при этом уже лежит в форме как скрытое поле и отправляется вместе с остальными данными.

Защита формы от спама: nonce, honeypot и reCAPTCHA

Форма без защиты — магнит для спам-ботов. Три уровня защиты, которые стоит комбинировать:

1. Nonce (одноразовый ключ). Это обязательный минимум. Скрытое поле с уникальным ключом генерируется при выводе формы, а обработчик проверяет его через wp_verify_nonce(). Подделать запрос с чужого сайта без ключа бот не сможет.

2. Honeypot (ловушка). Скрытое поле, которое не видит человек, но заполняет «тупой» бот. Если поле не пустое — это спам, и запрос отклоняется. Реализация выше: поле dscw_website, спрятанное через CSS.

3. reCAPTCHA. Сервис Google, который отличает человека от бота по поведению. В плагинах вроде Contact Form 7 подключается галочкой и ключами от Google, в самописную форму — сложнее: нужны ключи и проверка ответа на сервере через HTTP-запрос к Google.

Начинать стоит с nonce и honeypot — этого хватает для большинства небольших сайтов. reCAPTCHA добавляют, когда спам продолжает приходить. Про другие настройки, которые защищают сайт от взлома, читайте в гайде по безопасности WordPress для новичков.

Сравнение трёх способов

Критерий Плагин (CF7 / WPForms) Свой шорткод + обработчик AJAX-форма
Сложность внедрения Минимальная Средняя Выше средней
Нужно писать код Нет Да (только PHP) Да (PHP + JS)
Время на внедрение 5–10 минут 30–60 минут 1–2 часа
Гибкость разметки Ограничена настройками Полная Полная
Отправка без перезагрузки Зависит от плагина Нет Да
Защита от спама Встроена (reCAPTCHA, honeypot) Nonce + honeypot Nonce + honeypot
Зависимость от плагина Да Нет Нет
Кому подходит Новичкам без опыта кода Тем, кто хочет контроль без лишнего JS Тем, кому важен UX и производительность

Практическая рекомендация: если сайт простой и задача «лишь бы работало» — ставьте плагин. Если форма — часть кастомной темы или нужен полный контроль — пишите свой шорткод. AJAX-версия оправдана, когда форма на видном месте и важна конверсия: отсутствие перезагрузки заметно повышает шанс, что пользователь доведёт отправку до конца.

Почему письма не доходят и как это исправить

Самая частая жалоба после «форма не работает» — «заявки не приходят на почту». Причина почти всегда в том, что WordPress отправляет письма через функцию wp_mail(), которая по умолчанию использует встроенный почтовый сервер хостинга. Такие письма часто попадают в спам или не отправляются вовсе.

Решение — настроить SMTP: отправку писем через сторонний почтовый сервис с авторизацией. Это делается плагином (например, WP Mail SMTP или FluentSMTP) или несколькими строками в functions.php. После настройки письма уходят от имени вашего домена и доходят до адресата.

Второй важный момент — сохранение заявок. Полагаться только на почту рискованно: письмо может затеряться. Плагины вроде WPForms и Fluent Forms умеют хранить заявки в базе и показывать их в админке. Для самописной формы можно сохранять заявки в кастомный тип записи или хотя бы дублировать их в лог-файл. Если боитесь потерять данные сайта в целом — настройте резервное копирование WordPress.

Частые ошибки новичков

  1. Код в родительской теме. Добавили форму в functions.php активной темы — при её обновлении код сотрётся. Только дочерняя тема или отдельный плагин.
  2. Забытый nonce. Без wp_nonce_field() и wp_verify_nonce() форма открыта для поддельных запросов и спама.
  3. Нет серверной валидации. Атрибут required в HTML проверяет только в браузере — его легко обойти. Всегда проверяйте и очищайте данные в PHP.
  4. Данные без очистки. Вставка $_POST напрямую в письмо или базу — путь к XSS-уязвимости. Используйте sanitize_text_field(), sanitize_email(), sanitize_textarea_field().
  5. Письма уходят в спам. Не настроен SMTP, письмо отправляется с хостингового сервера. Настройте SMTP и укажите корректный Reply-To.
  6. Перепутаны хуки AJAX. Забыли wp_ajax_nopriv_* — и форма не работает для незалогиненных посетителей, то есть почти для всех.

TimeWeb

Часто задаваемые вопросы

Какой способ создания формы выбрать новичку?

Начните с плагина Contact Form 7 или WPForms — это займёт 5–10 минут и не потребует кода. Когда понадобится полный контроль над разметкой и логикой, переходите на собственный шорткод с обработчиком, а затем — на AJAX-версию без перезагрузки страницы.

Почему письма с формы не приходят на почту?

Чаще всего потому, что WordPress отправляет письма через встроенный сервер хостинга, и они попадают в спам или не уходят вовсе. Настройте SMTP через плагин (WP Mail SMTP, FluentSMTP) или код в functions.php, чтобы письма отправлялись от имени вашего домена с авторизацией.

Обязательно ли использовать nonce в контактной форме?

Да, это обязательный минимум защиты. Nonce — одноразовый ключ, который генерируется при выводе формы и проверяется обработчиком через wp_verify_nonce(). Без него форму можно подделать и использовать для спама или атак.

Можно ли сделать контактную форму без плагина?

Да. Создайте шорткод, который выводит HTML-форму, и обработчик на хуке init, который проверяет nonce, очищает данные и отправляет письмо через wp_mail(). Для отправки без перезагрузки добавьте обработчик на wp_ajax_ и JavaScript-скрипт.

Как защитить форму от спама без reCAPTCHA?

Используйте связку nonce и honeypot: nonce отсекает поддельные запросы, а honeypot-поле (скрытое поле, которое заполняет только бот) отлавливает автоматический спам. Этого достаточно для большинства небольших сайтов; reCAPTCHA подключают, если спам продолжается.

Куда сохранять заявки, чтобы не потерять их?

Не полагайтесь только на почту. Плагины WPForms и Fluent Forms хранят заявки в базе и показывают их в админке. Для самописной формы сохраняйте заявки в кастомный тип записи или дублируйте в лог. Дополнительно настройте резервное копирование сайта.

Вывод

Контактная форма в WordPress — задача с тремя уровнями сложности: плагин за 10 минут для быстрого старта, собственный шорткод с обработчиком для полного контроля и AJAX-версия для лучшего пользовательского опыта. Какой бы способ вы ни выбрали, соблюдайте три правила: проверяйте и очищайте данные на сервере, защищайте форму nonce и honeypot, настраивайте SMTP для доставки писем.

Если нужна форма с интеграцией в CRM, сложная логика или полноценная разработка на WordPress — команда студии «Делай Сайт» реализует это под ключ. Посмотрите наше портфолио или свяжитесь с нами — подскажем оптимальное решение под вашу задачу.

Статья написана для блога delai-sait.ru — разработка и поддержка сайтов на WordPress.

Clearfy

Поделиться:
Telegram ВКонтакте