Skip to content

mergeConcatDeep — GTM Variable Template for Object

VARIABLES › OBJECT
mergeConcatDeep EXTENDED Object

Deep-merges two objects, concatenating arrays at all levels.



Examples

Deep arrays concatenated
INPUT
Base Object: {name: 'John', tags: ['user', 'active']}
Additional Object: {age: 30, tags: ['premium']}
OUTPUT
John
Deep non-array override
INPUT
Base Object: {status: 'pending', priority: 1, count: 5}
Additional Object: {status: 'completed', count: 10}
OUTPUT
completed

GTM Configuration

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

mergeConcatDeep
Base Object
💾 The base object to merge from. Its properties will be overridden by the additional object.
Additional Object
💾 The object to merge in. Its properties take priority over the base object.
Input Setup
Input Function (optional)
⚙️ Optional pre-processing function applied to the base object before merging.
Result Handling
Output Function (optional)
⚙️ Optional function to apply to the merged object before returning it.
Base Object object
💡 Type any text to see the result update live
🎯 Using special value — click input to type instead
Test with:
Falsy
Truthy
Additional Object object
mergeConcatDeep()


Under the Hood

📜 View Implementation Code
/**
 * Deep merges two objects recursively, concatenating arrays instead of replacing them.
 *
 * @param {Object} data.src - The base object to merge from.
 * @param {Object} data.add - The additional object to merge in.
 * @param {Function|string} [data.out] - Optional output handler.
 *
 * Direct-mode specific parameters:
 * @param {Function} [data.pre] - Optional pre-processor function.
 * 
 * @returns {Object} A new object with deep merged properties. Arrays are concatenated, nested objects are recursively merged.
 *
 * @framework ggLowCodeGTMKit
 */
const getType = require('getType');

const mergeConcatDeep = function(baseObject, additionalObject) {
    const mergedObject = {};
    
    if (!baseObject || typeof baseObject !== 'object') {
        return additionalObject || {};
    }
    
    if (!additionalObject || typeof additionalObject !== 'object') {
        return baseObject;
    }
    
    for (let key in baseObject) {
        if (baseObject.hasOwnProperty(key)) {
            const baseVal = baseObject[key];
            const addVal = additionalObject[key];
            
            if (getType(baseVal) === 'array' && getType(addVal) === 'array') {
                mergedObject[key] = baseVal.concat(addVal);
            } else if (getType(baseVal) === 'object' && getType(addVal) === 'object') {
                mergedObject[key] = mergeConcatDeep(baseVal, addVal);
            } else if (addVal !== undefined) {
                mergedObject[key] = addVal;
            } else {
                mergedObject[key] = baseVal;
            }
        }
    }
    
    for (let key in additionalObject) {
        if (additionalObject.hasOwnProperty(key) && baseObject[key] === undefined) {
            mergedObject[key] = additionalObject[key];
        }
    }
    
    return mergedObject;
};
const safeFunction = fn => typeof fn === 'function' ? fn : x => x;
const out = safeFunction(data.out);
// ===============================================================================
// mergeConcatDeep - Direct mode
// ===============================================================================
const applyCast = (castFn, value) => safeFunction(castFn)(value);
const value = applyCast(data.pre, data.src);
return out(mergeConcatDeep(value, data.add));
// ===============================================================================
// mergeConcatDeep(...) – Apply Mode
// ===============================================================================
/*
return function(baseObject, additionalObject) {
   additionalObject = data.rp1 ? data.add : additionalObject;
   return out(mergeConcatDeep(baseObject, additionalObject));
};
*/
🧪 View Test Scenarios (10 tests)
✅ '[example] Deep arrays concatenated'
✅ '[example] Deep non-array override'
✅ Test adding new properties
✅ Test empty additional object
✅ Test array with one empty array
✅ Test nested objects are recursively merged (deep)
✅ Test deeply nested objects merged
✅ Test nested arrays concatenated
✅ Test additional properties added at all levels
✅ Test null base returns additional