Array Variables
Array Variables
A user’s tags arrive as [“sports”, “premium”, “subscriber”]. A DOM scrape returns an array of element IDs. A backend pushes a list of consent purposes. GTM’s native trigger conditions don’t natively understand array containment — there’s no “fire when tags include any of these values” option. Array is the functional layer the rest of the framework runs on — 31 sandbox-safe variable templates for containment tests, array reshaping, slicing, and the higher-order functions (map, filter, reduce) that other categories’ Apply chains compose against.
Why this category exists
Section titled “Why this category exists”Arrays show up in three places in a GTM container, and GTM’s built-in tooling doesn’t handle any of them well:
- Trigger conditions on array contents. Sites push
dataLayer.user_tags = [“premium”, “subscriber”], then need to fire a tag when one of a list of values is present. GTM’s nativecontainsoperator matches the array’s stringified form — which breaks on partial matches and offers no AND/OR semantics across multiple values. - DOM scraping returns arrays.
querySelectorAlland similar APIs return collections that need to be filtered, deduplicated, mapped, or counted before being sent to a tag. - Tag parameters expect array shapes. Some destinations want their input as an array — Meta CAPI’s user-data fields, custom GA4 parameters, server-side tag payloads. Building those arrays from individual variables is a Custom JavaScript pattern in every container.
Beyond the direct GTM use cases, the category serves a deeper architectural role: the higher-order functions are the mechanism that powers Apply chains across the framework. When the URL Transformer applies a function to query parameters, it’s iterating over an array with map. When Items filters by a property, it’s using filterArray. The Array category is the functional toolkit other categories compose against.
Three jobs: containment, reshaping, functional
Section titled “Three jobs: containment, reshaping, functional”Fire tags based on array contents
includesAll, includesAny, includesNone — boolean tests for trigger conditions on array values. The clean answer to “fire when user has any of these tags.”
Make arrays the shape downstream needs
Construct, deduplicate, flatten, sort, slice. Take DOM-scraped or dataLayer arrays and produce the exact shape a tag’s parameter requires.
map, filter, reduce as named templates
The higher-order functions that JavaScript developers reach for daily. Available as composable, sandbox-safe variables that other categories’ Apply chains use under the hood.
The variables — at a glance
Section titled “The variables — at a glance”Thirty-one variables, with the containment tests as the hero group.
Fire tags based on array contents
Section titled “Fire tags based on array contents”The most direct GTM use case. A site pushes user attributes as an array — content tags, audience segments, consent purposes — and you need to fire a tag conditionally based on whether specific values are present.
GTM’s native contains operator on a Data Layer Variable matches the array’s stringified form. It fails on partial matches (a value of “sport” would also match [“sports”]), can’t express AND/OR semantics across multiple values, and doesn’t behave correctly when the dataLayer pushes a JavaScript array object.
| Field | Value |
|---|---|
| Array input | {{DL - user_tags}} |
| Lookup values | [“premium”, “vip”, “enterprise”, “founder”] |
true when the user’s tags include any of the listed valuesThe three containment variables cover the three semantic cases. includesAll for compound qualification. includesNone for blocklists. includesAny for the most common any-of-list matching.
Why this matters for consent. Consent management platforms typically push arrays of granted purposes — [“analytics”, “advertising”, “personalization”]. Firing a tag only when consent for “advertising” is granted is exactly an includesAny with [“advertising”] as the lookup.
Build arrays from individual values
Section titled “Build arrays from individual values”Some tag destinations expect array-shaped parameters even when the source values are individual fields. The constructors handle the assembly job.
| Slot | Value |
|---|---|
| Input 1 | {{Apply - normalizePhone on primary_phone}} |
| Input 2 | {{Apply - normalizePhone on secondary_phone}} |
| Input 3 | {{Apply - normalizePhone on work_phone}} |
user_data.ph on a CAPI tagReshape DOM-scraped and dataLayer arrays
Section titled “Reshape DOM-scraped and dataLayer arrays”Arrays from outside the framework arrive in the wrong shape constantly. Four reshaping primitives cover the common needs.
| Field | Value |
|---|---|
| Input | [null, “sku-001”, “sku-002”, “sku-001”, "", “sku-003”] |
| After compact | [“sku-001”, “sku-002”, “sku-001”, “sku-003”] |
| After uniq | [“sku-001”, “sku-002”, “sku-003”] |
Slice and paginate large arrays
Section titled “Slice and paginate large arrays”Some arrays are too large to send wholesale. GA4 limits event parameters. Server-side tag payloads often have JSON size limits.
| Field | Value |
|---|---|
| Input array | {{DL - search_results}} (could be 100+ items) |
| N | 10 |
Aggregate arrays into single values
Section titled “Aggregate arrays into single values”| Field | Value |
|---|---|
| Input array | [“sports”, “premium”, “subscriber”] |
| Separator | , (or {{space}}, or any delimiter) |
“sports,premium,subscriber” — ready as a GA4 custom dimension valueevery and some are boolean aggregations: every item satisfies a predicate, or at least one does. Use as trigger conditions when you need “fire only if every item in the cart is discount-applicable” or “fire if any item triggered a stockout warning.”
Search arrays by value or pattern
Section titled “Search arrays by value or pattern”findreturns the first item matching a predicate.indexOfreturns the index of a value’s first occurrence, or-1.lastIndexOffor the last occurrence.findIndexByCallbackandfindIndexByRegexfor index-based search by predicate or pattern.
| Field | Value |
|---|---|
| Input array | {{DL - ecommerce.items}} |
| Predicate | {{Apply - itemHasProperty discount > 0}} |
-1Map, filter, reduce as named templates
Section titled “Map, filter, reduce as named templates”JavaScript developers reach for map, filter, and reduce daily. The Array category provides them as named templates that take an Apply-mode function as their callback.
| Field | Value |
|---|---|
| Input array | [12.5, 49.99, 199] |
| Apply function | {{Apply - formatNumber EUR}} |
[“12,50 €”, “49,99 €”, “199,00 €“]Composed patterns — chaining variables
Section titled “Composed patterns — chaining variables”Clean DOM-scraped IDs
Take a noisy DOM-scraped array, strip falsy values, deduplicate, take the first 10.
Build and join
Construct an array from individual variables, then join into a single string for a GA4 parameter.
Audience qualification
Test multiple containment conditions to qualify a user for an audience segment.
Why you don’t need Custom JavaScript
Section titled “Why you don’t need Custom JavaScript”The dominant Custom JavaScript pattern for array operations in GTM:
function() {
var tags = {{DLV - user_tags}};
if (!Array.isArray(tags)) return false;
var lookup = [‘premium’, ‘vip’, ‘enterprise’];
return tags.some(function(tag) {
return lookup.indexOf(tag) !== -1;
});
}Half a dozen lines that boil down to includesAny(tags, lookup). Each one:
- Buries intent in code. The lookup list is hardcoded inside the function.
- Doesn’t compose. AND and OR semantics across two arrays means two functions.
- Lacks defensive type handling. Half the implementations skip
Array.isArray. - Doesn’t transfer to sGTM. Named templates with explicit permissions transfer cleanly.
Cheatsheet
Section titled “Cheatsheet”| Goal | Variable | Mode |
|---|---|---|
| Trigger when array contains any of a list | includesAny | Direct |
| Trigger when array contains all of a list | includesAll | Direct |
| Trigger when array contains none of a list | includesNone | Direct |
| Build an array from individual variables | ⚡ ARRAY › From Values | Direct / Apply |
| Build an array with explicit positions | ⚡ ARRAY › From Indexed Values | Direct / Apply |
| Wrap a value in a length-1 array | wrapInArray | Direct / Apply |
| Transform every item | map | Direct / Apply |
| Keep items matching a predicate | filterArray | Direct / Apply |
| Collapse to a single value | reduce / reduceRight | Direct / Apply |
| Boolean: every item passes / any item passes | every / some | Direct |
| Find first item matching predicate | find | Direct / Apply |
| First / last / all-but-first item | head / last / tail | Direct / Apply |
| First N / last N items | takeItems / takeItemsRight | Direct / Apply |
| Skip first N / last N items | dropItems / dropItemsRight | Direct / Apply |
| Split into chunks of size N | chunk | Direct / Apply |
| Item at specific index | selectFromArray | Direct / Apply |
| Index of value (first / last) | indexOf / lastIndexOf | Direct |
| Index of item matching predicate / regex | findIndexByCallback / findIndexByRegex | Direct / Apply |
| Remove duplicate values | uniq | Direct / Apply |
| Remove falsy values | compact | Direct / Apply |
| Flatten one level of nesting | flatten | Direct / Apply |
| Reverse order | reverse | Direct / Apply |
| Sort with comparator | sort | Direct / Apply |
| Concatenate items into a string | join | Direct / Apply |
How do I fire a GTM tag when a dataLayer array contains specific values?
Use includesAny to fire when at least one of a list is present, includesAll when every value must be present, or includesNone when none should be present. Each returns a boolean for use as a trigger condition.
Why doesn’t GTM’s native “contains” work for arrays?
GTM’s contains operator on a Data Layer Variable matches the array’s stringified form. That works in some cases but breaks on partial matches (“sport” matches [“sports”]) and offers no AND/OR semantics across multiple lookup values.
How do I build an array from individual values to send to a tag?
Use ⚡ ARRAY › From Values to assemble an array from individual variable inputs. It takes N slots, each pointing to a variable, and returns an array of those values.
How do I deduplicate an array in GTM?
Use uniq to return only unique values. Pair with compact to also remove falsy values like null, undefined, and empty strings.
How do I get the first or last item of an array?
Use head for the first item, last for the last item, tail for everything except the first. For specific indices, use selectFromArray. For taking N items from either end, use takeItems and takeItemsRight.
How do I run map, filter, or reduce on an array?
The map, filterArray, and reduce variables accept an Apply-mode function as their callback. Same semantics as JavaScript’s Array methods, but as composable named templates.
Are these variables sandbox-safe in server-side GTM?
Yes. All templates run inside GTM’s sandboxed JavaScript environment using only permissioned APIs. They work in both web and server containers.