Форма обратной связи — один из самых част встречающихся элементов на сайте и сейчас я хочу рассказать о том как сделать её на основе компонента, при этом не используя встроенный в битрикс модуля «Веб-формы» т.к. он доступен только начиная с лицензии «Стандарт», а подавляющее большинство сайтов не имеющих отношения к Интернет-торговле делаются на редакции «Старт». Так же мы учтём в форме один маленький лайфхак который я узнал на курсе Бизнес молодость ЦЕХ, который мне посчастливилось проходить летом 2019-го года. И так, поехали.
Подготовка компонента
Чтобы сэкономить время, предлагаю установить один прикольный модуль «Мастер создания компонента», он позволит быстро и без лишних телодвижений создать простой макет нашего компонента формы обратной связи. Устанавливаем компонент через страницу на маркетплейсе или через админку.
Затем переходим в раздел: Настройки -> Настройки продукта -> Список мастеров, тут ищем «Мастер создания компонента» и в контекстном меню напротив, выбираем пункт «Установить»:
Для нашего компонента я выбрал следующие базовые настройки:
- Тип компонента — простой
- Пространство имён — custom
- Идентификатор — emptyscript
- Название — Пустой скрипт
- Описание — Заготовка под кастомный компонент
- Категория в списке компонентов — Custom
Почему пустой скрипт? Т.к. функциональность формы крайне простая мы будем описывать бизнес логику формы в файлах component_epilog.php или доп.файлах ajax.php в папке шаблона компонента. А сам компонент emptyscript послушит каркасом для ряда простых форм.
Опции шаблона компонента следующие:
Мы будем использовать jQuery Ajax для обработки формы, а так же будем хранить стили компонента прямо в папке шаблона. В итоге настройки для мастера будут должны получиться примерно такими:
Нажимаем «Создать», ждём пару секунд, готово! Компонент успешно создан! Можете поблагодарить автора компонента донатом, он действительно экономит кучу времени. Давайте создадим какой-нибудь раздел на сайте и разместим нашу заготовку.
Перейдём к описанию самой формы.
Шаблон формы обратной связи
Допустим вы фрилансер, вебмастер, у вас есть свой landing-page и вы хотите подвесить туда форму обратной связи. Как будет выглядеть наш шаблон? Какую информацию будем собирать о клиенте? Предлагаю собрать следующее:
- Имя
- Контактный телефон
- Сайт (если есть)
- Описание проблемы или задачи которую хочет решить клиент
- Уточнение способа связи (та самая фишка от БМ)
- Согласие с политикой конфиденциальности
Основываясь на этом списке, делаем форму:
Первые три поля обязательны, т.к. нам нужна эта информация чтобы дозвониться до клиента и обсудить проект, а если не дозвонились то отправить адресованное ему письмо с коммерческим предложением (КП) и т.д. в котором нужно обратиться по имени. Поля «Сайт» и «Описание проблемы или задачи» позволят вам лучше подготовиться к обработки заявки, сделать более адресное КП.
Блок «Как с вами связаться» очень важен. Есть категория клиентов которая не любит звонки им гораздо удобнее провести первичный контакт с исполнителем через WhatsApp или электронную почту. Этот блок позволяет узнать предпочтение клиента и связаться с ним, наиболее удобным для него способом.
И конечно же «Согласие с политикой конфиденциальности». Согласно закону 152-ФЗ «О персональных данных», вы как владелец веб-сайта обязаны запросить подобное согласие от клиента если собираете его персональные данные (имя, телефон и т.п.). Кстати быстро сгенерировать страницу для сайта с описание политики конфиденциальности поможет этот сервис.
С внешним видом определились, давайте верстать!
<form action="<?=$templateFolder;?>/ajax.php" class="bg-white rounded pb_form_v1 ajax_form" method="POST">
<input type="hidden" name="FORM" value="MAIN_FEEDBACK">
<h2 class="mb-4 mt-0 text-center">Оставьте заявку.</h2>
<div class="sub_title">и получите аудит вашего сайта бесплатно</div>
<div class="form-group">
<input type="text" name="USER_NAME" class="form-control pb_height-50 reverse" placeholder="Ваше имя *" required="">
</div>
<div class="form-group">
<input type="text" name="USER_EMAIL" class="form-control pb_height-50 reverse" placeholder="Email *" required="">
</div>
<div class="form-group">
<input type="text" name="USER_PHONE" class="form-control pb_height-50 reverse" placeholder="Телефон *" required="">
</div>
<div class="form-group">
<input type="text" name="USER_WEBSITE" class="form-control pb_height-50 reverse" placeholder="Сайт, если он уже есть">
</div>
<div class="form-group">
<textarea name="USER_MESSAGE" class="form-control pb_height-110 reverse" placeholder="Пару слов о ваших проблемах и задачах..."></textarea>
</div>
<div class="form-group">
<label>Как нам с вами связаться?</label>
<div class="radio_block">
<div class="custom-control custom-radio">
<input type="radio" class="custom-control-input" id="phoneCall" name="CONNECT_TYPE" value="Позвонить по телефону" checked="">
<label class="custom-control-label" for="phoneCall">Позвонить по телефону</label>
</div>
<div class="custom-control custom-radio">
<input type="radio" class="custom-control-input" id="whatsapp" name="CONNECT_TYPE" value="Написать в WhatsApp">
<label class="custom-control-label" for="whatsapp">Написать в WhatsApp</label>
</div>
<div class="custom-control custom-radio">
<input type="radio" class="custom-control-input" id="sendEmail" name="CONNECT_TYPE" value="Написать на почту">
<label class="custom-control-label" for="sendEmail">Написать на почту</label>
</div>
</div>
</div>
<div class="form-group politika custom-control custom-radio">
<input type="checkbox" id="policy_full" name="policy" value="y" class="form-control reverse custom-control-input" required="required">
<label class="custom-control-label" for="policy_full">Согласен с <a href="#" target="_blank">политикой конфиденциальности</a></label>
</div>
<div class="form-group">
<input type="submit" class="btn btn-primary btn-lg btn-block pb_btn-pill btn-shadow-blue" value="Написать">
</div>
</form>
Для валидации используем стандартный HTML5, однако при желании можно подключить jQuery Validate или аналогичный плагин.
Большая часть стилей, это стандартный Bootstrap 4, однако для некоторых элементов формы стиля я всё же приведу (это scss):
.pb_form_v1 {
padding: 50px;
@include pb_box-shadow(1px, 11px, 68px, -20px, rgba($black,.75));
@include media-breakpoint-down(md) {
padding: 30px;
}
}
// inputs
input, select, textarea {
font-weight: 300;
color: rgba($black, .7);
}
.pb_select-wrap {
position: relative;
&:before {
@include Ionicons;
content: "\f3d0";
position: absolute;
right: 20px;
top: 50%;
transform: translateY(-50%);
font-size: 26px;
}
select {
appearance: none;
}
}
// select {
.form-control {
&.reverse {
background: lighten($black, 95%);
transition: .3s all ease;
border-color: lighten($black, 95%);
&:focus, &:active {
background: none;
border-color: theme-color('primary')!important;
}
}
}
.form-control-outline {
background: none;
&:focus, &:active {
background: none;
}
&.light {
color: $white;
border-color: rgba($white, .4);
&:focus, &:active {
border-color: rgba($white, 1);
}
&::placeholder {
color: rgba($white, .5);
}
}
&.dark {
color: $body-color;
}
}
// buttons
.btn {
&:focus, &:active {
box-shadow: none!important;
outline: none!important;
}
}
.btn-shadow-blue {
@include pb_box-shadow(0px, 15px, 28px, -5px, rgba($blue,.45));
}
.pb_btn-pill {
border-radius: 50px;
padding-left: 40px;
padding-right: 40px;
}
.pb_outline-light {
border: 1px solid rgba(255,255,255,.2);
text-transform: uppercase;
background: none;
color: #ffffff;
&:hover, &:active, &:focus {
outline: none;
background: $white!important;
border: 1px solid #ffffff;
color: $black;
}
}
.pb_outline-dark {
border: 1px solid rgba(0,0,0,.2);
text-transform: uppercase;
color: #000000;
background: none;
&:hover, &:active, &:focus {
outline: none;
background: $black!important;
border: 1px solid #000000;
color: $white;
}
}
И стили для чекбоксов блока «Как нам с вами связаться?»:
.custom-control {
position: relative;
display: -webkit-inline-box;
display: -webkit-inline-flex;
display: -ms-inline-flexbox;
display: inline-flex;
min-height: 1.8rem;
padding-left: 1.5rem;
margin-right: 1rem; }
.custom-control-input {
position: absolute;
z-index: -1;
opacity: 0; }
.custom-control-input:checked ~ .custom-control-indicator {
color: #fff;
background-color: #007bff;
}
.custom-control-input:focus ~ .custom-control-indicator {
-webkit-box-shadow: 0 0 0 1px #fff, 0 0 0 3px #007bff;
box-shadow: 0 0 0 1px #fff, 0 0 0 3px #007bff;
}
.custom-control-input:active ~ .custom-control-indicator {
color: #fff;
background-color: #b3d7ff;
}
.custom-control-input:disabled ~ .custom-control-indicator {
background-color: #e9ecef;
}
.custom-control-input:disabled ~ .custom-control-description {
color: #868e96;
}
.custom-control-indicator {
position: absolute;
top: 0.4rem;
left: 0;
display: block;
width: 1rem;
height: 1rem;
pointer-events: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-color: #ddd;
background-repeat: no-repeat;
background-position: center center;
background-size: 50% 50%; }
.custom-checkbox .custom-control-indicator {
border-radius: 0.25rem; }
.custom-checkbox .custom-control-input:checked ~ .custom-control-indicator {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E");
}
.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-indicator {
background-color: #007bff;
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E");
}
.custom-radio .custom-control-indicator {
border-radius: 50%;
}
.custom-radio .custom-control-input:checked ~ .custom-control-indicator {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E");
}
.captcha-wrapper {
padding-left: 15px;
}
Давайте так же подключим плагин для всплывающих окон, чтобы показывать пользователю результат. Я предпочитаю magnificPopup , подключите плагин, стили и jQuery (если ещё не сделали этого):
<!-- Magnific Popup core CSS file -->
<link rel="stylesheet" href="magnific-popup/magnific-popup.css">
<!-- jQuery 1.7.2+ or Zepto.js 1.0+ -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<!-- Magnific Popup core JS file -->
<script src="magnific-popup/jquery.magnific-popup.js"></script>
И создайте внизу страницы (после формы) блок для показа всплывающего окна:
<div class="white-popup mfp-hide" id="js_contact_form_popup"></div>
Мы будем подставлять в него ответ сервера и показывать пользователю popup.
Форма готова!
Подключаем проверку Google
Перейдите на страницу Google reCaptcha (у вас должен быть аккаунт на Google), нажмите кнопку «Создать» и введите следующие настройки:
Указываем тип капчи «Я не робот»:
После сохранения настроек, вы получите пару ключей, а именно «Ключ сайта» и «Секретный ключ»:
Их лучше сразу сохранить в константах сайта. Обычно это файл init.php или отдельный файл constants.php подключаемый в начале init.php.
<?
//Ключ сайта Google капчи
define('GOOGLE_CAPTCHA_SITE_KEY', '---тут ваш ключ---');
//Секретный ключ Google капчи
define('GOOGLE_CAPTCHA_SECRET_KEY', '---тут ваш секретный ключ---');
Добавим блок капчи в вёрстку формы, вот так (можно вставить его перед согласием с политикой конфиденциальности):
<div class="row form-group">
<div class="captcha-wrapper">
<div class="g-recaptcha" data-sitekey="<?=GOOGLE_CAPTCHA_SITE_KEY;?>"></div>
</div>
</div>
Так же необходимо подключить js скрипта api Goolge reCaptcha, делается это в файле header.php шаблона сайта:
<?
//Подключаем Google reCaptcha API
Asset::getInstance()->addString('<script src="https://www.google.com/recaptcha/api.js"></script> ');
Проверка ввода капчи
Для верификации ввода капчи нам потребуется дополнительный php класс ReCaptcha, его можно найти на GitHub. Скачиваем и подключаем его в наш компонент. Т.к. для обработки формы я собираюсь использовать ajax.php подключим этот класс туда (ajax.php это доп.файл в лежащий в папке с шаблоном компонента и отвечающий за серверную обработку запроса с формы).
<?
//Подключаем ядро 1С Битрикс
require($_SERVER["DOCUMENT_ROOT"] . '/bitrix/modules/main/include/prolog_before.php');
//Подключаем класс Google для проверки ввода капчи
require($_SERVER['DOCUMENT_ROOT'] . '/local/php_interface/recaptchalib.php');
if($_POST['FORM'] == 'MAIN_FEEDBACK_QUICK'){
//ответ
$response = false;
//проверка секретного ключа
$reCaptcha = new ReCaptcha(GOOGLE_CAPTCHA_SECRET_KEY);
if ($_POST["g-recaptcha-response"]) {
$response = $reCaptcha->verifyResponse(
$_SERVER["REMOTE_ADDR"],
$_POST["g-recaptcha-response"]
);
}
//Проверяем ответ Google
if ($response->success) {
//Отправляем форму, записываем данные в инфоблок ...
echo json_encode(['success'=>'y', 'message'=>'Заявка успешно отправлена! Мы скоро свяжемся с вами.']);
} else {
echo json_encode(['success'=>'n', 'message'=>'Вы не прошли проверку Google reCaptcha']);
}
}
Как видите здесь мы создаём экземпляр класса ReCaptcha() подставляя ранее полученный «секретный ключ», Google по средствам своего API сам проверит валидность капчи и вернёт соответствующий ответ в переменную $response. Проверка $response->success сообщает нам об успешной проверки пользователя или же о провале.
Давайте добавим JavaScript обработчик нашей форме, чтобы удостовериться что всё работает:
//Отправка формы
$('.ajax_form').submit(function(event) {
event.preventDefault();
var form = $(this);
$.ajax({
url: form.attr('action'),
method: 'POST',
data: form.serialize(),
beforeSend: function () { /* здесь можно задать визуальный эффект отправки формы*/},
success: function (data) {
var formResponse = $.parseJSON(data);
if(formResponse.success == 'y'){
$('#js_contact_form_popup').html('<span>Спасибо!</span><br/> Ваша заявка успешно отправлена.<br/> Мы скоро свяжемся с вами для уточнения деталей.');
form[0].reset();
} else {
$('#js_contact_form_popup').html('<span>Ошибка!</span><br/>' + formResponse.message);
}
//Показываем всплывающее окно с сообщением от сервера
$.magnificPopup.open({
items: {
src: $('#js_contact_form_popup'),
type: 'inline',
mainClass: 'mfp-fade',
removalDelay: 300,
}
});
}
});
});
Подробнее о том как работать с jQuery Ajax можно прочитать в этой статье. Проверим работу капчи:
Шаблон письма
Шаблон письма до безобразия прост, в нём мы отразим только самую необходимую информацию:
<h2>Новая заявка</h2>
<ul>
<li><b>Имя: </b>#USER_NAME#</li>
<li><b>Телефон: </b>#USER_PHONE#</li>
<li><b>Email: </b>#USER_EMAIL#</li>
<li><b>Сайт: </b>#USER_WEBSITE#</li>
<li><b><span style="color: #ee1d24;">Способ связи: </span></b>#CONNECT_TYPE# <i>(предпочтительный способ связи с клиентом)</i></li>
</ul>
<br>
<b>Текст сообщения:</b> #USER_MESSAGE#<br>
<br>
Сообщение сгенерировано автоматически, на него <b>не нужно</b> отвечать.<br>
Осталось дополнить наш ajax.php чтобы в случае успешной проверки капчи он отправлял данные на почту:
<?
//Подключаем ядро 1С Битрикс
require($_SERVER["DOCUMENT_ROOT"] . '/bitrix/modules/main/include/prolog_before.php');
//Подключаем класс Google для проверки ввода капчи
require($_SERVER['DOCUMENT_ROOT'] . '/local/php_interface/recaptchalib.php');
if($_POST['FORM'] == 'MAIN_FEEDBACK_QUICK'){
//ответ
$response = false;
//проверка секретного ключа
$reCaptcha = new ReCaptcha(GOOGLE_CAPTCHA_SECRET_KEY);
if ($_POST["g-recaptcha-response"]) {
$response = $reCaptcha->verifyResponse(
$_SERVER["REMOTE_ADDR"],
$_POST["g-recaptcha-response"]
);
}
//Проверяем ответ Google
if ($response->success) {
//Отправляем форму
$arrFields = [
'USER_NAME' => strip_tags($_POST['USER_NAME']),
'USER_EMAIL' => strip_tags($_POST['USER_EMAIL']),
'USER_PHONE' => strip_tags($_POST['USER_PHONE']),
'USER_MESSAGE' => strip_tags($_POST['USER_MESSAGE']),
'USER_WEBSITE' => strip_tags($_POST['USER_WEBSITE']),
'CONNECT_TYPE' => strip_tags($_POST['CONNECT_TYPE']),
];
if(CEvent::Send('CUSTOM_FORM', SITE_ID, $arrFields, 'N', 10)){
echo json_encode(['success'=>'y', 'message'=>'Заявка успешно отправлена! Мы скоро свяжемся с вами.']);
}
} else {
echo json_encode(['success'=>'n', 'message'=>'Вы не прошли проверку Google reCaptcha']);
}
}
Метод CEvent::Send() отвечает за отправку письма, число 10 в параметрах метода — это идентификатор почтового шаблона который мы подготовили ранее, у вам он может отличаться. Если вы всё сделали правильно, в результате вам на почту будет приходить такое вот письмо:Как видите для менеджера выделен предпочтительный способ связи с клиентом, это одна из фишек БМ, вы будете связываться с потенциальным покупателем максимально комфортным для него способом, что повысит его лояльность и возможно конверсию.
Заключение
На первый взгляд внедрение такого функционала может показаться сложным, но если всё разложить на последовательные логические шаги и использовать пару спец.инструментов задача становится значительно проще! Если у вас остались вопросы — пишите их в комментариях. Желаю удачи!
Здравствуйте, а как в битриксе правильно подключить scss? И с всплывающим окном не до конца понятно.
Scss/sass напрямую не подключается, используйте gulp или webpack для сборки scss и конвертации в css. Что конкретно не получается со всплывающим окном?
Попробовал, но при конвертации получаю ошибку Error: Undefined mixin. Скорее всего пока не разобрался как правильно, но а почему бы не выложить уже сконвертированный код в css если битрикс не поддерживает scss, статья же для битрикса написана?
Логично. Добавлю )