Відстеження глибини скролінгу та часу на активній вкладці за допомогою Google Tag Manager

Відстеження глибини скролінгу та часу на активній вкладці за допомогою Google Tag Manager

Розповідати про важливість відстеження скролінгу та часу на сторінці багато не варто. Чим більше інформації про взаємодію користувачів із контентом сторінки ми зберемо, тим краще. До того ж краще одразу з двох сторін:

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

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

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

Тег для збору даних про глибину скролінгу та часу на сторінці

У Google Tag Manager існує стандартний тригер для відстеження глибини скролінгу. Він має свій мінус: дані відправляються у момент досягнення порогового значення. Виходить, що за допомогою цього тригера немає можливості відстежити максимальне значення відсотка скролінгу. Для того, щоб обійти це обмеження, ми використовуємо користувацький скрипт, який додамо на сайт за допомогою тега типу Користувацький тег HTML (Custom 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. Це користувацька подія, на яку нам необхідно налаштувати тригер типу Спеціальна подія (Custom Event). Виглядає він так:Тригер типу події користувача для відстеження глибини прокручування і часу активності вкладки

Тег для передачі даних у Google Analytics

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

ВАЖЛИВО! Не забудьте вказати значення параметра Не взаємодія як True, щоб не зіпсувати значення показника відмов.

ВАЖЛИВО! У змінній налаштуваннях Google Analytics додайте налаштовуване поле transport зі значенням beacon. “Це налаштування дозволить перетворити звичайний GET запит, який за замовчуванням надсилає Google Analytics у POST, та передати його асинхронно використовуючи navigator.sendBeacon(). Докладніше можна почитати в офіційній документації.

Замість висновку

Рішення, описане в цій статті, дозволить вам краще зрозуміти, як відвідувачі вашого сайту взаємодіють з контентом на ньому, а також налаштувати аудиторії ремаркетингу на основі зібраних даних. Якщо у вас залишилися питання щодо налаштування – задавайте їх у коментарях.