{"id":13135,"date":"2026-09-22T07:35:00","date_gmt":"2026-09-22T05:35:00","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/?p=13135"},"modified":"2026-10-26T13:26:41","modified_gmt":"2026-10-26T12:26:41","slug":"tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables","status":"publish","type":"post","link":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\/","title":{"rendered":"Tutorial: Turning a Nested dataLayer Object Into Durable GTM Variables"},"content":{"rendered":"<p>A data layer variable in Google Tag Manager (GTM) can return a number, a string, an object or an entire array. Dot notation selects a value inside nested data. The important distinction is between a field name and an array position: <code>items.0<\/code> means the first item, not a particular product.<\/p>\n<p>Durable variables need a documented data structure, complete event payloads and checks for missing values. An index is useful when position is the intended meaning; product identity requires an identifier.<\/p>\n<figure class=\"lw-diagram\"><img src=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/diagrams\/quality-13135-20261024.png\" width=\"1120\" height=\"580\" decoding=\"async\" loading=\"lazy\" alt=\"Named paths select fields; numeric indices select positions. The whole items array avoids a fixed product count.\"><figcaption>Named paths select fields; numeric indices select positions. The whole items array avoids a fixed product count.<\/figcaption><\/figure>\n<h2>A complete add_to_cart event<\/h2>\n<p>The example adds two chairs and one table in a single action. The event contains those newly added items, rather than the whole existing cart. The value is <code>64.95 \u00d7 2 + 219.00 \u00d7 1 = 348.90<\/code>, excluding shipping and tax. Currency is required when a value is supplied.<\/p>\n<figure style=\"--cbb-digits:2\" class=\"cbb cbb--wrap cbb--numbers wp-block-code-beautifier-block-code\" data-lang=\"javascript\"><figcaption class=\"cbb-head\"><span class=\"cbb-lang\">JavaScript<\/span><span class=\"cbb-actions\"><button type=\"button\" class=\"cbb-button cbb-button--wrap\" data-cbb-action=\"wrap\" aria-pressed=\"true\" title=\"Wrap long lines\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M2 4h12M2 8h9.5a2.5 2.5 0 0 1 0 5H8m0 0 1.5-1.5M8 13l1.5 1.5M2 12h3\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg><span class=\"cbb-sr\">Wrap long lines<\/span><\/button><button type=\"button\" class=\"cbb-button cbb-button--copy\" data-cbb-action=\"copy\" data-cbb-done=\"Copied\" data-cbb-failed=\"Press Ctrl+C to copy\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><rect x=\"5.5\" y=\"5.5\" width=\"8\" height=\"8.5\" rx=\"1.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><path d=\"M10.5 3.5V3A1.5 1.5 0 0 0 9 1.5H4A1.5 1.5 0 0 0 2.5 3v6.5A1.5 1.5 0 0 0 4 11h.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><\/svg><span class=\"cbb-button-label\" aria-live=\"polite\">Copy<\/span><\/button><\/span><\/figcaption><pre class=\"cbb-pre\" tabindex=\"0\"><code class=\"cbb-code language-javascript\" style=\"counter-reset:cbb-line 0;\"><span class=\"cbb-line\">window.dataLayer = window.dataLayer || &#91;&#93;;\n<\/span><span class=\"cbb-line\">dataLayer.<span class=\"cbb-function\">push<\/span>({ ecommerce: <span class=\"cbb-constant\">null<\/span> });\n<\/span><span class=\"cbb-line\">dataLayer.<span class=\"cbb-function\">push<\/span>({\n<\/span><span class=\"cbb-line\">  event: <span class=\"cbb-string\">\"add_to_cart\"<\/span>,\n<\/span><span class=\"cbb-line\">  ecommerce: {\n<\/span><span class=\"cbb-line\">    currency: <span class=\"cbb-string\">\"EUR\"<\/span>,\n<\/span><span class=\"cbb-line\">    value: <span class=\"cbb-number\">348.90<\/span>,\n<\/span><span class=\"cbb-line\">    items: &#91;\n<\/span><span class=\"cbb-line\">      { item_id: <span class=\"cbb-string\">\"SKU-42\"<\/span>, item_name: <span class=\"cbb-string\">\"Chair\"<\/span>, price: <span class=\"cbb-number\">64.95<\/span>, quantity: <span class=\"cbb-number\">2<\/span>,\n<\/span><span class=\"cbb-line\">        item_category: <span class=\"cbb-string\">\"Furniture\"<\/span>, index: <span class=\"cbb-number\">0<\/span> },\n<\/span><span class=\"cbb-line\">      { item_id: <span class=\"cbb-string\">\"SKU-77\"<\/span>, item_name: <span class=\"cbb-string\">\"Table\"<\/span>, price: <span class=\"cbb-number\">219.00<\/span>, quantity: <span class=\"cbb-number\">1<\/span>,\n<\/span><span class=\"cbb-line\">        item_category: <span class=\"cbb-string\">\"Furniture\"<\/span>, index: <span class=\"cbb-number\">1<\/span> }\n<\/span><span class=\"cbb-line\">    &#93;\n<\/span><span class=\"cbb-line\">  },\n<\/span><span class=\"cbb-line\">  user: { logged_in: <span class=\"cbb-constant\">true<\/span>, segment: <span class=\"cbb-string\">\"b2b\"<\/span> }\n<\/span><span class=\"cbb-line\">});<\/span><\/code><\/pre><\/figure>\n<p>The initialization preserves an existing queue. Clearing <code>ecommerce<\/code> prevents old fields from leaking into this complete payload. The event name and related data belong in the same push. <code>user.segment<\/code> is an example of separate application state; a push alone does not configure a GA4 user property.<\/p>\n<h2>Reading nested fields with version 2<\/h2>\n<p>A Data Layer Variable named <code>DLV - ecommerce.currency<\/code>, with Data Layer Variable Name <code>ecommerce.currency<\/code> and version 2, returns <code>EUR<\/code>. The display name is arbitrary; the configured path determines the value. Further variables can use <code>ecommerce.value<\/code>, <code>ecommerce.items<\/code> and <code>ecommerce<\/code>. The last two return an array and an object, respectively.<\/p>\n<p>Version 1 treats dots as literal characters in a key. Version 2 interprets dots as nested structure and can also expand dotted keys such as <code>{\"page.type\":\"pdp\"}<\/code>. A literal dotted key therefore does not automatically require version 1. Consistent nested objects avoid ambiguous mixtures of dotted keys and object properties.<\/p>\n<p>Names are case-sensitive. A missing path without a configured default returns <code>undefined<\/code>. The resulting behavior depends on the tag and how it converts values into the outgoing request: a parameter may be omitted or converted, or custom code may fail. A missing value does not guarantee an empty parameter or a particular reporting difference.<\/p>\n<h2>Position is different from identity<\/h2>\n<table><thead><tr><th>Path<\/th><th>Meaning<\/th><\/tr><\/thead><tbody><tr><td><code>ecommerce.currency<\/code><\/td><td>Event currency<\/td><\/tr><tr><td><code>ecommerce.value<\/code><\/td><td>Event value<\/td><\/tr><tr><td><code>user.segment<\/code><\/td><td>Application segment<\/td><\/tr><tr><td><code>ecommerce.items<\/code><\/td><td>Whole item array<\/td><\/tr><tr><td><code>ecommerce.items.0.item_id<\/code><\/td><td>ID of the first item<\/td><\/tr><tr><td><code>ecommerce.items.1.price<\/code><\/td><td>Price of the second item; absent with only one item<\/td><\/tr><\/tbody><\/table>\n<p>A named path remains useful only while the schema and event data remain consistent. An index path remains correct when the requirement is \u201cthe first item\u201d; a change in order changes the product at that position. A product-specific lookup should search by <code>item_id<\/code>. The whole <code>ecommerce.items<\/code> array is normally the suitable input for GA4 ecommerce, with no custom mapping required when the source already follows the expected schema.<\/p>\n<h2>Message queue and merged model<\/h2>\n<p><code>window.dataLayer<\/code> is an array of queued messages. GTM processes messages and maintains an internal data model. Version 2 can merge objects and arrays at every nested level: omitted fields or trailing items can survive from earlier messages. A shorter array does not reliably clear earlier entries.<\/p>\n<p>Google&#8217;s GTM ecommerce examples clear the previous ecommerce object with <code>dataLayer.push({ecommerce:null})<\/code> before sending a complete event. This pattern fits the example above. Integrations deliberately building state across several messages need a coordinated reset and payload design; blindly clearing an incomplete payload can remove required data.<\/p>\n<h2>Optional validation without invented defaults<\/h2>\n<p>The following Custom JavaScript variable, named <code>JS - ecommerce valid<\/code>, reads a version-2 Data Layer Variable named <code>DLV - ecommerce<\/code>. The function returns a boolean and leaves the source untouched.<\/p>\n<p>The example contract is intentionally strict: EUR, numeric nonnegative prices and values, positive whole-number quantities, and a nonempty string in at least one of <code>item_id<\/code> or <code>item_name<\/code>. Every supplied identifier or name must be a nonempty string. GA4 also accepts an item with only a name; an ID is not universally mandatory. GA4 defaults an omitted quantity to 1, but this example requires an explicit quantity to expose missing shop data.<\/p>\n<figure style=\"--cbb-digits:2\" class=\"cbb cbb--wrap cbb--numbers wp-block-code-beautifier-block-code\" data-lang=\"javascript\"><figcaption class=\"cbb-head\"><span class=\"cbb-lang\">JavaScript<\/span><span class=\"cbb-actions\"><button type=\"button\" class=\"cbb-button cbb-button--wrap\" data-cbb-action=\"wrap\" aria-pressed=\"true\" title=\"Wrap long lines\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><path d=\"M2 4h12M2 8h9.5a2.5 2.5 0 0 1 0 5H8m0 0 1.5-1.5M8 13l1.5 1.5M2 12h3\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg><span class=\"cbb-sr\">Wrap long lines<\/span><\/button><button type=\"button\" class=\"cbb-button cbb-button--copy\" data-cbb-action=\"copy\" data-cbb-done=\"Copied\" data-cbb-failed=\"Press Ctrl+C to copy\"><svg aria-hidden=\"true\" focusable=\"false\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"><rect x=\"5.5\" y=\"5.5\" width=\"8\" height=\"8.5\" rx=\"1.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><path d=\"M10.5 3.5V3A1.5 1.5 0 0 0 9 1.5H4A1.5 1.5 0 0 0 2.5 3v6.5A1.5 1.5 0 0 0 4 11h.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"\/><\/svg><span class=\"cbb-button-label\" aria-live=\"polite\">Copy<\/span><\/button><\/span><\/figcaption><pre class=\"cbb-pre\" tabindex=\"0\"><code class=\"cbb-code language-javascript\" style=\"counter-reset:cbb-line 0;\"><span class=\"cbb-line\"><span class=\"cbb-keyword\">function<\/span> () {\n<\/span><span class=\"cbb-line\">  <span class=\"cbb-keyword\">var<\/span> e = {{DLV - ecommerce}};\n<\/span><span class=\"cbb-line\">  <span class=\"cbb-keyword\">function<\/span> <span class=\"cbb-function\">number<\/span>(x) { <span class=\"cbb-keyword\">return<\/span> <span class=\"cbb-keyword\">typeof<\/span> x === <span class=\"cbb-string\">\"number\"<\/span> &amp;&amp; <span class=\"cbb-function\">isFinite<\/span>(x); }\n<\/span><span class=\"cbb-line\">  <span class=\"cbb-keyword\">function<\/span> <span class=\"cbb-function\">text<\/span>(x) { <span class=\"cbb-keyword\">return<\/span> <span class=\"cbb-keyword\">typeof<\/span> x === <span class=\"cbb-string\">\"string\"<\/span> &amp;&amp; x.<span class=\"cbb-function\">trim<\/span>() !== <span class=\"cbb-string\">\"\"<\/span>; }\n<\/span><span class=\"cbb-line\">  <span class=\"cbb-keyword\">if<\/span> (!e || e.currency !== <span class=\"cbb-string\">\"EUR\"<\/span> || !<span class=\"cbb-function\">number<\/span>(e.value) || e.value &lt; <span class=\"cbb-number\">0<\/span> ||\n<\/span><span class=\"cbb-line\">      !<span class=\"cbb-type\">Array<\/span>.<span class=\"cbb-function\">isArray<\/span>(e.items) || !e.items.length) { <span class=\"cbb-keyword\">return<\/span> <span class=\"cbb-constant\">false<\/span>; }\n<\/span><span class=\"cbb-line\">  <span class=\"cbb-keyword\">var<\/span> sum = <span class=\"cbb-number\">0<\/span>;\n<\/span><span class=\"cbb-line\">  <span class=\"cbb-keyword\">for<\/span> (<span class=\"cbb-keyword\">var<\/span> i = <span class=\"cbb-number\">0<\/span>; i &lt; e.items.length; i++) {\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-keyword\">var<\/span> a = e.items&#91;i&#93;;\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-keyword\">if<\/span> (!a || <span class=\"cbb-keyword\">typeof<\/span> a !== <span class=\"cbb-string\">\"object\"<\/span> || <span class=\"cbb-type\">Array<\/span>.<span class=\"cbb-function\">isArray<\/span>(a)) { <span class=\"cbb-keyword\">return<\/span> <span class=\"cbb-constant\">false<\/span>; }\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-keyword\">if<\/span> (!<span class=\"cbb-function\">text<\/span>(a.item_id) &amp;&amp; !<span class=\"cbb-function\">text<\/span>(a.item_name)) { <span class=\"cbb-keyword\">return<\/span> <span class=\"cbb-constant\">false<\/span>; }\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-keyword\">if<\/span> (a.item_id !== <span class=\"cbb-constant\">undefined<\/span> &amp;&amp; !<span class=\"cbb-function\">text<\/span>(a.item_id)) { <span class=\"cbb-keyword\">return<\/span> <span class=\"cbb-constant\">false<\/span>; }\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-keyword\">if<\/span> (a.item_name !== <span class=\"cbb-constant\">undefined<\/span> &amp;&amp; !<span class=\"cbb-function\">text<\/span>(a.item_name)) { <span class=\"cbb-keyword\">return<\/span> <span class=\"cbb-constant\">false<\/span>; }\n<\/span><span class=\"cbb-line\">    <span class=\"cbb-keyword\">if<\/span> (!<span class=\"cbb-function\">number<\/span>(a.price) || a.price &lt; <span class=\"cbb-number\">0<\/span> ||\n<\/span><span class=\"cbb-line\">        !<span class=\"cbb-function\">number<\/span>(a.quantity) || a.quantity &lt;= <span class=\"cbb-number\">0<\/span> ||\n<\/span><span class=\"cbb-line\">        <span class=\"cbb-type\">Math<\/span>.<span class=\"cbb-function\">floor<\/span>(a.quantity) !== a.quantity) { <span class=\"cbb-keyword\">return<\/span> <span class=\"cbb-constant\">false<\/span>; }\n<\/span><span class=\"cbb-line\">    sum += a.price * a.quantity;\n<\/span><span class=\"cbb-line\">  }\n<\/span><span class=\"cbb-line\">  <span class=\"cbb-keyword\">return<\/span> <span class=\"cbb-function\">isFinite<\/span>(sum) &amp;&amp; <span class=\"cbb-type\">Math<\/span>.<span class=\"cbb-function\">abs<\/span>(sum - e.value) &lt; <span class=\"cbb-number\">0.005<\/span>;\n<\/span><span class=\"cbb-line\">}<\/span><\/code><\/pre><\/figure>\n<p>The comparison allows less than half a euro cent of floating-point difference. This is an example check for EUR, not a universal currency, discount or tax model. Free items with a genuine numeric price of 0 remain valid. Strings such as <code>\"64.95\"<\/code>, malformed prices and zero quantities fail instead of silently becoming 0 or 1. Optional item fields remain available because the array is not rebuilt.<\/p>\n<p>For the GA4 <code>add_to_cart<\/code> tag, a Custom Event trigger uses event name <code>add_to_cart<\/code> and the additional condition <code>{{JS - ecommerce valid}}<\/code> equals <code>true<\/code>. Event parameters map <code>currency<\/code>, <code>value<\/code> and <code>items<\/code> to the corresponding version-2 variables. The guard must be attached to the actual sending tag; merely returning <code>undefined<\/code> from a different variable does not stop a tag. Other triggers must not bypass the check.<\/p>\n<h2>Checking the selected event<\/h2>\n<p>In GTM preview, the same selected event provides three complementary views: the original message, the resulting data layer state and the resolved variables. Additional model fields can be intentional persistent state, not automatically a defect. Missing results can arise from timing, a clear, a wrong version, spelling or custom validation.<\/p>\n<p>A useful test sequence covers two items, one item, changed order, a free item, a name-only item and malformed input. After a second shorter event, old products must not remain. The tag must fire once for valid input and remain blocked for invalid input. Tag Assistant and the outgoing GA4 request then verify the configured mapping; a unit test of the function alone cannot verify the container.<\/p>\n<div class=\"lw-faq\"><h2>Questions and answers<\/h2><h3>What happens to a price with a decimal comma?<\/h3><p>The validator rejects text, including <code>\"64,95\"<\/code>. Numeric prices at the source are preferable. Any conversion of localized text requires a known locale and explicit validation; deleting dots indiscriminately would turn an English decimal price into a different amount. The expression <code>Number(value) || 0<\/code> conceals invalid input and should not supply a financial default.<\/p><h3>Should the custom variable push another message?<\/h3><p>No. Variable evaluation can occur more than once. A pure function reads input and returns a result without modifying the queue or its items. A push inside a variable can create unexpected events or loops.<\/p><\/div>\n<div class=\"lw-quellen\">\n<h2>Sources<\/h2>\n<ul>\n<li><a href=\"https:\/\/developers.google.com\/tag-platform\/tag-manager\/datalayer\" target=\"_blank\" rel=\"noopener noreferrer\">The data layer<\/a><\/li>\n<li><a href=\"https:\/\/developers.google.com\/tag-platform\/tag-manager\" target=\"_blank\" rel=\"noopener noreferrer\">Google Tag Manager documentation<\/a><\/li>\n<li><a href=\"https:\/\/support.google.com\/tagmanager\/answer\/7683362?hl=en\" target=\"_blank\" rel=\"noopener noreferrer\">GTM variable types<\/a><\/li><li><a href=\"https:\/\/developers.google.com\/analytics\/devguides\/collection\/ga4\/ecommerce?client_type=gtm\" target=\"_blank\" rel=\"noopener noreferrer\">GA4 ecommerce with GTM<\/a><\/li><li><a href=\"https:\/\/developers.google.com\/analytics\/devguides\/collection\/ga4\/reference\/events?hl=en\" target=\"_blank\" rel=\"noopener noreferrer\">GA4 event reference<\/a><\/li><li><a href=\"https:\/\/github.com\/google\/data-layer-helper\" target=\"_blank\" rel=\"noopener noreferrer\">Google Data Layer Helper: data model and merging<\/a><\/li><\/ul>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Nested dataLayer values can be read directly with version-2 variables. A complete ecommerce example explains array positions, merged state and optional validation without invented prices or quantities.<\/p>\n","protected":false},"author":1,"featured_media":28503,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[113],"tags":[91267,91312,91516,91219],"class_list":["post-13135","post","type-post","status-publish","format-standard","hentry","category-tutorials","tag-google-tag-manager","tag-javascript","tag-tracking","tag-tutorial"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Tutorial: Turning a Nested dataLayer Object Into Durable GTM Variables | Lukas Wojcik<\/title>\n<meta name=\"description\" content=\"Reading nested pushes with dot notation, telling stable paths from index-dependent ones, and the merge that makes an old ecommerce object reappear.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Tutorial: Turning a Nested dataLayer Object Into Durable GTM Variables | Lukas Wojcik\" \/>\n<meta property=\"og:description\" content=\"Reading nested pushes with dot notation, telling stable paths from index-dependent ones, and the merge that makes an old ecommerce object reappear.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-09-22T05:35:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-26T12:26:41+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/10\/quality-hero-13135-20261024.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Lukas Wojcik\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Lukas Wojcik\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\\\/\"},\"author\":{\"name\":\"Lukas Wojcik\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"headline\":\"Tutorial: Turning a Nested dataLayer Object Into Durable GTM Variables\",\"datePublished\":\"2026-09-22T05:35:00+00:00\",\"dateModified\":\"2026-10-26T12:26:41+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\\\/\"},\"wordCount\":990,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"image\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/lw-flux3-20261031\\\/hero-13135.png\",\"keywords\":[\"Google Tag Manager\",\"JavaScript\",\"Tracking\",\"Tutorial\"],\"articleSection\":[\"Tutorials\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\\\/\",\"name\":\"Tutorial: Turning a Nested dataLayer Object Into Durable GTM Variables | Lukas Wojcik\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/lw-flux3-20261031\\\/hero-13135.png\",\"datePublished\":\"2026-09-22T05:35:00+00:00\",\"dateModified\":\"2026-10-26T12:26:41+00:00\",\"description\":\"Reading nested pushes with dot notation, telling stable paths from index-dependent ones, and the merge that makes an old ecommerce object reappear.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/lw-flux3-20261031\\\/hero-13135.png\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/lw-flux3-20261031\\\/hero-13135.png\",\"width\":1200,\"height\":630,\"caption\":\"Tutorial: Turning a Nested dataLayer Object Into Durable GTM Variables\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-analytics\\\/tutorials\\\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Tutorial: Turning a Nested dataLayer Object Into Durable GTM Variables\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\",\"name\":\"Lukas Wojcik - Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\",\"name\":\"Lukas Wojcik\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"width\":424,\"height\":636,\"caption\":\"Lukas Wojcik\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\"},\"sameAs\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Tutorial: Turning a Nested dataLayer Object Into Durable GTM Variables | Lukas Wojcik","description":"Reading nested pushes with dot notation, telling stable paths from index-dependent ones, and the merge that makes an old ecommerce object reappear.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\/","og_locale":"en_US","og_type":"article","og_title":"Tutorial: Turning a Nested dataLayer Object Into Durable GTM Variables | Lukas Wojcik","og_description":"Reading nested pushes with dot notation, telling stable paths from index-dependent ones, and the merge that makes an old ecommerce object reappear.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\/","og_site_name":"Lukas Wojcik - Blog","article_published_time":"2026-09-22T05:35:00+00:00","article_modified_time":"2026-10-26T12:26:41+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/10\/quality-hero-13135-20261024.png","type":"image\/png"}],"author":"Lukas Wojcik","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Lukas Wojcik","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\/#article","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\/"},"author":{"name":"Lukas Wojcik","@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"headline":"Tutorial: Turning a Nested dataLayer Object Into Durable GTM Variables","datePublished":"2026-09-22T05:35:00+00:00","dateModified":"2026-10-26T12:26:41+00:00","mainEntityOfPage":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\/"},"wordCount":990,"commentCount":0,"publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"image":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\/#primaryimage"},"thumbnailUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/lw-flux3-20261031\/hero-13135.png","keywords":["Google Tag Manager","JavaScript","Tracking","Tutorial"],"articleSection":["Tutorials"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\/","url":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\/","name":"Tutorial: Turning a Nested dataLayer Object Into Durable GTM Variables | Lukas Wojcik","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\/#primaryimage"},"image":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\/#primaryimage"},"thumbnailUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/lw-flux3-20261031\/hero-13135.png","datePublished":"2026-09-22T05:35:00+00:00","dateModified":"2026-10-26T12:26:41+00:00","description":"Reading nested pushes with dot notation, telling stable paths from index-dependent ones, and the merge that makes an old ecommerce object reappear.","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\/#primaryimage","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/lw-flux3-20261031\/hero-13135.png","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/lw-flux3-20261031\/hero-13135.png","width":1200,"height":630,"caption":"Tutorial: Turning a Nested dataLayer Object Into Durable GTM Variables"},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-analytics\/tutorials\/tutorial-turning-a-nested-datalayer-object-into-durable-gtm-variables\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.lukaswojcik.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Tutorial: Turning a Nested dataLayer Object Into Durable GTM Variables"}]},{"@type":"WebSite","@id":"https:\/\/www.lukaswojcik.com\/blog\/#website","url":"https:\/\/www.lukaswojcik.com\/blog\/","name":"Lukas Wojcik - Blog","description":"","publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.lukaswojcik.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9","name":"Lukas Wojcik","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","width":424,"height":636,"caption":"Lukas Wojcik"},"logo":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg"},"sameAs":["https:\/\/www.lukaswojcik.com\/blog"]}]}},"_links":{"self":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/13135","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/comments?post=13135"}],"version-history":[{"count":5,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/13135\/revisions"}],"predecessor-version":[{"id":27379,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/13135\/revisions\/27379"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media\/28503"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=13135"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/categories?post=13135"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=13135"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}