{"id":912,"date":"2026-04-14T16:03:42","date_gmt":"2026-04-14T14:03:42","guid":{"rendered":"https:\/\/www.sabatka.net\/cs\/?p=912"},"modified":"2026-04-15T09:47:03","modified_gmt":"2026-04-15T07:47:03","slug":"datalayer-and-recursive-merge","status":"publish","type":"post","link":"https:\/\/www.sabatka.net\/cs\/datalayer-and-recursive-merge\/","title":{"rendered":"dataLayer a recursive merge"},"content":{"rendered":"\n<p>dataLayer je jednoduch\u00e9 javascriptov\u00e9 pole. Pushnu objekt, p\u0159e\u010dtu si ho v prom\u011bnn\u00e9 v Google Tag Manageru (GTM), hotovo. Na tom p\u0159ece nem\u016f\u017ee b\u00fdt nic slo\u017eit\u00e9ho.<\/p>\n\n\n\n<p>Jasn\u011b.<\/p>\n\n\n\n<p>Pokud navrhujete strukturu dataLayer a je\u0161t\u011b jste nesly\u0161eli o recursive merge, zva\u017ete, jestli chcete \u010d\u00edst d\u00e1le. Bude se v\u00e1m sp\u00e1t h\u016f\u0159.<\/p>\n\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button scroll_to_subscribe\"><a class=\"wp-block-button__link wp-element-button\" href=\"#\">Chci odeb\u00edrat novinky<\/a><\/div>\n\n\n\n<div class=\"wp-block-button linkedinShare\"><a class=\"wp-block-button__link wp-element-button\">Sd\u00edlet na LinkedIN<\/a><\/div>\n<\/div>\n\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">dataLayer vs. datov\u00fd model GTM \u2014 to nen\u00ed tot\u00e9\u017e<\/h2>\n\n\n\n<p>Ne\u017e se pust\u00edme do p\u0159\u00edklad\u016f, pot\u0159ebujeme si ujasnit jednu z\u00e1sadn\u00ed v\u011bc. V diskuz\u00edch o dataLayer se b\u011b\u017en\u011b zam\u011b\u0148uj\u00ed dva pojmy, kter\u00e9 znamenaj\u00ed n\u011bco jin\u00e9ho:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>dataLayer<\/strong> \u2014 javascriptov\u00e9 pole (<code>Array<\/code>), do kter\u00e9ho pushujete objekty. \u017dije v prohl\u00ed\u017ee\u010di, m\u016f\u017eete se na n\u011bj pod\u00edvat v konzoli.<\/li>\n\n\n\n<li><strong>Datov\u00fd model GTM<\/strong> (intern\u00ed stav) \u2014 objekt, kter\u00fd si GTM udr\u017euje intern\u011b. Kdy\u017e v GTM vytvo\u0159\u00edte prom\u011bnnou typu Data Layer Variable, \u010dtete z tohoto intern\u00edho modelu \u2014 ne p\u0159\u00edmo z pole dataLayer.<\/li>\n<\/ul>\n\n\n\n<p>A pr\u00e1v\u011b tady za\u010d\u00edn\u00e1 z\u00e1bava. Kdy\u017e zavol\u00e1te <code>dataLayer.push()<\/code>, GTM vezme v\u00e1\u0161 objekt a <strong>mergne ho<\/strong> do sv\u00e9ho intern\u00edho datov\u00e9ho modelu. A ten merge nen\u00ed prost\u00fd p\u0159epis. Je to <strong>recursive merge<\/strong>.<\/p>\n\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Co je recursive merge<\/h2>\n\n\n\n<p>Recursive merge (hloubkov\u00e9 slu\u010dov\u00e1n\u00ed) znamen\u00e1, \u017ee GTM proch\u00e1z\u00ed strukturu objektu \u00farove\u0148 po \u00farovni a slu\u010duje hodnoty. Primitivn\u00ed hodnoty (string, number, boolean) se p\u0159ep\u00ed\u0161ou. Ale vno\u0159en\u00e9 objekty se neslu\u010duj\u00ed jako celek \u2014 GTM sestoup\u00ed dovnit\u0159 a slou\u010d\u00ed jednotliv\u00e9 kl\u00ed\u010de.<\/p>\n\n\n\n<p>Zn\u00ed to nevinn\u011b. Pod\u00edvejme se, co to znamen\u00e1 v praxi.<\/p>\n\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">dataLayer etudy<\/h2>\n\n\n\n<p>P\u0159ipravil jsem n\u011bkolik sc\u00e9n\u00e1\u0159\u016f. U ka\u017ed\u00e9ho zkuste nejd\u0159\u00edv odpov\u011bd\u011bt sami \u2014 a pak si p\u0159e\u010dt\u011bte \u0159e\u0161en\u00ed.<\/p>\n\n\n\n<div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Etuda 1: Jednoduch\u00fd p\u0159epis<\/h3>\n\n\n\n<p>Co dostanu v datov\u00e9m modelu v prom\u011bnn\u00e9 <code>x<\/code>?<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>dataLayer.push({'x': 1});\ndataLayer.push({'x': 2});\n<\/code><\/pre>\n\n\n\n<div data-wp-context=\"{ &quot;autoclose&quot;: false, &quot;accordionItems&quot;: [] }\" data-wp-interactive=\"core\/accordion\" role=\"group\" class=\"wp-block-accordion is-layout-flow wp-block-accordion-is-layout-flow\">\n<div data-wp-class--is-open=\"state.isOpen\" data-wp-context=\"{ &quot;id&quot;: &quot;accordion-item-1&quot;, &quot;openByDefault&quot;: false }\" data-wp-init=\"callbacks.initAccordionItems\" data-wp-on-window--hashchange=\"callbacks.hashChange\" class=\"wp-block-accordion-item is-layout-flow wp-block-accordion-item-is-layout-flow\">\n<h3 class=\"wp-block-accordion-heading\"><button aria-expanded=\"false\" aria-controls=\"accordion-item-1-panel\" data-wp-bind--aria-expanded=\"state.isOpen\" data-wp-on--click=\"actions.toggle\" data-wp-on--keydown=\"actions.handleKeyDown\" id=\"accordion-item-1\" type=\"button\" class=\"wp-block-accordion-heading__toggle\"><span class=\"wp-block-accordion-heading__toggle-title\">> Spr\u00e1vn\u00e1 odpov\u011b\u010f<\/span><span class=\"wp-block-accordion-heading__toggle-icon\" aria-hidden=\"true\">+<\/span><\/button><\/h3>\n\n\n\n<div inert aria-labelledby=\"accordion-item-1\" data-wp-bind--inert=\"!state.isOpen\" id=\"accordion-item-1-panel\" role=\"region\" class=\"wp-block-accordion-panel is-layout-flow wp-block-accordion-panel-is-layout-flow\">\n<p><strong>x = <code>2<\/code><\/strong><\/p>\n\n\n\n<p>\u017d\u00e1dn\u00e9 p\u0159ekvapen\u00ed. Primitivn\u00ed hodnota se prost\u011b p\u0159ep\u00ed\u0161e. Tohle funguje p\u0159esn\u011b tak, jak \u010dek\u00e1te.<\/p>\n<\/div>\n<\/div>\n<\/div>\n\n\n\n<div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Etuda 2: Vno\u0159en\u00fd objekt<\/h3>\n\n\n\n<p>Co dostanu v datov\u00e9m modelu v prom\u011bnn\u00e9 <code>x<\/code>?<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>dataLayer.push({'x': {'a': 1} });\ndataLayer.push({'x': {'b': 2} });\n<\/code><\/pre>\n\n\n\n<div data-wp-context=\"{ &quot;autoclose&quot;: false, &quot;accordionItems&quot;: [] }\" data-wp-interactive=\"core\/accordion\" role=\"group\" class=\"wp-block-accordion is-layout-flow wp-block-accordion-is-layout-flow\">\n<div data-wp-class--is-open=\"state.isOpen\" data-wp-context=\"{ &quot;id&quot;: &quot;accordion-item-2&quot;, &quot;openByDefault&quot;: false }\" data-wp-init=\"callbacks.initAccordionItems\" data-wp-on-window--hashchange=\"callbacks.hashChange\" class=\"wp-block-accordion-item is-layout-flow wp-block-accordion-item-is-layout-flow\">\n<h3 class=\"wp-block-accordion-heading\"><button aria-expanded=\"false\" aria-controls=\"accordion-item-2-panel\" data-wp-bind--aria-expanded=\"state.isOpen\" data-wp-on--click=\"actions.toggle\" data-wp-on--keydown=\"actions.handleKeyDown\" id=\"accordion-item-2\" type=\"button\" class=\"wp-block-accordion-heading__toggle\"><span class=\"wp-block-accordion-heading__toggle-title\">> Spr\u00e1vn\u00e1 odpov\u011b\u010f<\/span><span class=\"wp-block-accordion-heading__toggle-icon\" aria-hidden=\"true\">+<\/span><\/button><\/h3>\n\n\n\n<div inert aria-labelledby=\"accordion-item-2\" data-wp-bind--inert=\"!state.isOpen\" id=\"accordion-item-2-panel\" role=\"region\" class=\"wp-block-accordion-panel is-layout-flow wp-block-accordion-panel-is-layout-flow\">\n<p><strong>x = <code>{'a': 1, 'b': 2}<\/code><\/strong><\/p>\n\n\n\n<p>A tady to za\u010d\u00edn\u00e1. Druh\u00fd push <strong>nep\u0159epsal<\/strong> cel\u00fd objekt <code>x<\/code>. GTM sestoupil dovnit\u0159 a p\u0159idal kl\u00ed\u010d <code>b<\/code> k existuj\u00edc\u00edmu kl\u00ed\u010di <code>a<\/code>. V\u00fdsledek je slou\u010den\u00fd objekt.<\/p>\n\n\n\n<p>Pokud jste \u010dekali <code>{'b': 2}<\/code>, nejste sami. Ale recursive merge funguje jinak \u2014 proch\u00e1z\u00ed strukturu a slu\u010duje, nep\u0159episuje.<\/p>\n<\/div>\n<\/div>\n<\/div>\n\n\n\n<p><\/p>\n\n\n\n<div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Etuda 3: Pole (Array)<\/h3>\n\n\n\n<p>Co dostanu v datov\u00e9m modelu v prom\u011bnn\u00e9 <code>x<\/code>?<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>dataLayer.push({'x': &#91;1, 2, 3] });\ndataLayer.push({'x': &#91;4, 5] });\n<\/code><\/pre>\n\n\n\n<div data-wp-context=\"{ &quot;autoclose&quot;: false, &quot;accordionItems&quot;: [] }\" data-wp-interactive=\"core\/accordion\" role=\"group\" class=\"wp-block-accordion is-layout-flow wp-block-accordion-is-layout-flow\">\n<div data-wp-class--is-open=\"state.isOpen\" data-wp-context=\"{ &quot;id&quot;: &quot;accordion-item-3&quot;, &quot;openByDefault&quot;: false }\" data-wp-init=\"callbacks.initAccordionItems\" data-wp-on-window--hashchange=\"callbacks.hashChange\" class=\"wp-block-accordion-item is-layout-flow wp-block-accordion-item-is-layout-flow\">\n<h3 class=\"wp-block-accordion-heading\"><button aria-expanded=\"false\" aria-controls=\"accordion-item-3-panel\" data-wp-bind--aria-expanded=\"state.isOpen\" data-wp-on--click=\"actions.toggle\" data-wp-on--keydown=\"actions.handleKeyDown\" id=\"accordion-item-3\" type=\"button\" class=\"wp-block-accordion-heading__toggle\"><span class=\"wp-block-accordion-heading__toggle-title\">> Spr\u00e1vn\u00e1 odpov\u011b\u010f<\/span><span class=\"wp-block-accordion-heading__toggle-icon\" aria-hidden=\"true\">+<\/span><\/button><\/h3>\n\n\n\n<div inert aria-labelledby=\"accordion-item-3\" data-wp-bind--inert=\"!state.isOpen\" id=\"accordion-item-3-panel\" role=\"region\" class=\"wp-block-accordion-panel is-layout-flow wp-block-accordion-panel-is-layout-flow\">\n<p><strong>x = <code>[4, 5, 3]<\/code><\/strong><\/p>\n\n\n\n<p>Z\u00e1bava za\u010d\u00edn\u00e1. Pole se v recursive merge chov\u00e1 jako objekt s \u010d\u00edseln\u00fdmi kl\u00ed\u010di. Index 0 se p\u0159ep\u00ed\u0161e na <code>4<\/code>, index 1 na <code>5<\/code> a index 2 z\u016fstane <code>3<\/code>, proto\u017ee druh\u00fd push nem\u011bl t\u0159et\u00ed prvek.<\/p>\n\n\n\n<p>V\u00fdsledek nen\u00ed <code>[4, 5]<\/code> (p\u0159epis) ani <code>[1, 2, 3, 4, 5]<\/code> (concat). Je to hybrid, kter\u00fd ned\u00e1v\u00e1 smysl v \u017e\u00e1dn\u00e9m b\u011b\u017en\u00e9m program\u00e1torsk\u00e9m kontextu.<\/p>\n\n\n\n<p>Tak bacha na to.<\/p>\n<\/div>\n<\/div>\n<\/div>\n\n\n\n<div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Etuda 4: Pole produkt\u016f<\/h3>\n\n\n\n<p>Co dostanu v datov\u00e9m modelu v prom\u011bnn\u00e9 <code>x<\/code>?<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>dataLayer.push({'x': &#91;{'id': 1, 'name': 'Produkt 1'}] });\ndataLayer.push({'x': &#91;{'id': 2}] });\n<\/code><\/pre>\n\n\n\n<div data-wp-context=\"{ &quot;autoclose&quot;: false, &quot;accordionItems&quot;: [] }\" data-wp-interactive=\"core\/accordion\" role=\"group\" class=\"wp-block-accordion is-layout-flow wp-block-accordion-is-layout-flow\">\n<div data-wp-class--is-open=\"state.isOpen\" data-wp-context=\"{ &quot;id&quot;: &quot;accordion-item-4&quot;, &quot;openByDefault&quot;: false }\" data-wp-init=\"callbacks.initAccordionItems\" data-wp-on-window--hashchange=\"callbacks.hashChange\" class=\"wp-block-accordion-item is-layout-flow wp-block-accordion-item-is-layout-flow\">\n<h3 class=\"wp-block-accordion-heading\"><button aria-expanded=\"false\" aria-controls=\"accordion-item-4-panel\" data-wp-bind--aria-expanded=\"state.isOpen\" data-wp-on--click=\"actions.toggle\" data-wp-on--keydown=\"actions.handleKeyDown\" id=\"accordion-item-4\" type=\"button\" class=\"wp-block-accordion-heading__toggle\"><span class=\"wp-block-accordion-heading__toggle-title\">> Spr\u00e1vn\u00e1 odpov\u011b\u010f<\/span><span class=\"wp-block-accordion-heading__toggle-icon\" aria-hidden=\"true\">+<\/span><\/button><\/h3>\n\n\n\n<div inert aria-labelledby=\"accordion-item-4\" data-wp-bind--inert=\"!state.isOpen\" id=\"accordion-item-4-panel\" role=\"region\" class=\"wp-block-accordion-panel is-layout-flow wp-block-accordion-panel-is-layout-flow\">\n<p><strong>x = <code>[{'id': 2, 'name': 'Produkt 1'}]<\/code><\/strong><\/p>\n\n\n\n<p>Tohle je nejprakti\u010dt\u011bj\u0161\u00ed etuda. Recursive merge sestoupil do pole (index 0), uvnit\u0159 na\u0161el objekt \u2014 a mergoval ho znovu. V\u00fdsledek: produkt s <code>id: 2<\/code> zd\u011bdil <code>name: 'Produkt 1'<\/code> z p\u0159edchoz\u00edho pushe. Vznikl frankenstein \u2014 objekt, kter\u00fd popisuje neexistuj\u00edc\u00ed produkt.<\/p>\n\n\n\n<p>V e-commerce m\u011b\u0159en\u00ed je tohle no\u010dn\u00ed m\u016fra. Pokud pushujete eventy bez \u010di\u0161t\u011bn\u00ed datov\u00e9ho modelu, m\u016f\u017eete v Google Analytics 4 (GA4) reportech vid\u011bt produkt s cenou jin\u00e9ho produktu nebo s n\u00e1zvem p\u0159edchoz\u00ed polo\u017eky v ko\u0161\u00edku. A proto\u017ee to nespadne s chybou, m\u016f\u017eete na to p\u0159ij\u00edt a\u017e za t\u00fddny \u2014 z dat, kter\u00e1 ned\u00e1vaj\u00ed smysl.<\/p>\n<\/div>\n<\/div>\n<\/div>\n\n\n\n<p><\/p>\n\n\n\n<div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Etuda 5: Objekt + _clear<\/h3>\n\n\n\n<p>Co dostanu v datov\u00e9m modelu v prom\u011bnn\u00e9 <code>x<\/code>?<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>dataLayer.push({'x': {'a': 1} });\ndataLayer.push({'x': {'b': 2}, _clear: true });\n<\/code><\/pre>\n\n\n\n<div data-wp-context=\"{ &quot;autoclose&quot;: false, &quot;accordionItems&quot;: [] }\" data-wp-interactive=\"core\/accordion\" role=\"group\" class=\"wp-block-accordion is-layout-flow wp-block-accordion-is-layout-flow\">\n<div data-wp-class--is-open=\"state.isOpen\" data-wp-context=\"{ &quot;id&quot;: &quot;accordion-item-5&quot;, &quot;openByDefault&quot;: false }\" data-wp-init=\"callbacks.initAccordionItems\" data-wp-on-window--hashchange=\"callbacks.hashChange\" class=\"wp-block-accordion-item is-layout-flow wp-block-accordion-item-is-layout-flow\">\n<h3 class=\"wp-block-accordion-heading\"><button aria-expanded=\"false\" aria-controls=\"accordion-item-5-panel\" data-wp-bind--aria-expanded=\"state.isOpen\" data-wp-on--click=\"actions.toggle\" data-wp-on--keydown=\"actions.handleKeyDown\" id=\"accordion-item-5\" type=\"button\" class=\"wp-block-accordion-heading__toggle\"><span class=\"wp-block-accordion-heading__toggle-title\">> Spr\u00e1vn\u00e1 odpov\u011b\u010f<\/span><span class=\"wp-block-accordion-heading__toggle-icon\" aria-hidden=\"true\">+<\/span><\/button><\/h3>\n\n\n\n<div inert aria-labelledby=\"accordion-item-5\" data-wp-bind--inert=\"!state.isOpen\" id=\"accordion-item-5-panel\" role=\"region\" class=\"wp-block-accordion-panel is-layout-flow wp-block-accordion-panel-is-layout-flow\">\n<p><strong>x = <code>{'b': 2}<\/code><\/strong><\/p>\n\n\n\n<p>P\u0159\u00edznak <code>_clear: true<\/code> \u0159\u00edk\u00e1 GTM: kl\u00ed\u010de v tomto pushe zapi\u0161 jako celek, ned\u011blej recursive merge. Tak\u017ee <code>x<\/code> se nep\u0159id\u00e1v\u00e1 k existuj\u00edc\u00edmu <code>{'a': 1}<\/code> \u2014 p\u0159ep\u00ed\u0161e se cel\u00fd na <code>{'b': 2}<\/code>. Kl\u00ed\u010d <code>a<\/code> je pry\u010d.<\/p>\n<\/div>\n<\/div>\n<\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Etuda 6: _clear a jin\u00fd kl\u00ed\u010d<\/h3>\n\n\n\n<p>Co dostanu v datov\u00e9m modelu v prom\u011bnn\u00e9 <code>x<\/code>?<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>dataLayer.push({'x': {'a': 1} });\ndataLayer.push({'y': {'b': 2}, _clear: true });<\/code><\/pre>\n\n\n\n<div data-wp-context=\"{ &quot;autoclose&quot;: false, &quot;accordionItems&quot;: [] }\" data-wp-interactive=\"core\/accordion\" role=\"group\" class=\"wp-block-accordion is-layout-flow wp-block-accordion-is-layout-flow\">\n<div data-wp-class--is-open=\"state.isOpen\" data-wp-context=\"{ &quot;id&quot;: &quot;accordion-item-6&quot;, &quot;openByDefault&quot;: false }\" data-wp-init=\"callbacks.initAccordionItems\" data-wp-on-window--hashchange=\"callbacks.hashChange\" class=\"wp-block-accordion-item is-layout-flow wp-block-accordion-item-is-layout-flow\">\n<h3 class=\"wp-block-accordion-heading\"><button aria-expanded=\"false\" aria-controls=\"accordion-item-6-panel\" data-wp-bind--aria-expanded=\"state.isOpen\" data-wp-on--click=\"actions.toggle\" data-wp-on--keydown=\"actions.handleKeyDown\" id=\"accordion-item-6\" type=\"button\" class=\"wp-block-accordion-heading__toggle\"><span class=\"wp-block-accordion-heading__toggle-title\">> Spr\u00e1vn\u00e1 odpov\u011b\u010f<\/span><span class=\"wp-block-accordion-heading__toggle-icon\" aria-hidden=\"true\">+<\/span><\/button><\/h3>\n\n\n\n<div inert aria-labelledby=\"accordion-item-6\" data-wp-bind--inert=\"!state.isOpen\" id=\"accordion-item-6-panel\" role=\"region\" class=\"wp-block-accordion-panel is-layout-flow wp-block-accordion-panel-is-layout-flow\">\n<p><strong>x = <code>{'a': 1}<\/code><\/strong><\/p>\n\n\n\n<p><code>_clear: true<\/code> resetuje jen root kl\u00ed\u010de p\u0159\u00edtomn\u00e9 v dan\u00e9m pushe. Druh\u00fd push zapisuje pouze <code>y<\/code> \u2014 na <code>x<\/code> nesah\u00e1. Hodnota <code>x<\/code> z\u016fst\u00e1v\u00e1 <code>{'a': 1}<\/code>.<\/p>\n\n\n\n<p>Tohle je d\u016fle\u017eit\u00e9 pochopit: <code>_clear<\/code> nen\u00ed glob\u00e1ln\u00ed reset cel\u00e9ho datov\u00e9ho modelu. Resetuje jen to, co pushujete.<\/p>\n<\/div>\n<\/div>\n<\/div>\n\n\n\n<div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Etuda 7: Pole + _clear<\/h3>\n\n\n\n<p>Co dostanu v datov\u00e9m modelu v prom\u011bnn\u00e9 <code>x<\/code>?<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>dataLayer.push({'x': &#91;1, 2, 3] });\ndataLayer.push({'x': &#91;4, 5], _clear: true });\n<\/code><\/pre>\n\n\n\n<div data-wp-context=\"{ &quot;autoclose&quot;: false, &quot;accordionItems&quot;: [] }\" data-wp-interactive=\"core\/accordion\" role=\"group\" class=\"wp-block-accordion is-layout-flow wp-block-accordion-is-layout-flow\">\n<div data-wp-class--is-open=\"state.isOpen\" data-wp-context=\"{ &quot;id&quot;: &quot;accordion-item-7&quot;, &quot;openByDefault&quot;: false }\" data-wp-init=\"callbacks.initAccordionItems\" data-wp-on-window--hashchange=\"callbacks.hashChange\" class=\"wp-block-accordion-item is-layout-flow wp-block-accordion-item-is-layout-flow\">\n<h3 class=\"wp-block-accordion-heading\"><button aria-expanded=\"false\" aria-controls=\"accordion-item-7-panel\" data-wp-bind--aria-expanded=\"state.isOpen\" data-wp-on--click=\"actions.toggle\" data-wp-on--keydown=\"actions.handleKeyDown\" id=\"accordion-item-7\" type=\"button\" class=\"wp-block-accordion-heading__toggle\"><span class=\"wp-block-accordion-heading__toggle-title\">> Spr\u00e1vn\u00ed odpov\u011b\u010f<\/span><span class=\"wp-block-accordion-heading__toggle-icon\" aria-hidden=\"true\">+<\/span><\/button><\/h3>\n\n\n\n<div inert aria-labelledby=\"accordion-item-7\" data-wp-bind--inert=\"!state.isOpen\" id=\"accordion-item-7-panel\" role=\"region\" class=\"wp-block-accordion-panel is-layout-flow wp-block-accordion-panel-is-layout-flow\">\n<p><strong>x = <code>[4, 5]<\/code><\/strong><\/p>\n\n\n\n<p>Se <code>_clear: true<\/code> se pole chov\u00e1 p\u0159edv\u00eddateln\u011b \u2014 kl\u00ed\u010d <code>x<\/code> se p\u0159ep\u00ed\u0161e jako celek. \u017d\u00e1dn\u00e9 hybridn\u00ed slu\u010dov\u00e1n\u00ed index\u016f.<\/p>\n<\/div>\n<\/div>\n<\/div>\n\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Co z toho vypl\u00fdv\u00e1<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Data se v datov\u00e9m modelu kumuluj\u00ed<\/h3>\n\n\n\n<p>Pokud pushnu e-commerce data pro produkt A a pak pushnu data pro produkt B, v datov\u00e9m modelu <strong>z\u016fst\u00e1vaj\u00ed oba<\/strong>. Vno\u0159en\u00e9 objekty se slu\u010duj\u00ed, ne p\u0159episuj\u00ed.<\/p>\n\n\n\n<p>S <code>_clear:true<\/code> m\u00e1te mo\u017enost ale jednotliv\u00e9 \u010d\u00e1sti dataLayer m\u011bnit.<\/p>\n\n\n\n<div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:33.33%\">\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"1024\" height=\"1024\" data-src=\"https:\/\/www.sabatka.net\/wp-content\/uploads\/2026\/04\/null-did-you-know.png\" alt=\"\" class=\"wp-image-936 lazyload\" data-srcset=\"https:\/\/www.sabatka.net\/wp-content\/uploads\/2026\/04\/null-did-you-know.png 1024w, https:\/\/www.sabatka.net\/wp-content\/uploads\/2026\/04\/null-did-you-know-300x300.png 300w, https:\/\/www.sabatka.net\/wp-content\/uploads\/2026\/04\/null-did-you-know-150x150.png 150w, https:\/\/www.sabatka.net\/wp-content\/uploads\/2026\/04\/null-did-you-know-768x768.png 768w\" data-sizes=\"(max-width: 1024px) 100vw, 1024px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 1024px; --smush-placeholder-aspect-ratio: 1024\/1024;\" \/><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:66.66%\">\n<h3 class=\"wp-block-heading\">V\u011bdeck\u00e1 pozn\u00e1mka<\/h3>\n\n\n\n<p>Je to jako <a href=\"https:\/\/cs.wikipedia.org\/wiki\/Th%C3%A9seuova_lo%C4%8F\" target=\"_blank\" rel=\"noopener\">Th\u00e9seuova lo\u010f<\/a> \u2014 pokud ka\u017ed\u00fdm pushem nahrad\u00edte \u010d\u00e1st objektu, je to po\u0159\u00e1d ten sam\u00fd objekt?<br><br>Mmm&#8230;<\/p>\n<\/div>\n<\/div>\n\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Z\u00e1le\u017e\u00ed na tom, kdy p\u0159esn\u011b jak\u00e1 data \u010dtete<\/h3>\n\n\n\n<p>Na <strong>single page aplikac\u00edch<\/strong> je to naprosto z\u00e1sadn\u00ed probl\u00e9m. U\u017eivatel p\u0159ejde z produktov\u00e9 str\u00e1nky na kategorii \u2014 ale data o produktu jsou po\u0159\u00e1d v datov\u00e9m modelu. Pokud tag \u010dte prom\u011bnnou v moment, kdy u\u017e by tam nem\u011bla b\u00fdt, pos\u00edl\u00e1te do GA4 nesmysly.<\/p>\n\n\n\n<p>Na <strong>klasick\u00e9m webu<\/strong> je tohle men\u0161\u00ed probl\u00e9m (str\u00e1nka se reloadne, dataLayer se vytvo\u0159\u00ed znovu), ale po\u0159\u00e1d to dok\u00e1\u017ee u\u0161kodit. Typick\u00fd p\u0159\u00edklad: u\u017eivatel p\u0159id\u00e1 produkt do ko\u0161\u00edku, pak ho odebere. Pokud odebr\u00e1n\u00ed pushnete jako nov\u00fd objekt bez vy\u010di\u0161t\u011bn\u00ed, <a href=\"https:\/\/www.sabatka.net\/cs\/revenue-in-ga4-do-you-know-what-you-are-looking-at\/\">data o revenue v GA4 nebudou sed\u011bt<\/a> \u2014 proto\u017ee v datov\u00e9m modelu z\u016fst\u00e1vaj\u00ed zbytky p\u0159edchoz\u00edch push\u016f.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u0158e\u0161en\u00ed existuj\u00ed, ale \u017e\u00e1dn\u00e9 nen\u00ed univerz\u00e1ln\u00ed<\/h3>\n\n\n\n<p>Tady nen\u00ed silver bullet. Ka\u017ed\u00fd p\u0159\u00edstup m\u00e1 trade-offy a je t\u0159eba promyslet, aby cel\u00e9 \u0159e\u0161en\u00ed d\u00e1valo smysl v kontextu va\u0161eho webu:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u010ci\u0161t\u011bn\u00ed na stran\u011b v\u00fdvoj\u00e1\u0159\u016f<\/strong> \u2014 Program\u00e1to\u0159i explicitn\u011b resetuj\u00ed relevantn\u00ed kl\u00ed\u010de p\u0159ed nov\u00fdm pushem. Spolehliv\u00e9, ale vy\u017eaduje discipl\u00ednu a dokumentaci. Jak\u00e9koli opomenut\u00ed = tich\u00e1 chyba v datech.<\/li>\n\n\n\n<li><strong>Selektivn\u00ed \u010dten\u00ed v GTM<\/strong> \u2014 Ne\u010dtete prom\u011bnnou \u201eobecn\u011b&#8220;, ale v\u00e1\u017eete ji na konkr\u00e9tn\u00ed event. Trigger se aktivuje jen na ten spr\u00e1vn\u00fd push, tak\u017ee \u010dtete data v moment, kdy jsou aktu\u00e1ln\u00ed. Funguje dob\u0159e, ale konfigurace se m\u016f\u017ee zkomplikovat.<\/li>\n\n\n\n<li><strong><code>_clear: true<\/code><\/strong> \u2014 Resetuje root kl\u00ed\u010de v dan\u00e9m pushe \u2014 m\u00edsto recursive merge je p\u0159ep\u00ed\u0161e cel\u00e9. Bezpe\u010dn\u00e9 proti kumulaci v r\u00e1mci jednoho kl\u00ed\u010de. Ale pozor: neresetuje ostatn\u00ed root kl\u00ed\u010de. Pokud pot\u0159ebujete vy\u010distit i jin\u00e9 kl\u00ed\u010de, mus\u00edte je v pushe explicitn\u011b nastavit na <code>null<\/code> nebo je do pushe zahrnout.<\/li>\n\n\n\n<li><strong>dataLayer picker<\/strong> &#8211; \u0161ablona, kter\u00e1 v\u00e1m z dataLayer na\u010dte pouze data z pushe, kter\u00fd triggeroval event. V\u00edce o <a href=\"https:\/\/www.simoahava.com\/custom-templates\/data-layer-picker\/\" target=\"_blank\" rel=\"noopener\">dataLayer picker psal Simo Ahava<\/a>.<br>Pozn.: d\u00edky <a href=\"https:\/\/mareklecian.cz\/\" data-type=\"link\" data-id=\"https:\/\/mareklecian.cz\/\" target=\"_blank\" rel=\"noopener\">Markovi Leci\u00e1novi<\/a> za dopln\u011bn\u00ed t\u00e9hle mo\u017enosti<\/li>\n\n\n\n<li><strong>Kombinace<\/strong> \u2014 V praxi v\u011bt\u0161inou skon\u010d\u00edte u kombinace p\u0159\u00edstup\u016f. Na m\u00fdch projektech typicky doporu\u010duji <code>_clear: true<\/code> pro e-commerce eventy (add_to_cart, purchase) a selektivn\u00ed \u010dten\u00ed pro ostatn\u00ed.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Extra bacha na pole<\/h3>\n\n\n\n<p>Etuda 3 ukazuje, pro\u010d jsou pole v dataLayer zr\u00e1dn\u00e1. Pokud pushujete pole (t\u0159eba seznam produkt\u016f v ko\u0161\u00edku), recursive merge je m\u016f\u017ee rozb\u00edt zp\u016fsobem, kter\u00fd je t\u011b\u017ek\u00e9 debugovat. Doporu\u010duju:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Pole v\u017edy pushovat s <code>_clear: true<\/code>, nebo<\/li>\n\n\n\n<li>wrappovat je do nov\u00e9ho objektu, aby se p\u0159epsaly jako celek, nebo<\/li>\n\n\n\n<li>pou\u017e\u00edvat pro ka\u017ed\u00fd typ ud\u00e1losti v\u017edy vlastn\u00ed tag v GTM.<\/li>\n<\/ul>\n\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Jak to souvis\u00ed s kvalitou dat<\/h2>\n\n\n\n<p>Recursive merge je jeden z mechanism\u016f, kter\u00fdm mus\u00edte velmi dob\u0159e rozum\u011bt, abyste m\u011b\u0159ili spr\u00e1vn\u00e1 data. Pokud ho nezn\u00e1te, v GA4 reportech pak vid\u00edte podivn\u00e9 hodnoty \u2014 revenue se nes\u010d\u00edt\u00e1, produkty se duplikuj\u00ed, eventy nesou data z p\u0159edchoz\u00edch interakc\u00ed. P\u0159esn\u011b <a href=\"https:\/\/www.sabatka.net\/cs\/bugs-in-tracking-measurecamp-czechia-2025\/\">tento typ chyb jsem prezentoval na MeasureCamp<\/a> \u2014 tich\u00e9, bez erroru, ale s re\u00e1ln\u00fdm dopadem na data.<\/p>\n\n\n\n<p>Pokud \u0159e\u0161\u00edte <a href=\"https:\/\/www.sabatka.net\/cs\/data-quality-monitor-for-ga4\/\">kvalitu dat a monitoring m\u011b\u0159en\u00ed<\/a>, tohle je p\u0159esn\u011b typ probl\u00e9mu, kter\u00fd byste m\u011bli m\u00edt na radaru. Nen\u00ed to chyba v k\u00f3du, kter\u00e1 spadne s errorem. Je to chyba v datech, kter\u00e1 potichu zkresluje va\u0161e rozhodov\u00e1n\u00ed.<\/p>\n\n\n\n<p>A pokud va\u0161e firma pl\u00e1nuje vyu\u017e\u00edvat AI nad analytick\u00fdmi daty, pot\u0159ebujete <a href=\"https:\/\/www.sabatka.net\/cs\/5-levels-of-data-maturity\/\">datovou infrastrukturu, kter\u00e1 je na to p\u0159ipraven\u00e1<\/a>. Recursive merge probl\u00e9m v dataLayer je p\u0159esn\u011b ten typ \u201edrobnosti&#8220;, kter\u00e1 d\u011bl\u00e1 rozd\u00edl mezi daty, nad kter\u00fdmi jde tr\u00e9novat model, a daty, kter\u00e1 ho nau\u010d\u00ed blbosti.<\/p>\n\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Shrnut\u00ed<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>dataLayer pole a datov\u00fd model GTM jsou dv\u011b r\u016fzn\u00e9 v\u011bci.<\/li>\n\n\n\n<li>GTM d\u011bl\u00e1 recursive merge \u2014 vno\u0159en\u00e9 objekty se slu\u010duj\u00ed, ne p\u0159episuj\u00ed.<\/li>\n\n\n\n<li>Pole se merguj\u00ed po indexech, co\u017e vede k ne\u010dekan\u00fdm v\u00fdsledk\u016fm.<\/li>\n\n\n\n<li><code>_clear: true<\/code> resetuje root kl\u00ed\u010de v dan\u00e9m pushe \u2014 zabra\u0148uje recursive merge, ale nesah\u00e1 na ostatn\u00ed kl\u00ed\u010de.<\/li>\n\n\n\n<li>Na SPA je tohle kritick\u00e9. Na klasick\u00e9m webu to bol\u00ed u ud\u00e1lost\u00ed a e-commerce ud\u00e1lost\u00ed.<\/li>\n\n\n\n<li>Promyslete si architekturu dataLayer p\u0159edem \u2014 opravovat to zp\u011btn\u011b je drah\u00e9.<\/li>\n<\/ul>\n\n\n\n<p>Pokud si nejste jist\u00ed, jestli se v\u00e1m recursive merge probl\u00e9m net\u00fdk\u00e1, <a href=\"https:\/\/www.sabatka.net\/cs\/kontakt\/\">ozv\u011bte se mi<\/a> \u2014 projdeme va\u0161i dataLayer architekturu.<\/p>\n\n\n\n<div style=\"height:50px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button scroll_to_subscribe\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/www.sabatka.net\/cs\/kontakt\/\">Kontaktujte m\u011b<\/a><\/div>\n\n\n\n<div class=\"wp-block-button linkedinShare\"><a class=\"wp-block-button__link wp-element-button\">Sd\u00edlet na LinkedIN<\/a><\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>dataLayer je jednoduch\u00e9 javascriptov\u00e9 pole. Pushnu objekt, p\u0159e\u010dtu si ho v prom\u011bnn\u00e9 v Google Tag Manageru (GTM), hotovo. Na tom p\u0159ece nem\u016f\u017ee b\u00fdt nic slo\u017eit\u00e9ho. Jasn\u011b. Pokud navrhujete strukturu dataLayer a je\u0161t\u011b jste nesly\u0161eli o recursive merge, zva\u017ete, jestli chcete \u010d\u00edst d\u00e1le. Bude se v\u00e1m sp\u00e1t h\u016f\u0159. dataLayer vs. datov\u00fd model GTM \u2014 to nen\u00ed [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":922,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9,10],"tags":[],"class_list":["post-912","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-digitalni-analytika","category-gtm"],"_links":{"self":[{"href":"https:\/\/www.sabatka.net\/cs\/wp-json\/wp\/v2\/posts\/912","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sabatka.net\/cs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sabatka.net\/cs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sabatka.net\/cs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sabatka.net\/cs\/wp-json\/wp\/v2\/comments?post=912"}],"version-history":[{"count":21,"href":"https:\/\/www.sabatka.net\/cs\/wp-json\/wp\/v2\/posts\/912\/revisions"}],"predecessor-version":[{"id":947,"href":"https:\/\/www.sabatka.net\/cs\/wp-json\/wp\/v2\/posts\/912\/revisions\/947"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.sabatka.net\/cs\/wp-json\/wp\/v2\/media\/922"}],"wp:attachment":[{"href":"https:\/\/www.sabatka.net\/cs\/wp-json\/wp\/v2\/media?parent=912"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sabatka.net\/cs\/wp-json\/wp\/v2\/categories?post=912"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sabatka.net\/cs\/wp-json\/wp\/v2\/tags?post=912"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}