Gtm

dataLayer: як працює і як використовувати

dataLayer — глобальний масив між сайтом і GTM. Як влаштований, як правильно пушити події, читати значення через змінні і уникати типових помилок.

Автор: Андрій Коваленко 9 хв читання
Зміст

dataLayer — глобальний JavaScript-масив на сторінці, через який ваш сайт передає структуровані дані у Google Tag Manager. GTM слухає цей масив і, коли бачить потрібну подію, активує теги. Без dataLayer трекінг спирається на крихкий DOM — змінили клас кнопки і все зламалось.

Ця стаття — практичний розбір: як влаштований dataLayer, як правильно пушити події, як читати значення в GTM, реальні приклади для e-commerce і кастомних user properties, порядок ініціалізації і типові помилки.

Матеріал є продовженням основ GTM — якщо ви ще не розбирались з тегами і тригерами, прочитайте спочатку той посібник.

Що таке dataLayer і навіщо він потрібен

GTM може витягати дані двома способами: з DOM (клас елемента, текст кнопки, значення поля) або з dataLayer. DOM-підхід ненадійний: будь-який редизайн ламає трекінг. dataLayer — це контракт між командою розробки та аналітики: розробник пушить чітко описані об’єкти, аналітик читає їх через GTM незалежно від верстки.

Дивіться різницю на прикладі трекінгу кліку «Купити»:

ПідхідНалаштуванняЩо станеться при редизайні
DOM (Click trigger на CSS клас)Trigger: .btn-buyРозробник перейменував клас — трекінг мовчить
dataLayer.pushevent: 'add_to_cart' у onClickКнопка змінила вигляд — push залишився, все ок

Окремий плюс: через DOM ніколи не отримаєш дані, яких немає на сторінці — ціну з бекенду, ID авторизованого користувача, статус замовлення. dataLayer дозволяє передати все це з серверного шаблону або клієнтського JS.

Якщо хочете розібратись у терміні детальніше — дивіться glossary: dataLayer.

Структура dataLayer

window.dataLayer — звичайний масив JavaScript. Кожен елемент — об’єкт з довільними ключами і обов’язковим полем event (якщо хочете тригернути GTM).

window.dataLayer = [
  // Об'єкт 0 — контекст сторінки (без event, просто дані)
  {
    pageType: "product",
    pageLanguage: "uk",
    userId: "u_8821"
  },
  // Об'єкт 1 — подія при завантаженні
  {
    event: "page_view_ready",
    pageTitle: "Кросівки Nike Air Max"
  }
];

GTM на старті обробляє весь масив зверху донизу. Якщо знаходить об’єкт з полем event — перевіряє Custom Event тригери з таким ім’ям. Якщо об’єкт без event — просто оновлює внутрішній стан змінних.

Ключові поля

  • event (string) — ім’я події, яке GTM буде матчити по Custom Event тригерах. Іменуйте snake_case: add_to_cart, form_submit, video_play.
  • Будь-які інші поля — це параметри події, які ви читаєте через Data Layer Variable.

Ініціалізація dataLayer: порядок важливий

Один з найпоширеніших багів — неправильний порядок скриптів. Правило просте: dataLayer має бути оголошений до сніпету GTM.

Структура <head> має виглядати так:

<head>
  <!-- 1. Спочатку ініціалізація dataLayer і перший push -->
  <script>
    window.dataLayer = window.dataLayer || [];
    // Контекст сторінки, відомий на момент рендеру (серверні дані)
    window.dataLayer.push({
      pageType: "product",
      userId: "u_8821",        // якщо є авторизований користувач
      userType: "returning"
    });
  </script>

  <!-- 2. Потім сніпет GTM -->
  <script>
    (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
    new Date().getTime(),event:'gtm.js'});...
  </script>
</head>

Чому window.dataLayer = window.dataLayer || []? Захист від подвійного завантаження фрагмента (SPA-навігація, помилки збірки). Якщо просто window.dataLayer = [] — ви щоразу стираєте накопичені дані.

Якщо контекст сторінки прийде після GTM, він все одно потрапить в масив, але GTM вже оброблятиме перший Page View без цих даних. Тегам, прив’язаним до pageview, ці змінні будуть недоступні.

dataLayer.push: як правильно відправляти події

dataLayer.push(obj) — основний метод. Викликайте його в будь-який момент після ініціалізації:

// При кліку на кнопку (ваш JS)
document.querySelector('#btn-add-to-cart').addEventListener('click', function() {
  dataLayer.push({
    event: 'add_to_cart',
    ecommerce: {
      currency: 'UAH',
      value: 1490,
      items: [{
        item_id: 'SKU_1234',
        item_name: 'Кросівки Nike Air Max',
        item_category: 'Взуття',
        price: 1490,
        quantity: 1
      }]
    }
  });
});

