Tutorial: Z zagnieżdżonego dataLayer zbudować trwałe zmienne GTM

Spis treści
Sklep wypycha dane produktowe jako jeden zagnieżdżony obiekt, bo tak je i tak przechowuje. Menedżer tagów chce wartości płaskich, po jednej na zmienną, a pomostem między nimi jest zapis z kropkami.
Ten zapis sięga wszystkiego. Nie mówi natomiast, która z powstałych ścieżek będzie poprawna także w przyszłym miesiącu – a mniej więcej połowa nie będzie, z powodu niemającego nic wspólnego z menedżerem tagów.

Jak dociera zagnieżdżony push
Zwykły push e-commerce niesie trzy poziomy: zdarzenie, obiekt pod nim, a pod nim listę artykułów.
dataLayer.push({
event: "add_to_cart",
ecommerce: {
currency: "EUR",
value: 129.90,
items: [
{ item_id: "SKU-42", item_name: "Stuhl", price: 64.95, quantity: 2,
item_category: "Moebel", index: 0 },
{ item_id: "SKU-77", item_name: "Tisch", price: 219.00, quantity: 1,
item_category: "Moebel", index: 1 }
]
},
user: { logged_in: true, segment: "b2b" }
});
Rozpisany na ścieżki obiekt ten zawiera jedną nazwę zdarzenia, trzy wartości pod ecommerce, dwanaście wewnątrz listy artykułów i dwie pod user. Każda z nich jest osiągalna, a adresem jest łańcuch kluczy połączony kropkami.
Wersja 2 i kropka będąca rozdzielnikiem
Zmienna warstwy danych w menedżerze tagów ma ustawienie wersji i to ono wyznacza sposób odczytu nazwy.
Wersja 2: ecommerce.currency → "EUR"
ecommerce.items.0.item_id → "SKU-42"
user.segment → "b2b"
Wersja 1: ecommerce.currency → undefined
(caly ciag uchodzi za jeden klucz)
Wersja 2 jest domyślna dla nowych zmiennych i niemal zawsze właściwa. Wersja 1 istnieje dla jednego przypadku: klucza faktycznie noszącego kropkę w nazwie. Push z {"page.type": "pdp"} jest osiągalny wyłącznie wersją 1, bo wersja 2 szukałaby type w page, którego nie ma.
Dwa szczegóły kosztujące czas, dopóki są nieznane. Ścieżka rozróżnia wielkość liter w całości, więc Ecommerce.Items nic nie znajduje i nic nie zgłasza. A zmienna bez wartości domyślnej zwraca dla brakującej ścieżki undefined, co w tagu staje się pustym parametrem, a nie błędem – przekręcona ścieżka wygląda więc tak samo jak wartość nigdy niewysłana.
Listy i dlaczego indeks jest częścią kruchą
Krok w listę jest liczbą, a ta liczba to pozycja, a nie tożsamość.
| Ścieżka | Stabilna? | Dlaczego |
|---|---|---|
| ecommerce.currency | tak | Nazwany klucz na stałej głębokości |
| ecommerce.value | tak | Tak samo |
| user.segment | tak | Tak samo |
| ecommerce.items.0.item_id | nie | Pozycja 0 to artykuł, który akurat stoi z przodu |
| ecommerce.items.1.price | nie | Brakuje jej całkiem w koszyku z jednym artykułem |
Drugi wiersz dolnej połowy wytwarza szkodę cichą. W koszyku z jednym artykułem items.1 nie istnieje, zmienna pozostaje pusta, a tag wysyła parametr bez wartości. Nic nie zawodzi, a raport pokazuje liczbę nieco mniejszą niż sklep.
Ścieżka z indeksem da się obronić w dokładnie jednym położeniu: na stronie zawsze noszącej dokładnie jeden artykuł, na przykład karcie produktu. Wszędzie indziej – koszyk, kasa, zakup – liczba artykułów jest zmienna, a ich kolejność tak samo.
Scalanie, o które nikt nie prosił
Warstwa danych nie jest listą komunikatów. Menedżer tagów prowadzi scalony model wszystkich dotychczasowych pushy, a nowy push zostaje w niego wtopiony, zamiast go zastąpić.
Skutek jest określony i przykry. Strona wypychająca najpierw view_item z jednym artykułem, a potem add_to_cart z innym, zostawia wartości pierwszego artykułu wszędzie tam, gdzie drugi push ich nie nadpisze. Po liście artykułów o długości trzy przychodzi lista o długości jeden, a wychodzi scalona lista o długości trzy, z dwoma wpisami z poprzedniego zdarzenia.
dataLayer.push({ ecommerce: null }); // sprzata galaz
dataLayer.push({
event: "add_to_cart",
ecommerce: { currency: "EUR", value: 64.95, items: [ /* … */ ] }
});
Push sprzątający należy bez wyjątku przed każdy push e-commerce i jest najczęstszym pominięciem w podłączeniu sklepu. Jego działanie widać w podglądzie: widok komunikatów pokazuje, co zostało wypchnięte, widok modelu pokazuje, co zmienna naprawdę odczyta – a różnica między nimi to dokładnie ten problem.
Jedna zmienna zamiast dwudziestu
Tam, gdzie potrzebna jest cała lista, odpowiedzią nie jest dwadzieścia ścieżek z indeksem. Jest nią własna zmienna JavaScript czytająca listę i zwracająca to, czego potrzebuje tag.
function () {
var artikel = {{DLV - ecommerce.items}};
if (!Array.isArray(artikel) || !artikel.length) { return undefined; }
return artikel.map(function (a) {
return {
item_id: String(a.item_id || a.id || ""),
item_name: String(a.item_name || a.name || ""),
price: Number(a.price) || 0,
quantity: Number(a.quantity) || 1,
item_category: String(a.item_category || "")
};
}).filter(function (a) { return a.item_id !== ""; });
}
Trzy rzeczy daje to ponad odporność na kolejność. Ujednolica nazwy pól, więc sklep wysyłający na jednej stronie id, a na innej item_id, wytwarza dalej jedną postać. Wymusza typy, przez co cena przychodząca jako ciąg "64.95" przestaje być problemem. I odrzuca artykuły bez identyfikatora, które GA4 i tak by odrzuciło – tyle że po cichu.
Zmienna, którą to czyta, jest zwykłą zmienną warstwy danych wskazującą ecommerce.items, bez indeksu. Ta ścieżka jest stabilna, bo nazywa klucz, a nie pozycję.
Sprawdzenie w podglądzie
Dwa widoki podglądu rozstrzygają wszystko omówione powyżej i łatwo je ze sobą pomylić.
Widok komunikatów pokazuje push dokładnie tak, jak wysłała go strona. Widok modelu pokazuje scalony stan, który zmienna odczyta w tej chwili. Wartość stojąca w drugim, a brakująca w pierwszym, to pozostałość po wcześniejszym pushu – problem sprzątania – a wartość w pierwszym, brakująca w drugim, została zwykle nadpisana przez push późniejszy.
Trzeci widok, obszar zmiennych wybranego zdarzenia, pokazuje, co każda skonfigurowana zmienna faktycznie zwróciła. undefined w tym miejscu jest odpowiedzią na niemal każde pytanie o brakujący parametr i rozdziela dwie możliwe przyczyny: ścieżka jest błędna albo wartość nigdy nie została wypchnięta. Zestawienie zmiennej z widokiem modelu rozdziela to w sekundy.
Ostatni nawyk zapobiega najbardziej mozolnej klasie błędów. Ścieżka ze źródła strony to nie ścieżka z warstwy danych – wtyczka sklepu potrafi zmienić nazwy kluczy między szablonem a pushem, a sklep przetłumaczony czasem tłumaczy je razem z resztą. Ścieżkę należy skopiować z widoku modelu prawdziwego zdarzenia, a nie przepisać z dokumentacji.