Перейти к содержимому

RadicalForm для Joomla – профессиональная AJAX-форма обратной связи для Joomla с антиспамом

RadicalForm — форма обратной связи для Joomla без ограничений. Полная совместимость с любыми расширениями, AJAX-обработка и встроенная защита от ботов.

Плагин распространяется по принципу «как есть». Поддержка оказывается индивидуально по запросам и может быть бесплатной или платной в зависимости от задачи. Предложения по развитию можно обсудить в чатах Telegram или MAX.

Системные требования

  • Минимальная версия PHP
    8.2
  • Минимальная версия Joomla
    5.2

История изменений

Просмотреть историю версий RadicalForm можно по ссылке:

Что умеет плагин

  • Бесплатный системный плагин для Joomla, не требующий jQuery.
  • Работает с обычной HTML-разметкой, конструкторами страниц, интернет-магазинами и модальными окнами.
  • Отправляет формы через AJAX; количество форм на странице не ограничено.
  • Поддерживает HTML5-валидацию, обязательные поля, checkbox и select multiple.
  • Позволяет назначать адресатов, тему письма, Reply-To, копии CC/BCC и индивидуальные настройки через rfTarget.
  • Загружает несколько файлов, контролирует хранилище и при необходимости прикрепляет файлы к письму.
  • Ведёт историю обычных и заблокированных отправок и экспортирует данные в CSV.
  • Собирает разрешённые UTM-метки и передаёт их вместе с формой.
  • Содержит антиспам по времени, IP и содержимому, JavaScript-проверку браузера и ограничения массовых отправок.
  • Интегрируется с Telegram, MAX, JivoSite и Verbox.
  • Поддерживает переопределение шаблона письма, собственные PHP-макеты и плагины группы radicalform.
  • Корректно работает с кешированием Joomla и многоязычными сайтами.

Руководство актуализировано для RadicalForm 4.2.6.

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

RadicalForm не генерирует разметку формы: вы размещаете обычные элементы HTML там, где они нужны в шаблоне, модуле или конструкторе страниц.

  1. Рекомендуемый контейнер — тег <form>. Если он содержит кнопку .rf-button-send, RadicalForm автоматически добавит ему класс rf-form. Когда среда уже создаёт внешний <form>, используйте нейтральный контейнер, например <div class="rf-form">; вкладывать один тег <form> в другой нельзя.
  2. Кнопке отправки назначьте класс rf-button-send. Для кнопки внутри <form> рекомендуется указать type="button".
  3. Каждому передаваемому полю задайте атрибут name. Поля без name RadicalForm игнорирует.

Атрибуты action и method не требуются: запрос формирует JavaScript плагина.

Для простейшей формы обратной связи из одного поля код будет выглядеть так:
<form class="rf-form">
<input class="uk-input" name="phone" placeholder="Введите номер телефона" type="tel" required>
<button type="button" class="uk-button rf-button-send">Заказать звонок</button>
</form>

Кнопка с классом rf-button-send должна находиться внутри контейнера .rf-form. При ошибке RadicalForm покажет сообщение и выведет проблемные элементы в консоль браузера.

Класс required отмечает обязательное поле. Если оно пустое, RadicalForm добавит CSS-классы, указанные в параметре «CSS класс для невалидных полей». Можно также использовать стандартные атрибуты HTML5 required, type и pattern.

Что настроить после установки?

  1. Если нужна почта, оставьте включённой «Отправку email» и укажите основной адрес. При необходимости заполните CC, BCC, Reply-To и альтернативных адресатов.
  2. Проверьте CSS-классы невалидных полей и ошибок загрузки файлов. Значения по умолчанию подходят Bootstrap и UIkit, но их можно заменить классами вашего шаблона.
  3. Проверьте JavaScript №2. По умолчанию RadicalForm использует Joomla.renderMessages(), а если эта функция недоступна — обычный alert().
  4. Включите только нужные интеграции, загрузку файлов, UTM-метки и механизмы антиспама. Дополнительная JavaScript-проверка и ограничения массовых отправок по умолчанию выключены.

Имена полей и перевод

Подпись поля в письме и истории формируется из атрибута name. Для перевода создайте переопределение языковой константы Joomla. Например, для name="phone" создайте константу PHONE со значением «Телефон».

