Отслеживание заявок - одна из тех задач, благодаря которым веб-аналитика вообще существует. Иначе ведь и не понять, что реклама работает. А как известно, без Adwords не было бы Analytics.
Несмотря на всю важность точного отслеживания форм, универсального решения нет и быть не может, поэтому каждый раз приходится выдумывать или вспоминать, что еще можно сделать в конкретной ситуации, а это не всегда удается, а проджекту надо ASAP, а у тебя еще очередь да и на обед давно не ходил, с другой стороны интересно же, хотя делал кучу раз, клиент зато хороший, но сайт ужасный, а в контейнере вообще треш... короче я всё записал!
Так что палец на колесо, и покрутили от простого к менее простому.
Эксперимента ради я добавил в этот пост интерактивности: на странице стоит отдельный контейнер GTM, все формы обрабатываются описанными способами, результат видно, если нажать F12 в Chrome, далее вкладка Network и фильтр по слову collect.
Вот выгрузка контейнера, которую можно поставить к себе и подключить через Injector. Короче, всё к услугам читателя, развлекайся, дорогой гость!
Содержание
Встроенный триггер
Do you feel lucky, punk?
-- Clint Eastwood, Dirty Harry
Первое, что стоит попробовать - встроенный способ отслеживания. По моему опыту он срабатывает довольно редко, но тем не менее.
Этот триггер прослушивает Submit форм и при наступлении оных передает в dataLayer
событие gtm.formSubmit
. По выполнении сабмита можно, например, отправить событие в Google Analytics.
Разберем доступные настройки триггера:
Ждать теги - параметр будет полезен, если читатель возжелает к отправке формы подвязать уведомления CPA-сетей или что еще похуже, но переусердствовать с ним конечно не стоит.
Проверка ошибок воспрепятствует срабатыванию, если при отправке формы страница не перезагружается, что случается довольно часто, поэтому я оставил её выключенной. (Отсутствие перезагрузки означает, что выполнена функция
preventDefault()
, отменяющая действие по умолчанию)Условия активации нужны, чтобы читатель указал, какая именно форма его интересует.
На этой странице стоит отдельный контейнер Google Tag Manager с реализацией всех описанных методов, так что, если отправить тестовую форму ниже, то в заранее открытой вкладке Network читатель увидит ушедший запрос к collect.
Встроенный триггер
ТЗ для разработчиков
Когда встроенный триггер не сработал, и нет желания копаться в коде, на помощь приходит простой для веб-аналитика, но зачастую сложный с административной точки зрения способ.
"Пусть этот криворукий рукожоп сам ковыряется" - думает читатель и направляет разработчику ТЗ с требованием при отправке формы выполнять примерно следующий javascript код:
window.dataLayer = window.dataLayer || []
window.dataLayer.push({
event: 'form__tz',
details: {
formID: '{{идентификатор формы}}',
contact: '{{оставленный контакт}}',
},
eventCallback: function () {
// обработчик формы
onFormSubmit()
},
})
В данном случае тег с отправкой в Google Analytics нужно привязать на пользовательское событие form__tz
. Разбираем написанное:
details
предлагает разработчику положить туда некоторую информацию о форме, которую можно достать через Переменную уровня данных второй версии. Для идентификатора -details.formID
, а вот контакты по законам Google нельзя передавать в Analytics, но можно в Spreadsheets или в TelegrameventCallback
аналогичен свойству Ждать теги. Он нужен, чтобы поместить туда обработчик формы, который отправит заявку в CRM или на почту, но случится это только после всего остального, что завязано на отправленное событиеform__tz
. Использование не обязательно.
Проверяем:
dataLayer.push()
Сообщение об успехе
Еще один довольно простой способ - завязаться на сообщение об успешной отправке формы. Это может быть страница (устар. варианты - Success Page, Thank you page или вообще TYP), на которую пользователя перекидывают после успешной отправки, типа ../success.php или как в Битриксе ../?WEB_FORM_ID=123&RESULT_ID=.. В таком случае триггер завязывается на посещение этой страницы, или же она сразу указывается в цели в Google Analytics.
Минус в том, что пользователь может посетить эту страницу не только после отправления заявки, но и вернуться к ней во вкладке, добавить в избранное, воспользоваться подсказкой браузера, дать ссылку кому-то или вообще запостить её для всех. Очевидно, в этом случае читатель будет получать некорректные срабатывания.
Сообщение об успешной отправке, однако, может появляться и в виде модального окна без каких-либо перезагрузок. В этом случае поможет встроенный триггер типа Доступность элемента, который сработает при появлении сообщения, и отправит в dataLayer
событие gtm.elementVisibility
.
Триггер чудесный, решает множество задач, особенно в обремененных React'ом веб-приложениях, но пробежимся по нужным свойствам:
Метод выбора и Идентификатор элемента помогут указать на конкретный элемент, чьё появление нас интересует
Правило запуска этого триггера определяется задачей читателя. Если на странице несколько форм (стандартная + коллбэк), по которым всплывает одно и то же сообщение, то хорошо бы поставить как на картинке.
Регистрация изменений DOM поможет, если изначально элемента в структуре документа не было, и он встраивается в процессе. (React и прочие хипстерские технологии оперируют с виртуальным DOM и рендерят его по запросу, поэтому структура может легко меняться в процессе без особых усилий со стороны браузера)
Условия активации предлагают указать нужную страницу, и не нагружать клиентский ЭВМ ненужными операциями. В моем случае контейнер стоит только на одной странице, так что мне необязательно.
Success message
Прослушивание AJAX запроса
Случается, что вы сабмитите-сабмитите форму, а стандартный триггер не работает и в dataLayer
ничего не отправляется.
Вполне возможно, что разработчик прервал
всплытие события, добавив stopPropagation()
или return false
в обработчике submit
. Можно пожаловаться разрабу и попросить убрать, а можно вклиниться в процесс обработки заявки и перехватить её на следующем этапе путешествия - при отправке в CRM. Для этого придется переопределить метод send
, используемый для отправки запроса, но делать это нужно с большой осторожностью!
Создаем тег типа Пользовательский HTML с кодом ниже, в триггере просмотр страницы с формой.
<script>
(function(open) {
XMLHttpRequest.prototype.open = function(method, url) {
this.responseURL = url // полифилл из-за IE
this.addEventListener('load', function() {
if (~this.responseURL.indexOf('/priemy-raboty-v-bigquery/')) {
dataLayer.push({
event: 'form__ajax',
details: {
// ...
},
})
}
})
return open.apply(this, arguments)
}
})(XMLHttpRequest.prototype.open)
</script>
Узнать, куда уходит запрос с нужной формы, можно с помощью console.log(this.responseURL)
, и этот url потом зафильтровать. В примере я отправляю данные формы с помощью FormData()
.
AJAX request
Подмена функции-обработчика
Если перехват запроса срабатывает постоянно, показывая один и тот же url, и в целом не помогает, то есть еще вариант с подменой обработчика этой формы. Найти его можно, посмотрев в консоли прослушку событий:
Или через Search all files по id\классу\имени. Форму в этом разделе обрабатывает функция process()
.
Делаем тег типа Пользовательский HTML с кодом ниже, в триггере Модель DOM готова на страницы страницы с формой.
<script>
// сохранение старой функции
var _old_process = process
// определение новой
process = function (form) {
dataLayer.push({
event: 'form__rewrite',
details: {
contact: form.querySelector('input[placeholder=Контакт]').value,
formID: form.id,
},
})
// вызов старой с теми же параметрами
_old_process.apply(window, arguments)
}
</script>
В данном примере способ кажется обманчиво простым, на практике же форма может передаваться сперва в валидатор, оттуда еще в функцию, запрятанную внутрь jQuery, куда читатель никак не попадет. Тем не менее проверяем: