Отслеживание глубины скроллинга и времени на активной вкладке с помощью Google Tag Manager

Отслеживание глубины скроллинга и времени на активной вкладке с помощью Google Tag Manager

      Рассказывать о важности отслеживания скроллинга и времени на странице много не стоит. Чем больше информации о взаимодействии пользователей с контентом страницы мы соберем, тем лучше. К тому же лучше сразу с двух сторон:

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

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

  1. Тег для сбора данных о глубине прокрутки и времени на странице
  2. Переменные типа Data Layer для хранения информации
  3. Триггера пользовательского события
  4. Тег для передачи данных в Google Analytics

Тег для сбора данных о глубине прокрутки и времени на странице

      В Google Tag Manager существует стандартный триггер для отслеживания глубины прокрутки. Он имеет свой минус: данные отправляются в момент достижения порогового значения. Получается, что с помощью этого триггера нет возможности отследить максимальное значение процента скроллинга. Для того, чтобы обойти это ограничение, мы используем пользовательский скрипт, который добавим на сайт с помощью тега типа Пользовательский HTML.

      Когда-то давно сам скрипт придумала Настя Тимошенко, а спустя несколько лет ее решение было мной улучшено. Ранее скрипт отслеживал время на странице просто измеряя разницу между временем наступления события beforeunload (моментом, перед выгрузкой страницы с браузера) и началом запуска на странице. Теперь, после усовершенствования, скрипт считает время только тогда, когда вкладка пользователя активна.

<script>
   (function ( $ ) {

       //определяем максимальную глубину скроллинга и функции обработки времени
       $.scrollEvent = function(current_max) {
           var documentObj = $(document);
           var windowObj = $(window);

           var documentHeight = documentObj.height();
           var windowHeight = windowObj.height();
           var currentHeight = windowHeight + documentObj.scrollTop();

           current_value = getPercent(documentHeight, currentHeight);
           return(current_max > current_value ? current_max : current_value);
       }

       $.fixTime = function() {
           var dateObj = new Date();
           return Math.floor(dateObj.getTime() / 1000);
       }

       function num(val){
           val = Math.floor(val);
           return val < 10 ? '0' + val : val;
       }

       $.timeFormat = function(ms){
           var sec = ms, hours = sec / 3600 % 24, minutes = sec / 60 % 60, seconds = sec % 60;
           return num(hours) + ":" + num(minutes) + ":" + num(seconds);
       };

       function getPercent(doc, cur) {
           return !cur ? 0 : Math.floor(cur * 100 / doc);
       }

   })( jQuery );

   //Определяем временные интервалы

   function getTimeInterval(time) {
       if (time >= 0 && time < 30)
           return 'from 0 sec to 30 sec';
       if (time >= 30 && time < 60)
           return 'from 30 sec to 1 min';
       if (time >= 60 && time < 120)
           return 'from 1 min to 2 min';
       if (time >= 120 && time < 180)
           return 'from 2 min to 3 min';
       if (time >= 180 && time < 300)
           return 'from 3 min to 5 min';
       if (time >= 300 && time < 480)
           return 'from 5 min to 8 min';
       if (time >= 480)
           return 'more 8 min';
   }

   //Определяем интервалы глубины скроллинга

   function getScrollingInterval(deep) {
       if (deep >= 0 && deep < 20)
           return 'from 0% to 20%';
       if (deep >= 20 && deep < 40)
           return 'from 20% to 40%';
       if (deep >= 40 && deep < 60)
           return 'from 40% to 60%';
       if (deep >= 60 && deep < 80)
           return 'from 60% to 80%';
       if (deep >= 80 && deep <= 100)
           return 'from 80% to 100%';
   }

   //Присваиваем характеристику читателю статьи исходя из глубины скроллинга и времени на странице

   function getCharacters(deep, time) {
       if (/Android|webOS|Windows Phone|Macintosh|Samsung|Nokia|Bada|Symbian|iPhone|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent))
           var etalon = 21.1;
       else
           var etalon = 15.7;
       var documentH = jQuery(document).height();
       var etalonT = Math.floor(documentH / etalon, 2);

       if (deep >= 70 && time >= 0.7 * etalonT)
           return 'Читал вдумчиво';
       if (deep >= 70 && time < 0.7 * etalonT)
           return 'Читал по диагонали';
       if (deep < 10)
           return 'Не читал вовсе';
       if (deep >= 40 && deep < 70 && time >= 0.5 * 0.7 * etalonT)
           return 'Бросил читать на середине';
       if (deep >= 10 && deep < 40 && time >= 0.25 * 0.7 * etalonT)
           return 'Бросил читать в начале';
       if (deep >= 40 && deep < 70 && time < 0.5 * 0.7 * etalonT)
           return 'Просмотрел материал до середины';
       if (deep >= 10 && deep < 40 && time < 0.25 * 0.7 * etalonT)
           return 'Начал просматривать, но бросил в начале';
   }

   // Функция подсчёта времени не активности окна

   function onVisibilityChange() {
       var current_timestamp;

       if (document.visibilityState == "hidden") {
           invisibility_time = jQuery.fixTime();
       } else {
           current_timestamp = jQuery.fixTime();
           window_invisibility_time += (current_timestamp - invisibility_time);
       }
   }

   //Осуществляем вызов вышеописанных функций и передаем данные в GTM

   jQuery(document).ready(function() {

       // запускаем все счётчики как только окно стало активным (впервые)

       if (document.visibilityState == "visible")
       {
           window_invisibility_time = 0; // время, которое окно было не активным
           document.addEventListener('visibilitychange', onVisibilityChange, false); // запускаем слушатель активности окна

           var startLiveDoc = jQuery.fixTime();
           var current_max = 0;
           jQuery(window).scroll(function() {
               current_max = jQuery.scrollEvent(current_max);
           });

           //назначаем объекту window событие, действие которого выполнится в момент завершения работы пользователя со страницей (закрытие, обновление, переход на другую страницу)

           jQuery(window).bind('beforeunload', function(){
               current_max_string = current_max.toString() + '%';
               var endLiveDoc = jQuery.fixTime();
               var timeLiveDoc = jQuery.timeFormat(endLiveDoc - startLiveDoc);

               var time_on_page_active = jQuery.timeFormat(endLiveDoc - startLiveDoc - window_invisibility_time);
               var character = getCharacters(current_max, endLiveDoc - startLiveDoc  - window_invisibility_time);
               var percent_of_scrolling_int = getScrollingInterval(current_max);

               var time_on_page_int = getTimeInterval(endLiveDoc - startLiveDoc);
               var time_on_page_int_active = getTimeInterval(endLiveDoc - startLiveDoc - window_invisibility_time);
               dataLayer.push({'event': 'Scroll to', 'percent_of_scrolling': current_max_string, 'time_on_page': timeLiveDoc, 'character' : character, 'percent_of_scrolling_interval' : percent_of_scrolling_int, 'time_on_page_interval' : time_on_page_int, 'time_on_page_active': time_on_page_active, 'time_on_page_interval_active' : time_on_page_int_active, 'time_invisibility' : window_invisibility_time});
           });
       }
   });
