Форма обратной связи — один из самых част встречающихся элементов на сайте и сейчас я хочу рассказать о том как сделать её на основе компонента, при этом не используя встроенный в битрикс модуля «Веб-формы» т.к. он доступен только начиная с лицензии «Стандарт», а подавляющее большинство сайтов не имеющих отношения к Интернет-торговле делаются на редакции «Старт». Так же мы учтём в форме один маленький лайфхак который я узнал на курсе Бизнес молодость ЦЕХ, который мне посчастливилось проходить летом 2019-го года. И так, поехали.

Подготовка компонента

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

Затем переходим в раздел: Настройки -> Настройки продукта -> Список мастеров, тут ищем «Мастер создания компонента» и в контекстном меню напротив, выбираем пункт «Установить»:

Запуск мастера создания компонента


Для нашего компонента я выбрал следующие базовые настройки:

  • Тип компонента — простой
  • Пространство имён — custom
  • Идентификатор — emptyscript
  • Название — Пустой скрипт
  • Описание — Заготовка под кастомный компонент
  • Категория в списке компонентов — Custom
Базовые настройки будущего компонента

Почему пустой скрипт? Т.к. функциональность формы крайне простая мы будем описывать бизнес логику формы в файлах component_epilog.php или доп.файлах ajax.php в папке шаблона компонента. А сам компонент emptyscript послушит каркасом для ряда простых форм.

Опции шаблона компонента следующие:

Опции шаблона



Мы будем использовать jQuery Ajax для обработки формы, а так же будем хранить стили компонента прямо в папке шаблона. В итоге настройки для мастера будут должны получиться примерно такими:

Итоговые настройки мастера

Нажимаем «Создать», ждём пару секунд, готово! Компонент успешно создан! Можете поблагодарить автора компонента донатом, он действительно экономит кучу времени. Давайте создадим какой-нибудь раздел на сайте и разместим нашу заготовку.

Перейдём к описанию самой формы.

Шаблон формы обратной связи

Допустим вы фрилансер, вебмастер, у вас есть свой landing-page и вы хотите подвесить туда форму обратной связи. Как будет выглядеть наш шаблон? Какую информацию будем собирать о клиенте? Предлагаю собрать следующее:

  1. Имя
  2. Email
  3. Контактный телефон
  4. Сайт (если есть)
  5. Описание проблемы или задачи которую хочет решить клиент
  6. Уточнение способа связи (та самая фишка от БМ)
  7. Согласие с политикой конфиденциальности

Основываясь на этом списке, делаем форму:

Шаблон формы


Первые три поля обязательны, т.к. нам нужна эта информация чтобы дозвониться до клиента и обсудить проект, а если не дозвонились то отправить адресованное ему письмо с коммерческим предложением (КП) и т.д. в котором нужно обратиться по имени. Поля «Сайт» и «Описание проблемы или задачи» позволят вам лучше подготовиться к обработки заявки, сделать более адресное КП.

Блок «Как с вами связаться» очень важен. Есть категория клиентов которая не любит звонки им гораздо удобнее провести первичный контакт с исполнителем через 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), нажмите кнопку «Создать» и введите следующие настройки:

Настройка Google reCaptcha

Указываем тип капчи «Я не робот»:

Тип капчи Я не робот

После сохранения настроек, вы получите пару ключей, а именно «Ключ сайта» и «Секретный ключ»:

Ключи Google reCaptcha


Их лучше сразу сохранить в константах сайта. Обычно это файл 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>Имя:&nbsp;</b>#USER_NAME#</li>
	<li><b>Телефон:&nbsp;</b>#USER_PHONE#</li>
	<li><b>Email:&nbsp;</b>#USER_EMAIL#</li>
	<li><b>Сайт:&nbsp;</b>#USER_WEBSITE#</li>
	<li><b><span style="color: #ee1d24;">Способ связи:&nbsp;</span></b>#CONNECT_TYPE# <i>(предпочтительный способ связи с клиентом)</i></li>
</ul>
 <br>
 <b>Текст сообщения:</b>&nbsp;#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 в параметрах метода — это идентификатор почтового шаблона который мы подготовили ранее, у вам он может отличаться. Если вы всё сделали правильно, в результате вам на почту будет приходить такое вот письмо:
Заявка с сайта

Как видите для менеджера выделен предпочтительный способ связи с клиентом, это одна из фишек БМ, вы будете связываться с потенциальным покупателем максимально комфортным для него способом, что повысит его лояльность и возможно конверсию.

Заключение

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

Полезная статья?
(Голосов: 5, Рейтинг: 3.15)
Вам также могут понравиться
Обновление остатков товара на складе в 1С Битрикс

Обновление остатков товара на складе в 1С Битрикс

Как правильно обновлять остатки товара на сайта под управлением CMS 1С Битрикс.

Английский для программистов

Английский для программистов

Почему IT-специалисту необходимо освоить английский язык? Разбираем в статье.

Как подключить CSS и JS файлы к шаблону 1С Битрикс

Как подключить CSS и JS файлы к шаблону 1С Битрикс

Как правильно подключать стили и скрипты к шаблону 1С Битрикс.


Комментарии
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке
25.11.2020 | Rum

Здравствуйте, а как в битриксе правильно подключить scss? И с всплывающим окном не до конца понятно.

Комментировать | 0  
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке
Закрыть
25.11.2020 | maler1988

Scss/sass напрямую не подключается, используйте gulp или webpack для сборки scss и конвертации в css. Что конкретно не получается со всплывающим окном?

Комментировать | 0  
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке
Закрыть
26.11.2020 | Rum

Попробовал, но при конвертации получаю ошибку Error: Undefined mixin. Скорее всего пока не разобрался как правильно, но а почему бы не выложить уже сконвертированный код в css если битрикс не поддерживает scss, статья же для битрикса написана?

Комментировать | 0  
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке
Закрыть
04.12.2020 | maler1988

Логично. Добавлю )

Комментировать | 0  
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке
Закрыть