Skip to content

Object Variables

Object Variables

CoreCategory23 Variables

Modern dataLayers don’t push flat key-value pairs. They push deep JSON structures: ecommerce.items.0.price, user.profile.preferences.locale. GTM’s built-in DataLayer Variable handles dot-notation but throws “Cannot read property of undefined” the moment a single intermediate key is missing. Tag payloads need to be assembled, not just read. Object is the payload-shaping layer — 23 sandbox-safe variable templates for safe nested access, conditional payload assembly, deep merging, and key/value reshaping.

23 variables100% sandbox-safeWeb + ServerMIT licensed

Modern web stacks push complex JSON to the dataLayer. The dot-notation pattern works when every level exists. The moment a backend deploys a partial payload — user object missing on logged-out sessions, shipping missing on digital orders — the variable throws a runtime error, and your tag fires with the wrong shape.

Source — Analytics Mania on dataLayer Variables

”If the data is nested inside another object in the Data Layer (e.g., attributes: {pagePostAuthor: ’…’}), you must use dot notation in the GTM variable: attributes.pagePostAuthor.”

The Object category solves three problems:

  • Defensive nested access. Read deep paths safely, with undefined as the worst-case return value rather than thrown errors.
  • Tag payload composition. Build outbound payloads — Meta CAPI user_data, GA4 custom parameter blocks, server-side tag bodies — with conditional logic that decides which fields to include.
  • Object reshaping. Merge multiple sources, apply defaults to incomplete pushes, transform key formats between vendors.
Defensive access

Read deep paths without breaking

getValueByPath, pickNested, hasNested — read nested dataLayer properties safely. Worst case is undefined, never a thrown error.

Payload composition

Build the exact shape vendors require

Three generators. OBJECT Smart for conditional assembly. OBJECT Transformer for key-by-key reshaping. OBJECT From Arrays for zip-style construction.

Reshape & merge

Combine and adapt object shapes

assignObjects, mergeConcatDeep, assignDefaults. Combine user traits with session traits. Fill in missing keys without overwriting existing ones.

Twenty-five variables across two hero subgroups (generators, defensive access) plus supporting primitives.

The most common runtime error in any GTM container is “Cannot read property of undefined.” It happens when a variable expects ecommerce.items.0.price and a partial dataLayer push omits one of the intermediate keys.

The pattern that breaks: A backend pushes a cart-abandonment event without ecommerce. A GTM Custom JS variable accesses ecommerce.items.length — throws TypeError: Cannot read properties of undefined. The error blocks the tag from firing. Other tags that depended on this variable get cascade-blocked.

getValueByPath is the safe alternative. It walks the path step by step, returning undefined at the first missing key rather than throwing.

Recipe — Safely read a deeply nested price
Variable: getValueByPath · Direct or Apply mode
FieldValue
Source object{{Apply - getDataLayerCurrent}}
Pathecommerce.items.0.price
Returns 49.99 when the full path exists; undefined when any intermediate key is missing — never throws

Pair with falsyTo from the Value category to substitute a default when the path doesn’t exist:

getValueByPathApplyfalsyToDirect·0 (default)

Pick a subset of nested fields into a clean object

Section titled “Pick a subset of nested fields into a clean object”

Reading several nested paths into a new object — building a Meta CAPI user_data block from a sprawling user profile — is pickNested.

Recipe — Build user_data for Meta CAPI from a deep profile
Variable: pickNested · Direct or Apply mode
Source pathTarget key
user.contact.emailem
user.contact.phoneph
user.profile.firstNamefn
user.profile.lastNameln
user.address.cityct
user.address.countrycountry
Clean Meta-shaped {em, ph, fn, ln, ct, country} object — keys missing in source are absent in result

Build conditional tag payloads with the Smart generator

Section titled “Build conditional tag payloads with the Smart generator”

⚡ OBJECT › Smart packages conditional payload assembly into three property modes:

  • Fixed properties — always included, regardless of state.
  • Conditional properties — included only when a global condition evaluates true.
  • Rule-based properties — each property has its own individual condition.
Recipe — Conditional GA4 event parameters with consent-aware fields
Variable: ⚡ OBJECT › Smart · Direct mode
ModePropertyValue / Condition
Fixedpage_type{{DL - page_type}}
Fixedcurrency”EUR”
Rule-baseduser_idIf {{isGrantedAnalyticsStorage}}
Rule-basedcustomer_lifetime_valueIf {{isGrantedAdUserData}}
Rule-basedexperiment_variantIf {{hasNested experiment.variant}}
Single object output containing fixed fields plus per-rule fields when each condition is met

Cross-category composition. The conditions in rule-based mode can reference any predicate from Logic or any boolean variable elsewhere in the framework.

Recipe — Combine user, session, and event traits into a single object
Variable: assignObjects · Direct or Apply mode
SlotSource
Object 1 (lowest priority){{Apply - getPersistedDataLayerValue user_traits}}
Object 2 (middle priority){{Apply - getGA4SessionDataLayerValue session_traits}}
Object 3 (highest priority){{DL - event_traits}}
Merged object where event-level keys win on conflict

Deep-merge nested objects without overwriting branches

Section titled “Deep-merge nested objects without overwriting branches”

Shallow merge has a subtle failure mode. Two sources both have a user key with different nested fields. assignObjects takes the second one wholesale — id and email from source A are gone. mergeConcatDeep recursively merges at every level, preserving all keys from both sources.

Apply default values to incomplete payloads

Section titled “Apply default values to incomplete payloads”
Recipe — Apply GA4 ecommerce defaults to a partial event
Variable: assignDefaults · Direct or Apply mode
FieldValue
Target{{DL - ecommerce}} (whatever the backend pushed)
Defaults{ currency: “EUR”, value: 0, items: [] }
Currency defaults to EUR if missing; value defaults to 0; items defaults to empty array — but pushed values pass through unchanged

Transform every key or value with the Transformer

Section titled “Transform every key or value with the Transformer”
Recipe — Reshape user object for Meta CAPI’s short keys
Variable: ⚡ OBJECT › Transformer (Advanced) · Direct mode
Source keyTarget keyApply transform
emailem{{Apply - normalizeEmail → hashSHA256}}
phoneph{{Apply - normalizePhone → hashSHA256}}
firstNamefn{{Apply - trim → toLowerCase → hashSHA256}}
lastNameln{{Apply - trim → toLowerCase → hashSHA256}}
Object reshaped to Meta’s exact field names with values normalized and hashed in one pass

Parse JSON strings from cookies and storage

Section titled “Parse JSON strings from cookies and storage”
Recipe — Parse a CMP consent state from a cookie
Variables: getCookieValue (Apply) → parseJsonString (Direct)
FieldValue
Cookie namecmp_consent
Cookie raw value’{“analytics”:true,“marketing”:false}’
{ analytics: true, marketing: false } as an actual object

Build objects from arrays of keys and values

Section titled “Build objects from arrays of keys and values”
Recipe — Build an object from parallel arrays of keys and values
Variable: zipObject · Direct or Apply mode
FieldValue
Keys[“name”, “email”, “company”]
Values[“Jane Doe”, “[email protected]”, “Acme Inc”]
{ name: “Jane Doe”, email: “[email protected]”, company: “Acme Inc” }

Test for key existence before using values

Section titled “Test for key existence before using values”
  • has — does a top-level key exist? Use for shallow gates.
  • hasNested — does a deep dot-notation path exist all the way down?
  • hasKeyEqualTo — does a key exist and equal a specific value?

Convert between objects and key-value pair arrays

Section titled “Convert between objects and key-value pair arrays”
  • getKeys returns just the keys as an array.
  • values returns just the values as an array.
  • entries returns [[key, value], [key, value]] nested arrays.
  • toObjectPairs returns [{key, value}, {key, value}] objects — works with the Items category.
  • zipObject and assignObjectsFromPairs rebuild objects from these intermediate shapes.

Defensive deep read with default

Read a deep path safely, substitute a default when missing.

getValueByPathApplyfalsyToDirect

Layered traits assembly

User traits, session traits, event traits — merged with later sources winning on conflict.

user_traits+session_traits+event_traitsassignObjectsDirectassignDefaultsDirect

Vendor-specific payload reshape

Pick relevant nested fields, reshape keys to vendor convention, normalize values.

pickNestedApply⚡ OBJECT › TransformerDirect
GoalVariableMode
Build conditional payload (fixed + conditional + rule-based)⚡ OBJECT › SmartDirect
Reshape keys with per-key transforms⚡ OBJECT › Transformer (Advanced)Direct
Build object from keys and values arrays⚡ OBJECT › From ArraysDirect / Apply
Read deep path safelygetValueByPathDirect / Apply
Read top-level keygetValueDirect / Apply
Pick multiple nested paths into clean objectpickNestedDirect / Apply
Test deep path existencehasNestedDirect
Test top-level key existencehasDirect
Test key exists AND equals valuehasKeyEqualToDirect
Pick / omit top-level keyspick / omitDirect / Apply
Add or update single propertysetDirect / Apply
Shallow merge (later wins)assignObjectsDirect / Apply
Deep merge with array concatenationmergeConcatDeepDirect / Apply
Fill missing keys onlyassignDefaults / assignDefaultsDeepDirect / Apply
Get keys / values / entriesgetKeys / values / entriesDirect / Apply
Convert to / from key-value pair arraystoObjectPairs / zipObjectDirect / Apply
Parse JSON string into objectparseJsonStringDirect / Apply
Apply function to each propertyapplyFromObjectDirect / Apply

How do I safely access a nested dataLayer property in GTM?

Use getValueByPath with a dot-notation path. Returns undefined when any intermediate key is missing rather than throwing. For multiple nested fields, use pickNested to extract a subset of paths into a clean object.

How do I build a conditional payload for Meta CAPI or GA4?

Use ⚡ OBJECT › Smart. Three property modes: fixed (always added), conditional (added when a global condition is true), rule-based (each property has its own condition).

How do I merge user traits and session traits into one object?

assignObjects merges shallowly with later values winning. For deep nested structures use mergeConcatDeep. assignDefaults handles the inverse: fill missing keys only.

How do I check if a dataLayer key exists before using it?

has for top-level, hasNested for deep paths, hasKeyEqualTo for both presence and a specific value. Each returns a boolean for trigger conditions.

How do I transform every key or value of an object?

Use ⚡ OBJECT › Transformer (Advanced) for key-by-key transformation with arbitrary per-key logic. For uniform transformations get keys with getKeys, transform with Array’s map, rebuild with zipObject.

How do I parse a JSON string from a cookie into an object?

parseJsonString safely parses JSON-formatted strings. Returns undefined on malformed input rather than throwing.

Are these variables sandbox-safe in server-side GTM?

Yes. All templates run inside GTM’s sandboxed JavaScript environment. Object variables are particularly valuable in sGTM where reshaping incoming event payloads to match destination shapes is the main job.