GTM рецепты — теги и триггеры

## Передача значений между dataLayer и переменными GTM: где чаще всего ломается логика

## Передача значений между dataLayer и переменными GTM: где чаще всего ломается логика

Восемь из десяти разборов чужих контейнеров, которые попадают мне в руки, валятся на одном и том же месте — разработчик путает **источник правды** для значений. dataLayer пушитят событие, в триггере проверяют встроенную переменную, в теге снова читают dataLayer, а в отчёте — пустота или, что хуже, мусорные дубли.

Разложу, как мы в команде договариваемся о трёх уровнях и зачем это нужно.

**Уровень 1 — dataLayer.** Это контракт между сайтом и GTM. Сюда попадает только то, что сайт *готов отдать* и что не меняется после загрузки. Идентификатор заказа, тип пользователя, источник визита, список товаров в корзине. Содержимое dataLayer фиксируется в момент пуша — дальше оно лежит как снимок.

**Уровень 2 — встроенные и пользовательские переменные.** Это *производные* от dataLayer. Переменная не должна жить своей жизнью, у неё одна задача: достать значение по понятному пути и положить в удобную обёртку. Если вы ловите {{DLV — ecommerce.transaction_id}} в dataLayer, а в теге используете {{Transaction ID}}, которую определили вручную — у вас два места правды, и они рано или поздно разъедутся.

**Уровень 3 — теги.** Тег *потребляет* значения, но ничего не хранит. Шаблон тега должен ссылаться на переменные, а не на dataLayer напрямую. Это кажется педантизмом, пока не приходит задача «поменяй название параметра в трёх местах» и не выясняется, что в одном месте стоит dataLayer.push, в другом — переменная, в третьем — хардкод в шаблоне.

Практическое правило, которое экономит часы дебага: **один смысл — один источник чтения**. Если в dataLayer уже есть идентификатор заказа, не плодите custom JS, который его же вытаскивает из DOM. Если у вас есть переменная {{User Type}}, не дёргайте в теге window.dataLayer[0]['user_type'] напрямую.

Отдельная боль — порядок пушей. dataLayer.push({...}) *до* установки GTM не виден контейнеру. dataLayer.push({...}) *после* установки — виден, но если между ними успело сработать событие типа Pageview, ваше значение опоздает к нужному триггеру. Решение старое: либо пушить всё критичное в dataLayer до фрагмента GTM, либо использовать event name в dataLayer и подписываться на него триггером Custom Event — это самый предсказуемый паттерн в 2026 году.

И последнее. Переменная GTM — это не место для бизнес-логики. Решение «если user_type равен X, подставить Y» должно жить либо на сайте (до пуша), либо в lookup-таблице переменной, либо в условии триггера. Когда логика рассыпана по десяти местам, любая правка превращается в археологическую экспедицию.

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

Хорошим правилом самопроверки считаю вопрос: «Если завтра в dataLayer переименуют поле, в скольких местах я должен буду поправить?» Если больше двух — пора пересобирать структуру.

— @GTMrecipesRuPro
Этот пост опубликован в Telegram-канале GTM рецепты — теги и триггеры. Подписаться можно по ссылке: @GTMrecipesRuPro.
tech

Свежие посты в категории «Tech Infrastructure»

Все каналы категории →

start

Готовы запустить рекламу через сеть public.tg?

Новый оффер, продукт, GEO, кейс, событие или партнёрский запуск — соберём маршрут под задачу и отдадим медиаплан.

Telegram для медиаплана: @AFFtop_connect. Быстрый тест: $20 за канал, $1000 за пакет по сети.