5 способов отслеживания заявок через Google Tag Manager

Отслеживание заявок - одна из тех задач, благодаря которым веб-аналитика вообще существует. Иначе ведь и не понять, что реклама работает. А как известно, без Adwords не было бы Analytics.

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

Встроенный триггер

Do you feel lucky, punk?
Clint Eastwood, Dirty Harry

Первое, что стоит попробовать - встроенный способ отслеживания. По моему опыту он срабатывает довольно редко, но тем не менее.

Этот триггер прослушивает submit форм и при наступлении оных передает в dataLayer событие gtm.formSubmit. По выполнении сабмита можно, например, отправить событие в Google Analytics.
Разберем доступные настройки триггера:

  • Ждать теги - параметр будет полезен, если читатель возжелает к отправке формы подвязать уведомления CPA-сетей или что еще похуже, но переусердствовать с ним конечно не стоит.

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

    Отсутствие перезагрузки означает, что выполнена функция preventDefault(), отменяющая действие по умолчанию.

  • Условия активации нужны, чтобы читатель указал, какая именно форма его интересует.

На этой странице стоит отдельный контейнер Google Tag Manager с реализацией всех описанных методов, так что, если отправить тестовую форму ниже, то в заранее открытой вкладке Network читатель увидит ушедший запрос к collect.

Встроенный триггер

ТЗ для разработчиков

Когда встроенный триггер не сработал, и нет желания копаться в коде, на помощь приходит простой для веб-аналитика, но зачастую сложный с административной точки зрения способ.

“Пусть этот криворукий рукожоп сам ковыряется” - думает читатель и направляет разработчику ТЗ с требованием при отправке формы выполнять примерно следующий javascript код:

 1 2 3 4 5 6 7 8 910111213
dataLayer.push({
  'event': 'form__tz',
  'details': {
    // идентификатор формы
    'formID': formID,
    // оставленный контакт
    'contact': contact
  },
  'eventCallback' : function() {
    // обработчик формы
    onFormSubmit()
  }
})

В данном случае тег с отправкой в Google Analytics нужно привязать на пользовательское событие form__tz. Разбираем написанное:

  • details предлагает разработчику положить туда некоторую информацию о форме, которую можно достать через Переменную уровня данных второй версии. Для идентификатора - details.formID, а вот контакты по законам Google нельзя передавать в Analytics, но можно в Spreadsheets или в Telegram

  • eventCallback аналогичен свойству Ждать теги. Он нужен, чтобы поместить туда обработчик формы, который отправит заявку в 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 с кодом ниже, в триггере просмотр страницы с формой.

 1 2 3 4 5 6 7 8 9101112131415161718192021222324
<script>
  (function(send) {
    XMLHttpRequest.prototype.send = function(data) {
      // Вывод целевого URL запроса. Не забудьте убрать после отладки
      // console.log(this.responseURL)
      this.addEventListener("readystatechange", function() {
        if(this.readyState === 4 && this.status == 200) {
          // проверяем URL обработчика
          if(~this.responseURL.indexOf("/blog/priemy-raboty-v-bigquery/")){
            dataLayer.push({
              'event': 'form__ajax',
              'details': {
                // оставленный контакт. Предполагается отправка FormData
                'contact': data.getAll('contact')
              }
            })
          }
        }
        return true
      });
      send.apply(this, arguments)
    }
  })(XMLHttpRequest.prototype.send);
</script>

Узнать, куда уходит запрос с нужной формы, можно с помощью console.log(this.responseURL), и этот url потом зафильтровать. В примере я отправляю данные формы с помощью FormData().

AJAX request

Подмена функции-обработчика

Если перехват запроса срабатывает постоянно, показывая один и тот же url, и в целом не помогает, то есть еще вариант с подменой обработчика этой формы. Найти его можно, посмотрев в консоли прослушку событий:

Или через Search all files по id\классу\имени. Форму в этом разделе обрабатывает функция process(). Делаем тег типа Пользовательский HTML с кодом ниже, в триггере Модель DOM готова на страницы страницы с формой.

 1 2 3 4 5 6 7 8 9101112131415161718
<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, куда читатель никак не попадет. Тем не менее проверяем:

Rewrite function

Ссылки

Гайд Семёна по формам для трекинга полей

comments powered by Disqus