<input class="uk-input" name="phone" type="tel" required>

Если перевод должен работать и на сайте, и в панели управления, создайте переопределение для обеих областей.

Зарезервированные имена

Нельзя использовать служебные имена Joomla: option, plugin, group, format, module, template, method. Также зарезервированы поля RadicalForm: rfJsAction, rfJsChallenge, rfJsProof, rfJsPermit. Проверка выполняется без учёта регистра.

При конфликте переименуйте поле, например format в contact_format. RadicalForm проверяет имена и в браузере, и на сервере.

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

Тогда перевод ваших языковых переменных отобразится и в истории отправленных сообщений в настройках плагина.

JavaScript №1, №2, №3 и обработчик ошибок №9

JavaScript №1–3 выполняется после успешной отправки. Без атрибута data-rf-call вызывается JavaScript №2. В каждый обработчик передаются переменные rfMessage — текст результата и here — нажатая кнопка.

Значение JavaScript №2 по умолчанию создаёт рядом с кнопкой контейнер и выводит сообщение через Joomla.renderMessages(). Если функция Joomla недоступна, используется alert(rfMessage). Код можно заменить под ваш шаблон, например:

UIkit.modal.alert(rfMessage);

Атрибут data-rf-call="13" последовательно вызовет обработчики №1 и №3. Цифра 0 имеет особое значение: JavaScript №0 запускается до отправки.

Отдельный вывод ошибок

Если включить «Использовать отдельный код для вывода ошибок», для ошибок будет вызываться JavaScript №9. Ему также доступны rfMessage и here. Если отдельный обработчик выключен, RadicalForm использует первый доступный обработчик сообщения, обычно JavaScript №2.

Всплывающие окна

Чтобы после успешной отправки закрыть модальное окно и показать сообщение, поместите закрытие окна в JavaScript №1:

UIkit.modal(document.querySelector('#callback')).hide();

Затем вызовите №1 и №2 одной кнопкой:

<button type="button" class="uk-button uk-button-primary rf-button-send" data-rf-call="12">Отправить заявку</button>

Если библиотека модального окна переносит разметку в конец документа, проверьте в инструментах разработчика, что кнопка после открытия по-прежнему находится внутри .rf-form.

JavaScript №0 перед отправкой

JavaScript №0 позволяет добавить или изменить данные непосредственно перед отправкой. Для его вызова атрибут data-rf-call должен начинаться с нуля, например data-rf-call="02".

const code = document.querySelector('#product-code')?.textContent?.trim();
const form = here.closest('.rf-form');
if (code && form) {
    let field = form.querySelector('input[name="article"]');
    if (!field) {
        field = document.createElement('input');
        field.type = 'hidden';
        field.name = 'article';
        form.append(field);
    }
    field.value = code;
}

В JavaScript №0 доступны here и needReturn. Возврат false отменяет отправку:

if (!confirm('Отправить форму?')) {
    return false;
}

Сообщение после отправки

Текст успешного результата задаётся параметром «Сообщение после отправки формы». Его получает JavaScript №2 или обработчики, перечисленные в data-rf-call. Поле поддерживает HTML, но способ отображения должен уметь его обработать.

Индивидуальное сообщение формы

Для разных форм можно назначить JavaScript №3 и прочитать сообщение из data-атрибута кнопки:

UIkit.modal.alert(String(here.dataset.rfText));
<button type="button" class="uk-button rf-button-send"
        data-rf-call="3" data-rf-text="Мы вам перезвоним">
    Отправить заявку
</button>

Не помещайте пользовательский ввод в HTML без экранирования.

Цели Яндекс Метрики

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

UIkit.modal.alert(rfMessage);
if (typeof ym === 'function') {
    ym(12345678, 'reachGoal', 'FORM_SENT');
}

Замените номер счётчика и имя цели своими значениями. Код выполняется только после успешной обработки формы сервером.

Тема письма

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

Заказ на сайте. Телефон: {phone}

Для множественного поля значения объединяются через запятую. Если поля нет, маркер остаётся без замены. Также доступен маркер {rfLatestNumber} с номером записи.

Индивидуальная тема письма

Скрытое поле rfSubject переопределяет тему для конкретной формы. В индивидуальной теме тоже работают подстановки:

<input type="hidden" name="rfSubject" value="Заказ {product_name}">

Выбор адресата через rfTarget

Скрытое поле rfTarget связывает форму с альтернативными адресами email, получателями Telegram и MAX, а также с собственными PHP-макетами:

<input type="hidden" name="rfTarget" value="sales">

Укажите тот же Target ID у всех получателей, которым должна уйти эта форма. Получатели с пустым Target ID используются для форм без rfTarget.

Поле Reply-To

Параметр «Имя поля “Ответить на”» указывает, из какого поля формы брать адрес ответа. Значение по умолчанию — email. Если форма использует другое имя, укажите его в настройке. Поле должно содержать корректный email-адрес.

Обязательные поля и HTML5-валидация

RadicalForm поддерживает два способа проверки:

  • CSS-класс required проверяет непустое значение, а для checkbox — состояние checked;
  • стандартные ограничения HTML5 проверяются методом браузера checkValidity().
<input class="uk-input" name="email" type="email" required>
<input class="uk-input" name="quantity" type="text" pattern="\d+" required>

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

Тексты ошибок полей

Индивидуальную подсказку удобно разместить сразу после поля и показывать её, когда RadicalForm добавит класс ошибки:

<input class="uk-input" name="email" type="email" required>
<div class="rf-field-error">Укажите корректный email</div>
.rf-field-error {
    display: none;
    color: #b42318;
}
.is-invalid + .rf-field-error,
.uk-form-danger + .rf-field-error {
    display: block;
}

Checkbox и select multiple

Поля с несколькими значениями должны иметь одинаковое имя с суффиксом []:

<label><input type="checkbox" name="service[]" value="delivery"> Доставка</label>
<label><input type="checkbox" name="service[]" value="installation"> Установка</label>

<select name="city[]" multiple>
    <option value="moscow">Москва</option>
    <option value="kazan">Казань</option>
</select>

RadicalForm передаст все выбранные значения; в письме они объединяются разделителем из настроек.

Сообщение «Подождите»

Во время запроса кнопка блокируется, а её содержимое временно заменяется текстом из параметра «Сообщение “Подождите”». После ответа исходное содержимое восстанавливается. Можно использовать HTML, например спиннер вашего шаблона.

Загрузка файлов

Сначала включите «Разрешить загрузку файлов» на вкладке «Файлы». Полю задайте класс rf-upload-button и уникальное имя:

<input class="rf-upload-button" name="documents" type="file" multiple>
<div class="rf-filenames-list"></div>

.rf-filenames-list должен находиться внутри той же .rf-form. В нём отображаются загруженные файлы, ошибки и кнопки удаления.

Для кастомной кнопки элемент .rf-upload-button-text разместите рядом с input внутри общего родителя:

<div class="uk-form-custom" uk-form-custom>
    <button type="button" class="uk-button rf-upload-button-text">Приложить файлы</button>
    <input class="rf-upload-button" name="photos" type="file" multiple>
</div>

По умолчанию в сообщение добавляются ссылки на файлы. Параметр «Вставлять файлы в письмо как вложения» дополнительно прикрепляет их с учётом ограничения размера. Проверьте максимальный объём хранилища, срок хранения и путь скачивания.

Telegram

  1. Создайте бота через @BotFather командой /newbot.
  2. Включите Telegram, вставьте HTTP API token и сохраните плагин.
  3. Отправьте боту сообщение, затем нажмите «Обновить chat_id».
  4. Выберите получателей и при необходимости задайте им Target ID.

Если Telegram недоступен напрямую, RadicalForm поддерживает SOCKS5-прокси, включая DNS через прокси.

MAX

  1. Получите токен чат-бота MAX, включите интеграцию, вставьте токен и сохраните настройки.
  2. Нажмите «Проверить подключение MAX». RadicalForm отдельно проверит сеть, доверие TLS-сертификату и токен.
  3. Отправьте сообщение боту и нажмите «Обновить MAX ID». При первом нажатии может быть только сохранён маркер обновлений — тогда отправьте новое сообщение и повторите обновление.
  4. Для каждого получателя проверьте ID, тип user_id или chat_id и Target ID.