GTM отримує цей push, знаходить Custom Event тригер з ім’ям add_to_cart, активує GA4 Event тег — і подія летить в аналітику.

Важливий нюанс: очищення ecommerce

Google вимагає очищати попередній ecommerce-об’єкт перед кожним новим push’ем. Якщо ви пушите add_to_cart після view_item, GTM злиє обидва об’єкти — і в другій події з’являться поля першої.

Правило: перед будь-яким ecommerce-пушем завжди робіть:

dataLayer.push({ ecommerce: null }); // очистити попередній стан
dataLayer.push({
  event: 'add_to_cart',
  ecommerce: { ... }
});

Це офіційна рекомендація Google у документації GA4 ecommerce (Make ecommerce measurements with Tag Manager).

Читання dataLayer у GTM через Data Layer Variable

Щоб використати значення з dataLayer в тегах або тригерах — створіть змінну типу Data Layer Variable.

Шлях: Variables → User-Defined Variables → New → Variable Type → Data Layer Variable.

Базові налаштування

  • Variable Name — ключ або шлях до вкладеного значення через крапку.
  • Data Layer Version — завжди версія 2 (за замовчуванням). Версія 1 — legacy, не підтримує шляхи через крапку.

Приклади Variable Name для різних структур:

Проста пара ключ-значення:
  Variable Name: pageType
  Значення з push: { pageType: "product" } → поверне "product"

Вкладений об'єкт (через крапку):
  Variable Name: ecommerce.value
  Значення з push: { ecommerce: { value: 1490 } } → поверне 1490

Перший елемент масиву:
  Variable Name: ecommerce.items.0.item_name
  Значення з push: { ecommerce: { items: [{ item_name: "Кросівки" }] } } → "Кросівки"

Використання змінної в тегу GA4

Після створення змінної її можна використати у GA4 Event Tag як параметр:

Tag: GA4 Event
Event Name: add_to_cart
Event Parameters:
  currency → {{DL - ecommerce.currency}}
  value    → {{DL - ecommerce.value}}
  items    → {{DL - ecommerce.items}}

Префікс DL - у назві — рекомендована конвенція для зручності читання в GTM.

Приклади: ecommerce events для GA4

Нижче — повні приклади push’ів для основних ecommerce-подій GA4. Структура items[] стандартизована Google.

view_item — перегляд картки товару

dataLayer.push({ ecommerce: null });
dataLayer.push({
  event: 'view_item',
  ecommerce: {
    currency: 'UAH',
    value: 1490,
    items: [{
      item_id: 'SKU_1234',
      item_name: 'Кросівки Nike Air Max',
      item_brand: 'Nike',
      item_category: 'Взуття',
      item_category2: 'Кросівки',
      price: 1490,
      quantity: 1
    }]
  }
});

purchase — завершення покупки

Зазвичай відправляється на thank-you-page, де бекенд вже знає деталі замовлення:

dataLayer.push({ ecommerce: null });
dataLayer.push({
  event: 'purchase',
  ecommerce: {
    transaction_id: 'ORDER_88210',  // обов'язково, унікальний
    currency: 'UAH',
    value: 2980,                    // без доставки та податків
    shipping: 70,
    tax: 0,
    coupon: 'SALE10',               // якщо застосовувався
    items: [
      {
        item_id: 'SKU_1234',
        item_name: 'Кросівки Nike Air Max',
        price: 1490,
        quantity: 2
      }
    ]
  }
});

Важливо: transaction_id має бути унікальним. GA4 дедублікує повторні відправки по transaction_id — дублікати purchase з одним ID ігноруються.

begin_checkout — початок оформлення замовлення

dataLayer.push({ ecommerce: null });
dataLayer.push({
  event: 'begin_checkout',
  ecommerce: {
    currency: 'UAH',
    value: 2980,
    items: [
      { item_id: 'SKU_1234', item_name: 'Кросівки Nike Air Max', price: 1490, quantity: 2 }
    ]
  }
});

Приклади: user properties через dataLayer

Крім ecommerce, dataLayer — зручний канал для передачі атрибутів користувача, які потрібні в GTM для сегментації або персоналізації.

Зазвичай ці дані встановлюються при завантаженні сторінки — якщо є авторизація:

// Серверний шаблон (PHP, Python, тощо) рендерить це у <head>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
  userId: "u_8821",             // не Email і не PII, тільки хешований/внутрішній ID
  userType: "returning",        // new / returning
  userPlan: "pro",              // free / pro / enterprise
  userCountry: "UA"
});

У GTM створіть Data Layer Variables: userId, userType, userPlan. Далі використайте їх у GA4 Configuration Tag → User Properties:

user_id    → {{DL - userId}}
user_type  → {{DL - userType}}
plan       → {{DL - userPlan}}

Важливо щодо PII: не передавайте Email, ім’я, телефон через dataLayer напряму — це порушує умови Google Analytics і GDPR. Тільки анонімізовані ID або категоріальні атрибути.

Як налагодити dataLayer у Preview Mode

GTM Preview Mode — головний інструмент перевірки. Відкрийте Preview, виконайте потрібну дію на сайті, потім у Tag Assistant:

  1. Виберіть подію зліва (наприклад, add_to_cart).
  2. Вкладка Variables — показує значення всіх Data Layer Variables на момент події.
  3. Вкладка Data Layer — показує повний стан масиву після кожного push’у.
  4. Вкладка Tags — показує які теги спрацювали чи ні.

Якщо в Variables бачите undefined — значення або не прийшло, або шлях написаний неправильно.

Також зручно прямо в консолі браузера переглянути поточний стан:

// Показати весь масив
console.log(window.dataLayer);

// Показати останній push
console.log(window.dataLayer[window.dataLayer.length - 1]);

Типові помилки при роботі з dataLayer

1. Ініціалізація після сніпету GTM

GTM стартував, пустив перший Page View — a dataLayer з контекстом ще не прийшов. Виправлення: завжди window.dataLayer = window.dataLayer || [] і перший push до GTM сніпету.

2. Немає очищення ecommerce перед push

Без dataLayer.push({ ecommerce: null }) поля від попередньої події залишаються в стані. В purchase з’являться items від view_item. Робіть очищення перед кожним ecommerce push’ем.

3. Помилка в назві ключа або регістрі

GTM чутливий до регістру: UserID і userId — різні ключі. Перевіряйте Variable Name з точністю до символу.

4. Версія Data Layer Variable = 1

В GTM при створенні Data Layer Variable є вибір Version 1 або 2. Версія 1 — застаріла, не підтримує шляхи через крапку (наприклад, ecommerce.value). Завжди обирайте версію 2.

5. Подвійна відправка events

Трапляється при SPA-навігації (React, Vue): при переходах між сторінками компонент може рендеритись двічі або push викликається з useEffect з некоректними залежностями. Дивіться GA4 DebugView — якщо подія приходить двічі підряд з різницею <1с — це воно.

6. Передача PII

Email або телефон в dataLayer → в GA4 → у Google — пряме порушення умов обслуговування та GDPR. Замість email — SHA-256 хеш або внутрішній CRM-ID.

7. push до того, як сторінка завантажила JS-файл із логікою

В SPA при client-side навігації код компонента може запустити dataLayer.push до того, як GTM завантажив поточний контейнер (якщо ви використовуєте lazy route). Рішення — перевіряти window.google_tag_manager або використовувати window.dataLayer.push з eventCallback.

8. Ненадійні event names

Назви типу buttonClick, formsubmit, AddToCart (camelCase або без правил) ускладнюють підтримку. Стандарт GA4 — snake_case, у нижньому регістрі: form_submit, add_to_cart, video_start. Дотримуйтесь цього з першого дня.

Як пов’язані dataLayer, GTM і GA4

Для кращого розуміння — загальна схема потоку даних:

Дія користувача (клік/перехід/покупка)
       ↓
dataLayer.push({ event: 'purchase', ecommerce: {...} })
       ↓
GTM чує нову подію в масиві
       ↓
GTM знаходить Custom Event тригер "purchase"
       ↓
GTM активує GA4 Event тег
       ↓
Тег читає параметри з Data Layer Variables:
  {{DL - ecommerce.value}} → 2980
  {{DL - ecommerce.items}} → [...]
       ↓
GA4 отримує подія purchase з параметрами

dataLayer — посередник. Сайт не знає, що існує GA4 або GTM; GTM не знає, що відбулося на сайті. dataLayer — нейтральний протокол між ними. Якщо завтра ви замінюєте GA4 на Matomo або додаєте Meta Pixel — просто підключаєте новий тег в GTM, push’и сайту не змінюються.

Детальніше про події у аналітиці — в глосарії.

Контрольний список перед публікацією нових push’ів

Перед тим як мерджити код із новими dataLayer push’ами, пройдіться по чек-листу:

  • window.dataLayer = window.dataLayer || [] стоїть до сніпету GTM.
  • Перед ecommerce push’ем є dataLayer.push({ ecommerce: null }).
  • event іменований у snake_case.
  • Вкладені поля (ecommerce.currency, ecommerce.value) відповідають GA4-схемі.
  • Жодних PII у відкритому вигляді.
  • Перевірено у GTM Preview Mode — потрібні теги спрацювали.
  • Перевірено у GA4 DebugView — подія з’явилась з правильними параметрами.
  • Відсутні дублікати (особливо для SPA).

Пов’язані матеріали

Цю статтю пише і оновлює Андрій Коваленко — без AI-води і партнерських посилань. Помітив застарілий факт чи неточність — напиши, перепишу того ж тижня.

Хто веде сайт і чому без AI