</script>

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

  • Тип тега — Custom HTML (Пользовательский HTML);
  • В поле HTML вставляем код скрипта;
  • Триггер — All Pages (Все страницы).Тег для отслеживания максимальной глубины прокрутки и времени когда вкладка была активна

      После создания тега перейдите в режим предварительного просмотра и попробуйте поймать событие beforeunload. Вы можете нажимать на кнопку обновления страницы — это действие будет инициировать нужное событие. При этом, стоит сразу же нажимать и кнопку Esc, чтобы предотвратить полную выгрузку страницы и загрузку новой. Ваша задача поймать следующую информацию в отладчике Google Tag Manager:Информация которую передает пользовательский тег на уровень данных

      Нужное нам событие — Scroll to. Как видите, в момент этого события в dataLayer передается много интересной информации:

  • time_on_page  — время от начала загрузки страницы до наступления события beforeunload;
  • time_on_page_interval — время от начала загрузки страницы до наступления события beforeunload, сгруппированное по интервалам;
  • time_on_page_active — время активности вкладки, от момента начала загрузки страницы до наступления события beforeunload;
  • time_on_page_interval_active — время активности вкладки, от момента начала загрузки страницы до наступления события beforeunload, сгруппированное по интервалам;
  • time_invisibility — время когда вкладка была неактивна;
  • percent_of_scrolling — максимальное значение глубины прокрутки, выраженное в процентах;
  • percent_of_scrolling_interval — максимальное значение глубины прокрутки, выраженное в процентах и сгруппированное по интервалам;
  • character — тип читателя. Значение определяется на основании данных глубины скроллинга и времени проведенного на странице.

      Скорее всего, вам не понадобится вся информация, которую передает скрипт, поэтому создайте переменные типа Data Layer только для тех ключей, которые вам необходимы.

Переменные типа Data Layer для хранения информации

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

  • time_on_page:Пример настройки переменной типа dataLayer для хранения времени проведенного на странице
  • time_on_page_interval:Пример настройки переменной типа dataLayer для хранения времени проведенного на странице в интервалах
  • time_on_page_active:Пример настройки переменной типа dataLayer для хранения времени активности вкладки
  • time_on_page_interval_active:Пример настройки переменной типа dataLayer для хранения времени активности вкладки в интервалах
  • time_invisibility:Пример настройки переменной типа dataLayer для хранения времени когда вкладка была неактивна
  • percent_of_scrolling_interval:Пример настройки переменной типа dataLayer для хранения значения максимальной глубины скроллинга в интервалах
  • character:Пример настройки переменной типа dataLayer для хранения информации о типе читателя

      Если вы все сделали верно, то в режиме предварительного просмотра в момент события Scroll to ваши переменные будут хранить в себе нужные значения:Пример данных которые отображаются в режиме отладки

Триггер пользовательского события

      Выше я уже не раз говорил о событии Scroll to. Это пользовательское событие, на которое нам необходимо настроить триггер. Выглядит он следующим образом:Триггер типа пользовательского события для отслеживания глубины прокрутки и времени активности вкладки

Тег для передачи данных в Google Analytics

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

      ВАЖНО! Не забудьте указать значение параметра Не взаимодействие как True, чтобы не испортить значение показателя отказов.

      ВАЖНО! В переменной настроек Google Analytics добавьте настраиваемое поле transport со значением beacon. “Эта настройка позволит преобразовать обычный GET запрос, который по умолчанию отправляет Google Analytics в POST, и передать его асинхронно используя navigator.sendBeacon().Более подробно можно почитать в официальной документации.

Вместо заключения

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