Переопределение шаблона письма

Скопируйте /plugins/system/radicalform/tmpl/default.php в /templates/your_template/html/plg_system_radicalform/default.php, заменив your_template именем активного шаблона.

Макету доступны подготовленные переменные $subject, $header, $mainbody и $footer. Массив полей формы называется $input; переменной $source в RadicalForm 4 нет.

Если вы заново формируете тело письма, используйте актуальный класс Joomla:

use Joomla\CMS\Language\Text;

$mainbody = '';
foreach ($input as $key => $record) {
    if (is_array($record)) {
        $record = implode(', ', $record);
    }
    $label = htmlspecialchars(Text::_($key), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
    $value = htmlspecialchars((string) $record, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
    $mainbody .= '<p>' . $label . ': <strong>' . $value . '</strong></p>';
}

После обновления RadicalForm сравните переопределение с актуальным default.php в репозитории: Joomla не обновляет файлы шаблона автоматически.

JivoSite и Verbox

Установите код нужного виджета на сайте и включите соответствующий переключатель RadicalForm. Поля name, phone и email передаются в карточку клиента, если присутствуют в форме. Текст заявки отправляется в чат после успешной обработки.

Собственный PHP-код

Создайте PHP-файл в /templates/your_template/html/plg_system_radicalform/, включите «Использовать свой код» и укажите имя файла в поле Layout. Для выполнения только у определённой формы задайте одинаковый Target ID в настройке макета и в поле rfTarget.

<?php
defined('_JEXEC') or die;

if (isset($input['name'])) {
    $contactName = (string) $input['name'];
}

В собственном макете массив пользовательских полей называется $input. Также доступны $params, $target, $formID и подготовленные части письма. Не переопределяйте $body: в этой переменной RadicalForm хранит готовое письмо. Не выводите текст через echo — неожиданный вывод записывается в журнал.

Плагины RadicalForm

Для повторно используемой интеграции создайте плагин группы radicalform. В RadicalForm 4.2.6 предпочтительно событие onBeforeProcessRadicalForm с объектом события:

use Joomla\Plugin\System\RadicalForm\Event\BeforeProcessRadicalFormEvent;

public function onBeforeProcessRadicalForm(BeforeProcessRadicalFormEvent $event): void
{
    $input =& $event->getInput();
    $input['name'] = trim((string) ($input['name'] ?? ''));
}

$event->getClearInput() возвращает данные без служебных полей, $event->getInput() — полный изменяемый массив, а $event->getParams() — параметры RadicalForm с дополнительными значениями uploaddir и rfLatestNumber.

Старое событие onBeforeSendRadicalForm($clear, &$input, $params) продолжает вызываться для совместимости. Чтобы отклонить отправку, результат обработчика должен содержать ['send' => false, 'message' => 'Причина', 'fields' => ['email']]; обычная строка игнорируется. Для нового кода используйте объект события Joomla.

Скачать пример плагина RadicalForm

UTM-метки

Включите «Отслеживать UTM-метки», чтобы сохранить параметры из URL и добавить их к заявке. По умолчанию разрешены utm_source, utm_medium, utm_campaign, utm_term и utm_content; список можно изменить.

Время хранения задаётся в минутах. Значение 0 хранит метки до окончания текущей сессии Joomla. Не добавляйте в разрешённый список секретные или произвольные параметры URL.

История и экспорт CSV

На вкладке «История отправки форм» доступны журналы сообщений и спама. Можно показывать Target ID, Form ID и дополнительную информацию о посетителе, очищать историю, сбрасывать нумерацию и экспортировать записи в CSV, в том числе с раскладкой по полям.

Размер журнала ограничивается параметром «Очищать лог при достижении». RadicalForm совместим с ротацией журналов Joomla. CSV-экспорт экранирует разделители, кавычки и переносы строк, а также защищает значения, похожие на формулы электронных таблиц.

Интеграция с Bitrix24 CRM

Готовую интеграцию предлагает плагин WT JoomShopping Bitrix24 PRO, который поддерживает RadicalForm. Для собственной интеграции можно использовать пример кода как отправную точку, предварительно адаптировав авторизацию и поля под свою CRM.

Интеграция с AmoCRM

Для AmoCRM доступен плагин WT AmoCRM — RadicalForm; проверьте на странице разработчика актуальные требования к библиотеке и Joomla. Для собственной реализации доступен пример интеграции. Настройки CRM индивидуальны, поэтому готовый код необходимо проверить и адаптировать.


Антиспам

На вкладке «АнтиСпам» собраны независимые проверки. Блокировка по времени, IP и содержимому настраивается отдельно от JavaScript-проверки и ограничений массовых отправок.
Сообщение при блокировке

В этом поле можно указать сообщение, которое будет выводиться пользователям (или ботам), чье сообщение воспринято как спам.

Можно указать непосредственно сообщение или языковую константу, которую можно переопределить.

Блокируемые диапазоны задержки перед отправкой формы

Можно указать блокируемые диапазоны задержки перед отправкой формы. Используется метрика "Через какое время после загрузки страницы отправлена форма".

Чтобы лучше понять смысл этой блокировки, нужно увидеть поведение некоторых ботов.

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

Например:

0-4, 12-13

Форма будет заблокирована, если значение rf-duration попадает в диапазон от 0 до 4 секунд или от 12 до 13 секунд. Используйте эту проверку только после анализа истории: слишком широкий диапазон может затронуть реальных посетителей.

Черный список IP
Тут особых пояснений не требуется. Одна строка – один IP. Можно указывать не только точный IP, но и подсети с маской (в CIDR-нотации). Примеры: 203.0.113.15 или 198.51.100.0/24. Строки, начинающиеся с #, игнорируются.
Правила блокировки по содержимому

Правила блокируют форму по содержимому выбранных полей. В поле «Поля» укажите имена через запятую; значение * или пустое поле проверяет все доступные поля.

  • Режим «Содержит» ищет заданный фрагмент без сложного синтаксиса.
  • Режим «Регулярное выражение» использует PCRE-выражение PHP, включая ограничители и модификаторы, например /(casino|viagra)/iu.

Проверяйте регулярные выражения перед публикацией: ошибочное или слишком общее правило может блокировать нормальные заявки. Готовые примеры приведены ниже.

Примеры регулярных выражений
Любой gmail-адрес:
/@gmail\.com$/i

Gmail-адрес, где перед @ есть точка:
/^[^@\s]+\.[^@\s]+@gmail\.com$/i

Gmail-адрес с несколькими сегментами через точки, что часто встречается у спама:
/^[^@\s]+(?:\.[^@\s]+){2,}@gmail\.com$/i

Ссылка в сообщении:
/(https?:\/\/|www\.)/i

Типичные спам-слова:
/(casino|betting|slots|viagra)/iu

Сообщение только латиница/цифры/символы без пробелов, что часто бывает у мусора:
/^[A-Za-z0-9._-]{12,}$/

i — без учета регистра.
u — корректная работа с UTF-8, включая кириллицу.

JavaScript-проверка браузера

Параметр «Требовать JavaScript для отправки» добавляет одноразовую проверку перед обработкой формы и блокирует прямые HTTP-запросы, которые не выполняют JavaScript-протокол RadicalForm. Проверка выключена по умолчанию.

Можно задать задержку от 100 до 1000 мс и собственное сообщение об ошибке. Значение по умолчанию — 350 мс. Не увеличивайте задержку без необходимости: она добавляется к отправке каждой формы.

Защита от массовых отправок

Два независимых лимита ограничивают поток заявок, которые прошли остальные антиспам-проверки:

  • Блокировка при всплеске считает успешно обработанные формы за выбранный период и после достижения лимита приостанавливает дальнейшие отправки. По умолчанию в интерфейсе предлагаются 30 форм за 10 минут и блокировка на 60 минут.
  • Суточная блокировка задаёт максимум форм за календарные сутки в часовом поясе Joomla. Предлагаемое значение по умолчанию — 200.

Оба механизма выключены по умолчанию. Подберите лимиты с запасом относительно обычного потока заявок. При начале блокировки RadicalForm может один раз отправить уведомление на указанный email; срабатывания сохраняются в истории спама.