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

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

Заключение

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

Вам также могут понравиться

Исключения в PHP, что это и как ими пользоваться

Исключения в PHP, что это и как ими пользоваться

В этой статье вы узнаете что такое исключения в PHP и как их использовать для обработки ошибок. Начиная с PHP версии 5.0 стала доступна новая модель обработки ошибок, так называемые исключения. Она позволяет более гибко и информативно для пользователя обрабатывать не стандартные ситуации в работе вашего приложения. 

Загрузка файлов на сервер средствами PHP

Загрузка файлов на сервер средствами PHP

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

Современные способы заработка на сайтах

Современные способы заработка на сайтах

Не для кого не секрет, что в современном мире вы можете зарабатывать определённые деньги на своём сайте ничего не продавая. Говоря «ничего не продавая», я имею ввиду классическую схему, когда вы продаёте свои услуги, перепродаёте товар (предварительно закупая или используя схемы прямой поставки «дроп-шиппинга») или что-то производите. В статье рассмотрим методы, которые не требуют от вас подобных действий. И так, рассмотрим основные методы в порядке возрастания их сложности и времени которое требуется от владельца сайта.


Комментарии
Защита от автоматических сообщений
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
Введите слово на картинке
Закрыть

Самые читаемые

Тонкая настройка SEO для результатов фильтрации каталога битрикс

Тонкая настройка SEO для результатов фильтрации каталога битрикс

Одним из преимуществ интернет-магазинов на 1С Битрикс на мой взгляд является наличие не так давно до...

Основы SEO оптимизации сайта

Основы SEO оптимизации сайта

Эта статья не истина в последней инстанции, а лишь набор правил которые я применяю при создании/испр...

Собственный тип пользовательских полей в 1С Битрикс

Собственный тип пользовательских полей в 1С Битрикс

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