Skip to content

๐€๐‘๐‘๐€๐˜ From Indexed Values Generator - Array โ€” GTM Variable Template for GTM

VARIABLES โ€บ GTM
๐€๐‘๐‘๐€๐˜ From Indexed Values Generator - Array CORE GTM

Generates an array from indexed table values, ordered by index.


When to Use This

GTM Utilities

Access GTM-specific APIs: dataLayer, debug mode, container settings.

GA4 Ecommerce

Build and transform ecommerce data structures for GA4 event tracking.

Sorting

Order arrays and collections by values, keys, or custom comparators.


Examples

Transform with mapper
INPUT
Indexed Values: [
Append unindexed values at the end: true
Mapper Function (optional): val => val.toUpperCase()
OUTPUT
['HELLO', 'WORLD', 'EXTRA']
Array ordered by index
INPUT
Indexed Values: [
Append unindexed values at the end: true
OUTPUT
['first', 'second', 'third']

GTM Configuration

This is what you'll see when you open this variable in Google Tag Manager. Hover the icons for details.

๐€๐‘๐‘๐€๐˜ From Indexed Values Generator - Array
ARRAY โฌ‡
Indexed Values
๐Ÿ’พ Define values with optional indices.

Index column:
  โ€ข Valid indices: Non-negative numbers (0, 1, 2, ...)
  โ€ข Invalid/empty indices: Values are appended at the end (if enabled)
  โ€ข Gaps in indices: Filled with undefined

Value column:
  โ€ข Any value (string, number, variable, etc.)
IndexValue
โŠ–
โŠ–
โœ“ When enabled, values without valid indices are appended after the indexed values. When disabled, unindexed values are excluded from the result.
Value Processing
Mapper Function (optional)
โš™๏ธ Optional function to transform each individual value before adding it to the array: val => transformedVal

Use this for:
  โ€ข Trim whitespace: val => val.trim()
  โ€ข Parse numbers: val => parseFloat(val)
  โ€ข Transform case: val => val.toUpperCase()
  โ€ข Add prefix: val => 'item_' + val

Note: This applies to each value individually, including both indexed and unindexed values.
Result Handling
Output Function (optional)
โš™๏ธ Optional function to transform the entire array before returning it: arr => transformedArr

Use this for:
  โ€ข Remove gaps: arr => arr.filter(x => x !== undefined)
  โ€ข Convert to string: arr => arr.join(',')
  โ€ข Reverse array: arr => arr.reverse()

Note: This applies to the complete array after all values have been processed and positioned.
Indexed Values table
IndexValue
getType()


Under the Hood

๐Ÿ“œ View Implementation Code
/**
 * Converts indexed objects into a properly ordered array with optional unindexed values appended.
 * 
 * @param {Array<{ind?: number, val: any}>} data.ivl - Array of objects with optional index (ind) and value (val).
 * @param {boolean} [data.aui=true] - Whether to append unindexed values at the end.
 * @param {Function} [data.map] - Optional function to transform each value before adding to array.
 * @param {Function|string} [data.out] - Optional output handler.
 * 
 * @returns {Array} Ordered array with indexed values and optionally appended unindexed values.
 *
 * @framework ggLowCodeGTMKit
 */
const getType = require('getType');
const makeNumber = require('makeNumber');

const indexedObjects = getType(data.ivl) === 'array' && data.ivl || [];
const appendUnindexed = typeof data.aui !== 'undefined' ? data.aui : true;
const safeFunction = fn => typeof fn === 'function' ? fn : x => x;
const mapper = safeFunction(data.map);

const indexed = [];
const unindexed = [];

indexedObjects.forEach(obj => {
    if (obj && obj.hasOwnProperty('ind') && obj.ind !== null && obj.ind !== undefined) {
        const idx = makeNumber(obj.ind);
        if (typeof idx === 'number' && idx >= 0 && idx === idx) { 
            indexed.push(obj);
        } else if (obj.hasOwnProperty('val')) {
            unindexed.push(obj);
        }
    } else if (obj && obj.hasOwnProperty('val')) {
        unindexed.push(obj);
    }
});

indexed.sort((a, b) => makeNumber(a.ind) - makeNumber(b.ind));

let maxIndex = -1;
indexed.forEach(obj => {
    const idx = makeNumber(obj.ind);
    if (idx > maxIndex) {
        maxIndex = idx;
    }
});

const result = [];
result.length = maxIndex + 1;

indexed.forEach(obj => {
    result[makeNumber(obj.ind)] = mapper(obj.val);
});

if (appendUnindexed) {
    unindexed.forEach(obj => result.push(mapper(obj.val)));
}

const out = safeFunction(data.out);

return out(result);
๐Ÿงช View Test Scenarios (11 tests)
โœ… '[example] Transform with mapper'
โœ… '[example] Array ordered by index'
โœ… Array with gaps - should fill with undefined
โœ… Unindexed values appended - should add at the end
โœ… Unindexed values not appended - should exclude them
โœ… Mixed indexed and unindexed with gaps
โœ… Invalid indices - should treat as unindexed
โœ… Empty array - should return empty array
โœ… Duplicate indices - last one should win
โœ… Output function to remove undefined - should filter gaps
โœ… Unsorted indices - should sort properly