Custom HTML, события DL и переменные в GTM

Веб-аналитика Скрипты

Использование управляющего объекта для упрощённого взаимодействия с Data Layer менеджера тегов Гугла, сравнение с переменными GTM для решения тех же задач, пути оптимизации.


1. Управляющий объект

Вот такой рассмотрю. Представляет из себя контейнер методов для взаимодействия с объектом данных (Data Layer)… который вообще-то является массивом, но не суть.

Итак, в примерах видны возможности использования. Наверное, стоит подробнее коснуться настроек, то есть, дополнить там сям скринами.


1.1. П. 1

объект обработчика в теге Custom HTML

1.2. П. 2

При условии, что методы объекта-обработчика будут вызываться позже – чтобы на более ранней стадии был инициализирован управляющий объект, и стал доступен на любом событии позже «просмотра страницы»:

Триггер GTM все страницы

Почему не нравится Tag Sequencing – на таком примере. Допустим, управляющий объект нужен на событии DOM Ready, и там же есть тег, использующий управляющий объект, и который тоже нужен на DOM Ready. То есть, для обоих тегов выставлен триггер DOM Ready, и если не настроить очерёдность срабатывания тегов, тогда второй тег может не работать или работать через раз (тогда, когда объект-обработчик не успеет инициализироваться).

Чтобы этого избежать делается так:

Очерёдность тегов в Google Tag Manager

Вроде бы всё ок. Однако, если управляемый («ведомый») тег вызывается несколько раз на странице (кроме триггера DOM Ready есть и другие), то каждый раз он будет вызывать срабатывание тега управляющего («ведущего»), и это будет напрасно (выполнение одного и того же JS кода). Поэтому, лучше повесить ведущий тег на более раннее событие – «Просмотр страницы», а прочие теги, использующие объект-обработчик вешать на более поздние события.


1.3. П. 3

Переменная Global Javascript для управляющего объекта

Это чтобы была возможность использовать методы управляющего объекта красиво – с помощью переменной Google Tag Manager (двойные фигурные скобки).


1.4. П. 4

Необязательно, но очень полезно при настройке триггеров. Например, вместо трансляции тьмы событий, использовать несколько, с уточнениями в message. В данном случае, это message не стоит воспринимать буквально («сообщение»), оно лишь для передачи дополнительных данных, которые потом будут использоваться в триггерах, в значениях и т.д.

Пример нескольких событий:

Red Btn search
Red Btn found

Пример одного события с разными «сообщениями»:

Red Btn
     search
     found

По-красивше, по-моему.

Итак, переменная:

Переменная уровня данных для message

1.5. pushT

Основным методом является pushT – отправка события и сообщения с отложкой в секундах. Соответственно, для отправки данных без задержки, надо всего лишь указать 0 (ноль) в качестве первого параметра (см. примеры на Гитлабе).

Также, можно пропускать 3-й параметр (message) – отправлять только событие.


1.6. Кастомный таймер

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


(function() {
    var aTimes = [1, 60]; // здесь указываем отсечки в секундах через запятую
    for (var i = 0; i < aTimes.length; i++) {
		{{DL Processor}}.pushT(aTimes[i], "Timer Custom", aTimes[i]);
    }
})();

Отдельной переменной (как упоминалось в посте по ссылке) теперь не нужно – достаточно переменной DL Message (см. выше).

Что ещё очень полезно – создать триггер Window Loaded 1 сек:

Триггер задержки в 1 секунду от загрузки страницы

Так как основной тег кастомного таймера имеет триггером Window Loaded, то отсечка в 1 секунду будет означать задержку в 1 с от полной загрузки страницы. Это можно использовать для старта тегов (особенно, громоздких), которые нужны при загрузке страницы и для которых допустима погрешность во времени старта – так они не вклиниваются в процесс рендеринга страницы, что очень хорошо.


1.7. Опрос объекта данных

Иногда необходимо протранслировать событие раз на страницу и избежать повторных трансляций на данной странице. Есть опция в настройках тега "Once per page", но её иногда не хватает (не обеспечивает нужной гибкости). В таких случаях одним из решений может быть использование сессионного хранилища браузера, но с помощью объекта-обработчика эта задача решается проще.

Итак, была трансляция определённого события (с сообщением или без такового), например:


var dataLayer = window["dataLayer"] || [];
dataLayer.push({
	event: "Some Event",
	message: "some value as message"
});

После этого в массиве dataLayer это событие и сообщение содержатся в одном из элементов, и всё что теперь нужно – это проверить указанный массив (на эти событие и сообщение, либо только на событие) с помощью метода exists (см. примеры на Гитлабе).


2. Переменные Google Tag Manager

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


2.1. Причина корявости переменных

