В этой статье мы пошагово создадим виджет обратного звонка с красивой минималистичной анимацией и отправкой уведомлений на почту, на свой номер телефона и в мессенджер Telegram через бота. Виджет подойдет абсолютно для любого сайта на HTML или на любой CMS.
Демонстрацию можно посмотреть по ссылке.
Зачем нужен callback-виджет?
Есть масса сервисов, которые предоставляют различные настраиваемые виджеты обратного звонка — с возможностью подключить АТС, интегрировать с CRM (amoCRM, Битрикс24), с оповещением в Telegram, по СМС и так далее. За такой богатый функционал нужно платить ежемесячно, покупать минуты или выбирать тариф по карману. Стоимость подобных виджетов стартует примерно от 200 рублей в месяц.
Используя виджет, о котором мы поговорим в этой статье, вы получите навечно бесплатное, независимое и настраиваемое под любые нужды решение — с возможностью отправки заявки на почту, в Telegram и по СМС. Также с помощью вебхуков можно подключить отправку данных в CRM (если есть такая возможность на стороне самой CRM).
Минус такого виджета – отсутствие возможности онлайн-звонка. Но, думаю, это не большой минус, а скорее плюс, так как часто менеджеры не успевают ответить на звонок, и компания получает негатив от потенциального клиента. А в случае с виджетом мы принимаем заявку, выводим сообщение о том, что перезвоним в течение определенного времени, и у клиента не возникает негатива. Поэтому минус виджета может быть и плюсом.
Итак, приступим к созданию виджета.
Разметка HTML + CSS
<div class="widget-callback"> <div class="callback-button"> <span class="callback-button-title">Вам перезвонить?</span> <span class="callback-button-phone"></span> </div> <div class="callback-form"> <form id="calbback-widget-form"> <span class="callback-form-title">Оставьте свой телефон и мы свяжемся с вами</span> <input type="tel" name="wgphone" placeholder="+7 (999) 999 99 99" required > <input type="hidden" name="wgdata" value="Обратный звонок"> <input type="hidden" name="wgpage" value="<?php echo "https://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; ?>"> <input type="submit"> </form> </div> </div>
Так как виджет «сквозной» и устанавливается на все страницы, нам необходимо понимать, с какой страницы был заказан обратный звонок, чтобы оперативно помочь клиенту. Для этого нам понадобится скрытое поле в форме, которое будет передавать эту страницу, значение поле должно быть таким:
<?php echo "https://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; ?>
Если у вас одностраничный сайт или несколько страниц на HTML, измените расширение файла с .html на .php. Если устанавливаете на CMS , то все в порядке.
Второе скрытое поле будет передавать тему заявки — в данном случае это «Обратный звонок».
Теперь добавим небольшой скрипт открытия формы по клику на кнопку. Для этого нам понадобится подключить библиотеку jQuery и написать небольшой скрипт отправки. Если у вас уже подключена библиотека, то этого делать не стоит.
<script> $(document).ready(function () { //Открытие виджета по клику jQuery('body').on('click', '.callback-button-phone', function (e) { e.preventDefault(); jQuery('.widget-callback').toggleClass('widget-callback-form-open'); }); }); </script>
Далее оформим все с помощью CSS. Вы можете добавить этот код в свой файл стилей или создать новый.
body { margin: 0; padding: 0; } .widget-callback { font-family: sans-serif; font-size: 14px; } .widget-callback>div { -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } .widget-callback input { outline: none !important } .widget-callback .callback-button { position: absolute; right: 60px; bottom: 30px; } .widget-callback .callback-button-title { position: absolute; left: -150px; top: 16px; background: rgba(41, 41, 41, 0.75); color: #fff; padding: 6px 10px; border-radius: 3px; } .widget-callback.widget-callback-form-open .callback-button-title { display: none; } .widget-callback .callback-button-title:before { content: ''; position: absolute; width: 0; height: 0; border: solid transparent; border-width: 6px; top: 50%; right: -12px; transform: translateY(-50%); border-left-color: rgba(41, 41, 41, 0.75); } .widget-callback .callback-button-phone { width: 60px; height: 60px; display: block; background: #199c68; border-radius: 50%; position: relative; cursor: pointer; animation: 1200ms ease 0s normal none 1 running shake; animation-iteration-count: infinite; -webkit-animation: 1200ms ease 0s normal none 1 running shake; -webkit-animation-iteration-count: infinite; } .widget-callback.widget-callback-form-open .callback-button-phone { animation: unset; -webkit-animation: unset; background: #ddd; } .widget-callback .callback-button-phone:before { content: ''; background: url(call.svg); background-size: contain; position: absolute; display: block; width: 24px; height: 24px; left: 50%; top: 50%; margin: -12px 0 0 -12px; transform: scale(1); -webkit-transition: all 0.2s linear; transition: all 0.2s linear; } .widget-callback .callback-button-phone:after { content: ''; background: url(cancel.svg); background-size: contain; position: absolute; display: block; width: 24px; height: 24px; left: 50%; top: 50%; margin: -12px 0 0 -12px; transform: scale(0); -webkit-transition: all 0.2s linear; transition: all 0.2s linear; } .widget-callback.widget-callback-form-open .callback-button-phone:before { content: ''; transform: scale(0); } .widget-callback.widget-callback-form-open .callback-button-phone:after { content: ''; transform: scale(1); } .widget-callback .callback-form { display: none; background: #fff; border: 1px solid #f9f9f9; width: 240px; border-radius: 5px; padding: 30px 15px; right: 60px; bottom: 110px; position: absolute; box-shadow: 0px 5px 20px rgba(0, 0, 0, 0.08); } .widget-callback.widget-callback-form-open .callback-form { display: block; animation: formcbwg-in 0.1s ease; } @keyframes formcbwg-in { 0% { transform: translateY(15%); } 100% { transform: translateY(0%); } } @keyframes formcbwg-out { 0% { transform: translateY(0%); } 100% { transform: translateY(15%); } } .widget-callback .callback-form-title { text-align: center; display: block; margin: 0 0 30px; } .widget-callback input { width: 100%; box-sizing: border-box; padding: 15px; margin: 0 0 10px; border: 1px solid #ebebeb; border-radius: 3px; font-size: 16px; } .widget-callback input[type="submit"] { background: #199c68; color: #fff; text-transform: uppercase; font-size: 14px; border: none; cursor: pointer; } .widget-callback .success-send { text-align: center; } .widget-callback .success-send img { width: 60px; margin: 0 0 20px; } @media (max-width: 600px) { .widget-callback .callback-button { right: 30px; bottom: 30px; } .widget-callback .callback-form { width: 80%; right: 10%; box-sizing: border-box; } } @keyframes shake { 0% { transform: rotateZ(0deg); -ms-transform: rotateZ(0deg); -webkit-transform: rotateZ(0deg); } 10% { transform: rotateZ(-30deg); -ms-transform: rotateZ(-30deg); -webkit-transform: rotateZ(-30deg); } 20% { transform: rotateZ(15deg); -ms-transform: rotateZ(15deg); -webkit-transform: rotateZ(15deg); } 30% { transform: rotateZ(-10deg); -ms-transform: rotateZ(-10deg); -webkit-transform: rotateZ(-10deg); } 40% { transform: rotateZ(7.5deg); -ms-transform: rotateZ(7.5deg); -webkit-transform: rotateZ(7.5deg); } 50% { transform: rotateZ(-6deg); -ms-transform: rotateZ(-6deg); -webkit-transform: rotateZ(-6deg); } 60% { transform: rotateZ(5deg); -ms-transform: rotateZ(5deg); -webkit-transform: rotateZ(5deg); } 70% { transform: rotateZ(-4.28571deg); -ms-transform: rotateZ(-4.28571deg); -webkit-transform: rotateZ(-4.28571deg); } 80% { transform: rotateZ(3.75deg); -ms-transform: rotateZ(3.75deg); -webkit-transform: rotateZ(3.75deg); } 90% { transform: rotateZ(-3.33333deg); -ms-transform: rotateZ(-3.33333deg); -webkit-transform: rotateZ(-3.33333deg); } 100% { transform: rotateZ(0deg); -ms-transform: rotateZ(0deg); -webkit-transform: rotateZ(0deg); } } @-webkit-keyframes shake { 0% { transform: rotateZ(0deg); -ms-transform: rotateZ(0deg); -webkit-transform: rotateZ(0deg); } 10% { transform: rotateZ(-30deg); -ms-transform: rotateZ(-30deg); -webkit-transform: rotateZ(-30deg); } 20% { transform: rotateZ(15deg); -ms-transform: rotateZ(15deg); -webkit-transform: rotateZ(15deg); } 30% { transform: rotateZ(-10deg); -ms-transform: rotateZ(-10deg); -webkit-transform: rotateZ(-10deg); } 40% { transform: rotateZ(7.5deg); -ms-transform: rotateZ(7.5deg); -webkit-transform: rotateZ(7.5deg); } 50% { transform: rotateZ(-6deg); -ms-transform: rotateZ(-6deg); -webkit-transform: rotateZ(-6deg); } 60% { transform: rotateZ(5deg); -ms-transform: rotateZ(5deg); -webkit-transform: rotateZ(5deg); } 70% { transform: rotateZ(-4.28571deg); -ms-transform: rotateZ(-4.28571deg); -webkit-transform: rotateZ(-4.28571deg); } 80% { transform: rotateZ(3.75deg); -ms-transform: rotateZ(3.75deg); -webkit-transform: rotateZ(3.75deg); } 90% { transform: rotateZ(-3.33333deg); -ms-transform: rotateZ(-3.33333deg); -webkit-transform: rotateZ(-3.33333deg); } 100% { transform: rotateZ(0deg); -ms-transform: rotateZ(0deg); -webkit-transform: rotateZ(0deg); } }
Информирование по email
Разметка готова, теперь нужно настроить отправку уведомлений на почту, для этого подключим файл mail.php со следующим содержимым:
<?php if ($_SERVER["REQUEST_METHOD"] == "POST") { if (isset($_POST['wgphone'])) {$wgphone = $_POST['wgphone'];} if (isset($_POST['wgdata'])) {$wgdata = $_POST['wgdata'];} if (isset($_POST['wgpage'])) {$wgpage = $_POST['wgpage'];} $to = "up-lite@ya.ru"; /*Укажите адрес, на который должно приходить письмо*/ $headers = 'MIME-Version: 1.0' . "rn"; $headers .= "Content-type: text/html; charset=utf-8 rn"; // дополнительные данные $headers .= "From: Студия Аплайт <info@up-lite.ru>;rn"; // от кого $subject = "$wgdata"; $message = " <div style='background: #f8f8f8;padding: 20px; font-family:sans-serif;'> <div style='width: 400px;margin: 0 auto;'> <div style=' background: #1b3c56;border-radius: 10px 10px 0 0;padding: 30px 0;text-align: center;color: #fff;font-weight: 700;font-size: 20px;'>Заявка на обратный звонок </div> <div style='padding: 30px;border-radius: 0 0 10px 10px;background: #fff;'> <b>Телефон:</b> <a href='tel:".$wgphone."'>".$wgphone." </a><br> <b>Страница:</b> ".$wgdata." </div> </div> </div> "; $send = mail ($to, $subject, $message, $headers); if ($send == 'true') { echo ' <div class="success-send"> <img src="tick.svg"> <br> Мы получили Вашу заявку и скоро с Вами свяжемся! </div>'; } else { echo 'Нам не удалось отправить заявку, попробуйте еще раз'; } } else { http_response_code(403); echo "Попробуйте еще раз"; } ?>
Вам остается только заменить email на свой, и форма будет работать. Как видите, в теле письма мы сформировали HTML-разметку, поэтому письма будут приходить в красиво оформленном формате:
Это удобно для администратора — сразу настроенная ссылка на телефон дает возможность не копировать номер, а сразу при клике перейти в телефонную книгу.
AJAX-отправка данных формы
Теперь добавить AJAX-отправку данных формы. Это позволит отправлять номер телефона без перезагрузки, что очень удобно для посетителя.
Скрипт отправки формы:
<script> $(document).ready(function () { //ajax-отправка данных jQuery("#calbback-widget-form").submit(function () { var formID = jQuery(this).attr('id'); var formNm = jQuery('#' + formID); jQuery.ajax({ type: "POST", url: 'mail.php', data: formNm.serialize(), success: function (data) { jQuery(formNm).html(data); }, error: function (jqXHR, text, error) { jQuery(formNm).html(error); } }); return false; }); }); </script>
Скрипты можно объединить в один и подключить файлом – как удобно на вашем проекте.
Отправка СМС
Для отправки сообщений на свой номер или на номер клиента будем использовать сервис sms.ru. Регистрируемся и обращаем внимание на следующее:
1. API-ключ — на каждой странице он расположен в самом низу, копируем его.
2. Файл подключения к API sms.ru — переходим по ссылке (найти ее можно в разделе «Интеграции» -> «PHP» в первой табличке).
Файл sms.ru.php небходимо поместить в корневую папку с mail.php, а затем настроить подключение и отправку в самом файле mail.php. Выглядит это следующим образом:
//ОТПРАВКА СМС require_once 'sms.ru.php'; $smsru = new SMSRU('Ваш api_id'); // Ваш уникальный программный ключ, который можно получить на главной странице $data = new stdClass(); $data->to = 'Ваш номер или номер админа ; $data->text = ''.$wgdata.' '.$wgphone.''; // Текст сообщения $sms = $smsru->send_one($data); // Отправка сообщения и возврат данных в переменную
Преимущество этого сервиса в том, что можно отправлять до 5 СМС в день на свой номер бесплатно.
Проверяем отправку данных формы и видим, что теперь приходит и оповещение на номер телефона. Данные, которые приходят в сообщении, можно менять, но чем больше текста, тем дороже СМС.
Отправка данных в чат Telegram
Для отправки данных в мессенджер нам понадобится следующее:
- Создать бота.
- Создать чат, в который бот будет отправлять данные.
- Активировать бота.
- Проверить правильность настройки.
Создаем телеграм-бота.
В строке поиска ищем BotFather и даем ему команду /start, затем выбираем команду /newbot, следуем подсказкам и выбираем имя бота и как его будем вызывать. Выбранное имя может быть занято, вам сообщит об этом подсказка, поэтому придумайте уникальное имя — чтоб наверняка 🙂
После отправки имени BotFather отправит нам сообщение о том, что все готово, и пришлет специальный ключ — токен (см. скриншот), он понадобится для получения ID чата, в который будем отправлять данные заявки.
Отлично, бот готов. Создаем чат и добавляем в него бота.
- Слева в меню Телеграма выбираем «Создать группу».
- Пишем название группы, например «Заявки с сайта [название сайта]».
- Добавляем бота в созданную группу через поиск.
Затем нужно активировать бота командой /join @uplite_bot. Пишем ее в созданной группе, далее кликаем по имени бота @uplite_bot, и нас перебрасывает на диалог с нашим ботом, где его нужно активировать командой /start.
Теперь необходимо получить ID чата, делается это следующим запросом:
https://api.telegram.org/botXXXXXXXXXXXXXXXXXXXXXXX/getUpdates
Где XXXXXXXXXXXXXXXXXXXXXXX — токен вашего бота, полученный ранее.
Вставляем свой токен и переходим по ссылке, затем снова заходим в чат с нашим ботом и повторно активируем его командой /start, обновляем ссылку и ищем ID чата, он будет выглядеть следующим образом:
Ищем в тексте ID с черточкой — это и есть наш ID чата.
Итак, у нас теперь есть все данные для отправки заявки в чат Телеграма, осталось только настроить в mail.php.
//ОТПРАВКА В ТЕЛЕГРАМ $token = "ваш_токен"; $chat_id = "id_чата"; $arr = array( 'Телефон: ' => $wgphone, 'Страница' => $wgpage, 'Тема' => $wgdata ); foreach($arr as $key => $value) { $txt .= "<b>".$key."</b> ".$value."%0A"; }; $sendToTelegram = fopen("https://api.telegram.org/bot{$token}/sendMessage?chat_id={$chat_id}&parse_mode=html&text={$txt}","r");
Проверяем – все должно работать 🙂 Теперь у нас есть виджет с различными вариантами отправки заявок, который удовлетворит пожелания большинства заказчиков.