Заключается в том, что (все?) они пересчитываются на каждом событии (клики, кастомные события, просмотры страниц и т.д.). Чем больше событий (чем сложнее организована работа со страницей в GTM), тем больше процессорного времени жрут переменные.


2.2. Элемент DOM

Например, сделали переменную DOM, задав CSS селектор. Теперь, для каждого взаимодействия со страницей, которое идёт отдельным событием ГТМ, DOM опрашивается в поисках указанного элемента. Тогда как этот элемент нужен лишь на паре событий.

Но это ещё не всё. Если этот элемент сидит только на страницах определённого типа, то напрасно опрашиваться будут все страницы, т.к. нельзя отключить обработку переменных по триггерам (например, Page URL содержит/не содержит), потому что переменные более «низкоуровневые» сущности, чем триггеры.


2.3. Альтернатива переменной DOM

Опрашивать DOM из тега Custom HTML только на нужных событиях, с использованием объекта обработчика DL (или без такового).

Делаем тег Custom HTML с сужением условий выборки, используя триггеры – когда нужно проверить наличие элемента (например, DOM Ready + Page URL или клик + Page URL, и т.д.).

Далее в тег вбиваем запрос на поиск элемента (вместо 0 можно поставить задержку в секундах):

Трансляция события поиска элемента с помощью обработчика

{{DL Processor}}.pushT(0, "DOM Element", "search");

Делаем триггер, который ловит это событие:

Триггер события поиска DOM элемента

Теперь тег Custom HTML, который срабатывает по этому триггеру, ищет элемент и отправляет ещё событие в объект данных, которое свидетельствует о том, что элемент найден. Например:

Трансляция события в Data Layer о том, что элемент найден

(function() {	
    if (document.querySelector('.dom-element-class') === null) { return; }
    {{DL Processor}}.pushT(0, "DOM Element", "exists");
})();

Теперь триггер, который ловит и это событие (по аналогии с предыдущим, только message отличается):

Триггер события о том, что DOM элемент найден

Всё – это фактически триггер, куда можно (если нужно) добавить ещё условий для взаимодействия с соответствующим элементом DOM.


2.4. Custom Javascript

Возможности таких переменных огромны, здесь будет приведён лишь частный пример, когда можно отказаться от Custom Javascript. Однако логика отказа от таких переменных в пользу тегов Custom HTML одна и та же, и подходит для других случаев

Например, решили реализовать поиск элемента DOM на определённых страницах, опрашивая DOM, возвращая true/false в переменную.

Пример:


function () {
    var loc = window.location.href;
    var isTargetPage = (loc.includes('/cat/') || loc.includes('/product/')) ? true : false;
    if (!isTargetPage) { return false; }
    return document.querySelector('.dom-element-class') !== null ? true : false;
}

Хотя здесь идёт фильтр по страницам, и опрос DOM более экономный, чем в случае ранее рассмотренной переменной DOM, но всё равно на каждой странице и на каждом событии GTM выполняется как минимум первые 3 строки IIFE. Не касаясь величины затрат процессорного времени, такая реализация видится громоздкой (несмотря на то, что фильтрация по url’у без регулярок).


2.5. Альтернатива переменной Custom Javascript

Подбирать элемент DOM цепочкой Custom HTML и триггеров, рассмотренных ранее, плюс включить в один из триггеров фильтрацию по url’у. Получится гораздо экономнее и более гибко.


3. Оптимизация Google Tag Manager

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

  • Задействовать только те встроенные переменные, которые нужны, остальные выключить;
  • Свести к минимуму число переменных;
  • Прежде создания переменной, подумать, можно ли избежать этого с помощью цепочек Custom HTML и триггеров по событиям (как выше рассматривалось);
  • Свести к минимуму число триггеров и тегов – отслеживать только то, что нужно; в крайнем случае, поставить неиспользуемые теги на паузу;
  • Свести к минимуму взаимодействия по событиям загрузки страницы (просмотр страницы, DOM Ready, Window loaded и события инициализации GTM), также см. п. 1.6;
  • В тегах, работающих по событиям загрузки страницы (выше упоминались), использовать минимум регулярных выражений, особенно избегать «тяжёлых» регулярок;
  • Свести к минимуму регистрацию изменений в DOM (чекбокс в настройках триггера «Видимость элемента»); гуглоиды тоже предупреждают об осторожной работе с данной опцией;
  • Если нужно отследить видимость элемента, который появляется спустя +- одинаковое время (например, юзер нажал что-то, и после этого точно появится такой-то элемент), можно использовать метод pushT управляющего объекта, выставив лаг с запасом и организовав последующий запрос элемента, как рассматривалось выше; менее точно, но часто лучше, чем дёргать DOM на наличие изменений;
  • По возможности, и где уместно – фильтровать по типам страниц (не выполнять теги на неподходящих типах страниц).

Использованные картинки: 1, 2, 3