This is an automated email from the ASF dual-hosted git repository.

jkevan pushed a commit to branch UNOMI-610-new-tracker
in repository https://gitbox.apache.org/repos/asf/unomi-tracker.git


The following commit(s) were added to refs/heads/UNOMI-610-new-tracker by this 
push:
     new f67e79d  UNOMI-610: base tracker first draft
f67e79d is described below

commit f67e79da5c818a0e9e89494b31e6f9257f39986f
Author: Kevan <[email protected]>
AuthorDate: Tue Sep 6 16:46:43 2022 +0200

    UNOMI-610: base tracker first draft
---
 dist/apache-unomi-tracker.cjs.js | 91 ++++++++++++++++++++++++++++---------
 dist/apache-unomi-tracker.esm.js | 87 +++++++++++++++++++++++++++---------
 dist/apache-unomi-tracker.umd.js | 96 +++++++++++++++++++++++++++++++---------
 src/tracker/tracker.js           | 44 +++++++++++++++++-
 4 files changed, 256 insertions(+), 62 deletions(-)

diff --git a/dist/apache-unomi-tracker.cjs.js b/dist/apache-unomi-tracker.cjs.js
index 9d8bcdb..328326b 100644
--- a/dist/apache-unomi-tracker.cjs.js
+++ b/dist/apache-unomi-tracker.cjs.js
@@ -2,8 +2,13 @@
 
 Object.defineProperty(exports, '__esModule', { value: true });
 
+var _typeof = require('@babel/runtime/helpers/typeof');
 var es6CrawlerDetect = require('es6-crawler-detect');
 
+function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 
'default' in e ? e : { 'default': e }; }
+
+var _typeof__default = /*#__PURE__*/_interopDefaultLegacy(_typeof);
+
 function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof 
Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if 
(Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && 
o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = 
function F() {}; return { s: F, n: function n() { if (i >= o.length) return { 
done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { 
throw _e; }, f: F }; } throw new T [...]
 
 function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o 
=== "string") return _arrayLikeToArray(o, minLen); var n = 
Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && 
o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return 
Array.from(o); if (n === "Arguments" || 
/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, 
minLen); }
@@ -43,8 +48,12 @@ var newTracker = function newTracker() {
 
     /**
      * This function start the tracker by loading the context in the page
+     * Note: that the tracker will start once the current DOM is complete 
loaded, using listener on current document: DOMContentLoaded
+     *
+     * @param {object[]} digitalDataOverrides optional, list of digitalData 
extensions, they will be merged with original digitalData before context loading
      */
     startTracker: function startTracker() {
+      var digitalDataOverrides = arguments.length > 0 && arguments[0] !== 
undefined ? arguments[0] : undefined;
       // Check before start
       var cookieDisabled = !navigator.cookieEnabled;
       var noSessionID = !wem.sessionID || wem.sessionID === '';
@@ -60,7 +69,7 @@ var newTracker = function newTracker() {
           wem._executeFallback('navigator cookie disabled: ' + cookieDisabled 
+ ', no sessionID: ' + noSessionID + ', web crawler detected: ' + 
crawlerDetected);
         });
         return;
-      } // Base callback
+      } // Register base context callback
 
 
       wem._registerCallback(function () {
@@ -77,7 +86,10 @@ var newTracker = function newTracker() {
 
 
       document.addEventListener('DOMContentLoaded', function () {
-        wem.DOMLoaded = true; // complete already registered events
+        wem.DOMLoaded = true; // enrich digital data considering extensions
+
+        wem._handleDigitalDataOverrides(digitalDataOverrides); // complete 
already registered events
+
 
         wem._checkUncompleteRegisteredEvents(); // Dispatch javascript events 
for the experience (perso/opti displayed from SSR, based on unomi events)
 
@@ -739,6 +751,23 @@ var newTracker = function newTracker() {
     /* Private functions under this line */
 
     /*************************************/
+    _handleDigitalDataOverrides: function 
_handleDigitalDataOverrides(digitalDataOverrides) {
+      if (digitalDataOverrides && digitalDataOverrides.length > 0) {
+        var _iterator = _createForOfIteratorHelper(digitalDataOverrides),
+            _step;
+
+        try {
+          for (_iterator.s(); !(_step = _iterator.n()).done;) {
+            var digitalDataOverride = _step.value;
+            wem.digitalData = wem._deepMergeObjects(digitalDataOverride, 
wem.digitalData);
+          }
+        } catch (err) {
+          _iterator.e(err);
+        } finally {
+          _iterator.f();
+        }
+      }
+    },
     _registerListenersForTrackedConditions: function 
_registerListenersForTrackedConditions() {
       var videoNamesToWatch = [];
       var clickToWatch = [];
@@ -810,39 +839,39 @@ var newTracker = function newTracker() {
     },
     _checkUncompleteRegisteredEvents: function 
_checkUncompleteRegisteredEvents() {
       if (wem.digitalData && wem.digitalData.events) {
-        var _iterator = _createForOfIteratorHelper(wem.digitalData.events),
-            _step;
+        var _iterator2 = _createForOfIteratorHelper(wem.digitalData.events),
+            _step2;
 
         try {
-          for (_iterator.s(); !(_step = _iterator.n()).done;) {
-            var event = _step.value;
+          for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
+            var event = _step2.value;
 
             wem._completeEvent(event);
           }
         } catch (err) {
-          _iterator.e(err);
+          _iterator2.e(err);
         } finally {
-          _iterator.f();
+          _iterator2.f();
         }
       }
     },
     _dispatchJSExperienceDisplayedEvents: function 
_dispatchJSExperienceDisplayedEvents() {
       if (wem.digitalData && wem.digitalData.events) {
-        var _iterator2 = _createForOfIteratorHelper(wem.digitalData.events),
-            _step2;
+        var _iterator3 = _createForOfIteratorHelper(wem.digitalData.events),
+            _step3;
 
         try {
-          for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
-            var event = _step2.value;
+          for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
+            var event = _step3.value;
 
             if (event.eventType === 'optimizationTestEvent' || event.eventType 
=== 'personalizationEvent') {
               wem._dispatchJSExperienceDisplayedEvent(event);
             }
           }
         } catch (err) {
-          _iterator2.e(err);
+          _iterator3.e(err);
         } finally {
-          _iterator2.f();
+          _iterator3.f();
         }
       }
     },
@@ -853,12 +882,12 @@ var newTracker = function newTracker() {
           personalizationEvent: 'personalization'
         };
 
-        var _iterator3 = 
_createForOfIteratorHelper(experienceUnomiEvent.target.properties.variants),
-            _step3;
+        var _iterator4 = 
_createForOfIteratorHelper(experienceUnomiEvent.target.properties.variants),
+            _step4;
 
         try {
-          for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
-            var variant = _step3.value;
+          for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
+            var variant = _step4.value;
             var jsEventDetail = {
               id: variant.id,
               name: variant.systemName,
@@ -880,9 +909,9 @@ var newTracker = function newTracker() {
             wem.dispatchJSEvent('displayWemVariant', false, false, 
jsEventDetail);
           }
         } catch (err) {
-          _iterator3.e(err);
+          _iterator4.e(err);
         } finally {
-          _iterator3.f();
+          _iterator4.f();
         }
       }
     },
@@ -1212,6 +1241,28 @@ var newTracker = function newTracker() {
 
       console.log("Wem ".concat(enable ? 'enabled' : 'disabled'));
     },
+    _deepMergeObjects: function _deepMergeObjects(source, target) {
+      if (!wem._isObject(target) || !wem._isObject(source)) {
+        return source;
+      }
+
+      Object.keys(source).forEach(function (key) {
+        var targetValue = target[key];
+        var sourceValue = source[key]; // concat arrays || merge objects || 
add new props
+
+        if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {
+          target[key] = targetValue.concat(sourceValue);
+        } else if (wem._isObject(targetValue) && wem._isObject(sourceValue)) {
+          target[key] = wem._deepMergeObjects(sourceValue, Object.assign({}, 
targetValue));
+        } else {
+          target[key] = sourceValue;
+        }
+      });
+      return target;
+    },
+    _isObject: function _isObject(obj) {
+      return obj && _typeof__default["default"](obj) === 'object';
+    },
     _isInControlGroup: function _isInControlGroup(id) {
       if (wem.cxs.profileProperties && 
wem.cxs.profileProperties.unomiControlGroups) {
         var controlGroup = 
wem.cxs.profileProperties.unomiControlGroups.find(function (controlGroup) {
diff --git a/dist/apache-unomi-tracker.esm.js b/dist/apache-unomi-tracker.esm.js
index 1a4938a..b5a5bff 100644
--- a/dist/apache-unomi-tracker.esm.js
+++ b/dist/apache-unomi-tracker.esm.js
@@ -1,3 +1,4 @@
+import _typeof from '@babel/runtime/helpers/typeof';
 import { Crawler } from 'es6-crawler-detect';
 
 function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof 
Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if 
(Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && 
o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = 
function F() {}; return { s: F, n: function n() { if (i >= o.length) return { 
done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { 
throw _e; }, f: F }; } throw new T [...]
@@ -39,8 +40,12 @@ var newTracker = function newTracker() {
 
     /**
      * This function start the tracker by loading the context in the page
+     * Note: that the tracker will start once the current DOM is complete 
loaded, using listener on current document: DOMContentLoaded
+     *
+     * @param {object[]} digitalDataOverrides optional, list of digitalData 
extensions, they will be merged with original digitalData before context loading
      */
     startTracker: function startTracker() {
+      var digitalDataOverrides = arguments.length > 0 && arguments[0] !== 
undefined ? arguments[0] : undefined;
       // Check before start
       var cookieDisabled = !navigator.cookieEnabled;
       var noSessionID = !wem.sessionID || wem.sessionID === '';
@@ -56,7 +61,7 @@ var newTracker = function newTracker() {
           wem._executeFallback('navigator cookie disabled: ' + cookieDisabled 
+ ', no sessionID: ' + noSessionID + ', web crawler detected: ' + 
crawlerDetected);
         });
         return;
-      } // Base callback
+      } // Register base context callback
 
 
       wem._registerCallback(function () {
@@ -73,7 +78,10 @@ var newTracker = function newTracker() {
 
 
       document.addEventListener('DOMContentLoaded', function () {
-        wem.DOMLoaded = true; // complete already registered events
+        wem.DOMLoaded = true; // enrich digital data considering extensions
+
+        wem._handleDigitalDataOverrides(digitalDataOverrides); // complete 
already registered events
+
 
         wem._checkUncompleteRegisteredEvents(); // Dispatch javascript events 
for the experience (perso/opti displayed from SSR, based on unomi events)
 
@@ -735,6 +743,23 @@ var newTracker = function newTracker() {
     /* Private functions under this line */
 
     /*************************************/
+    _handleDigitalDataOverrides: function 
_handleDigitalDataOverrides(digitalDataOverrides) {
+      if (digitalDataOverrides && digitalDataOverrides.length > 0) {
+        var _iterator = _createForOfIteratorHelper(digitalDataOverrides),
+            _step;
+
+        try {
+          for (_iterator.s(); !(_step = _iterator.n()).done;) {
+            var digitalDataOverride = _step.value;
+            wem.digitalData = wem._deepMergeObjects(digitalDataOverride, 
wem.digitalData);
+          }
+        } catch (err) {
+          _iterator.e(err);
+        } finally {
+          _iterator.f();
+        }
+      }
+    },
     _registerListenersForTrackedConditions: function 
_registerListenersForTrackedConditions() {
       var videoNamesToWatch = [];
       var clickToWatch = [];
@@ -806,39 +831,39 @@ var newTracker = function newTracker() {
     },
     _checkUncompleteRegisteredEvents: function 
_checkUncompleteRegisteredEvents() {
       if (wem.digitalData && wem.digitalData.events) {
-        var _iterator = _createForOfIteratorHelper(wem.digitalData.events),
-            _step;
+        var _iterator2 = _createForOfIteratorHelper(wem.digitalData.events),
+            _step2;
 
         try {
-          for (_iterator.s(); !(_step = _iterator.n()).done;) {
-            var event = _step.value;
+          for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
+            var event = _step2.value;
 
             wem._completeEvent(event);
           }
         } catch (err) {
-          _iterator.e(err);
+          _iterator2.e(err);
         } finally {
-          _iterator.f();
+          _iterator2.f();
         }
       }
     },
     _dispatchJSExperienceDisplayedEvents: function 
_dispatchJSExperienceDisplayedEvents() {
       if (wem.digitalData && wem.digitalData.events) {
-        var _iterator2 = _createForOfIteratorHelper(wem.digitalData.events),
-            _step2;
+        var _iterator3 = _createForOfIteratorHelper(wem.digitalData.events),
+            _step3;
 
         try {
-          for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
-            var event = _step2.value;
+          for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
+            var event = _step3.value;
 
             if (event.eventType === 'optimizationTestEvent' || event.eventType 
=== 'personalizationEvent') {
               wem._dispatchJSExperienceDisplayedEvent(event);
             }
           }
         } catch (err) {
-          _iterator2.e(err);
+          _iterator3.e(err);
         } finally {
-          _iterator2.f();
+          _iterator3.f();
         }
       }
     },
@@ -849,12 +874,12 @@ var newTracker = function newTracker() {
           personalizationEvent: 'personalization'
         };
 
-        var _iterator3 = 
_createForOfIteratorHelper(experienceUnomiEvent.target.properties.variants),
-            _step3;
+        var _iterator4 = 
_createForOfIteratorHelper(experienceUnomiEvent.target.properties.variants),
+            _step4;
 
         try {
-          for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
-            var variant = _step3.value;
+          for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
+            var variant = _step4.value;
             var jsEventDetail = {
               id: variant.id,
               name: variant.systemName,
@@ -876,9 +901,9 @@ var newTracker = function newTracker() {
             wem.dispatchJSEvent('displayWemVariant', false, false, 
jsEventDetail);
           }
         } catch (err) {
-          _iterator3.e(err);
+          _iterator4.e(err);
         } finally {
-          _iterator3.f();
+          _iterator4.f();
         }
       }
     },
@@ -1208,6 +1233,28 @@ var newTracker = function newTracker() {
 
       console.log("Wem ".concat(enable ? 'enabled' : 'disabled'));
     },
+    _deepMergeObjects: function _deepMergeObjects(source, target) {
+      if (!wem._isObject(target) || !wem._isObject(source)) {
+        return source;
+      }
+
+      Object.keys(source).forEach(function (key) {
+        var targetValue = target[key];
+        var sourceValue = source[key]; // concat arrays || merge objects || 
add new props
+
+        if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {
+          target[key] = targetValue.concat(sourceValue);
+        } else if (wem._isObject(targetValue) && wem._isObject(sourceValue)) {
+          target[key] = wem._deepMergeObjects(sourceValue, Object.assign({}, 
targetValue));
+        } else {
+          target[key] = sourceValue;
+        }
+      });
+      return target;
+    },
+    _isObject: function _isObject(obj) {
+      return obj && _typeof(obj) === 'object';
+    },
     _isInControlGroup: function _isInControlGroup(id) {
       if (wem.cxs.profileProperties && 
wem.cxs.profileProperties.unomiControlGroups) {
         var controlGroup = 
wem.cxs.profileProperties.unomiControlGroups.find(function (controlGroup) {
diff --git a/dist/apache-unomi-tracker.umd.js b/dist/apache-unomi-tracker.umd.js
index e5f045f..dd64f5b 100644
--- a/dist/apache-unomi-tracker.umd.js
+++ b/dist/apache-unomi-tracker.umd.js
@@ -4,6 +4,16 @@
   (global = typeof globalThis !== 'undefined' ? globalThis : global || self, 
factory(global["apache-unomi-tracker"] = {}));
 })(this, (function (exports) { 'use strict';
 
+  function _typeof(obj) {
+    "@babel/helpers - typeof";
+
+    return _typeof = "function" == typeof Symbol && "symbol" == typeof 
Symbol.iterator ? function (obj) {
+      return typeof obj;
+    } : function (obj) {
+      return obj && "function" == typeof Symbol && obj.constructor === Symbol 
&& obj !== Symbol.prototype ? "symbol" : typeof obj;
+    }, _typeof(obj);
+  }
+
   class Provider$3 {
     constructor() {}
 
@@ -1685,8 +1695,12 @@
 
       /**
        * This function start the tracker by loading the context in the page
+       * Note: that the tracker will start once the current DOM is complete 
loaded, using listener on current document: DOMContentLoaded
+       *
+       * @param {object[]} digitalDataOverrides optional, list of digitalData 
extensions, they will be merged with original digitalData before context loading
        */
       startTracker: function startTracker() {
+        var digitalDataOverrides = arguments.length > 0 && arguments[0] !== 
undefined ? arguments[0] : undefined;
         // Check before start
         var cookieDisabled = !navigator.cookieEnabled;
         var noSessionID = !wem.sessionID || wem.sessionID === '';
@@ -1702,7 +1716,7 @@
             wem._executeFallback('navigator cookie disabled: ' + 
cookieDisabled + ', no sessionID: ' + noSessionID + ', web crawler detected: ' 
+ crawlerDetected);
           });
           return;
-        } // Base callback
+        } // Register base context callback
 
 
         wem._registerCallback(function () {
@@ -1719,7 +1733,10 @@
 
 
         document.addEventListener('DOMContentLoaded', function () {
-          wem.DOMLoaded = true; // complete already registered events
+          wem.DOMLoaded = true; // enrich digital data considering extensions
+
+          wem._handleDigitalDataOverrides(digitalDataOverrides); // complete 
already registered events
+
 
           wem._checkUncompleteRegisteredEvents(); // Dispatch javascript 
events for the experience (perso/opti displayed from SSR, based on unomi events)
 
@@ -2381,6 +2398,23 @@
       /* Private functions under this line */
 
       /*************************************/
+      _handleDigitalDataOverrides: function 
_handleDigitalDataOverrides(digitalDataOverrides) {
+        if (digitalDataOverrides && digitalDataOverrides.length > 0) {
+          var _iterator = _createForOfIteratorHelper(digitalDataOverrides),
+              _step;
+
+          try {
+            for (_iterator.s(); !(_step = _iterator.n()).done;) {
+              var digitalDataOverride = _step.value;
+              wem.digitalData = wem._deepMergeObjects(digitalDataOverride, 
wem.digitalData);
+            }
+          } catch (err) {
+            _iterator.e(err);
+          } finally {
+            _iterator.f();
+          }
+        }
+      },
       _registerListenersForTrackedConditions: function 
_registerListenersForTrackedConditions() {
         var videoNamesToWatch = [];
         var clickToWatch = [];
@@ -2452,39 +2486,39 @@
       },
       _checkUncompleteRegisteredEvents: function 
_checkUncompleteRegisteredEvents() {
         if (wem.digitalData && wem.digitalData.events) {
-          var _iterator = _createForOfIteratorHelper(wem.digitalData.events),
-              _step;
+          var _iterator2 = _createForOfIteratorHelper(wem.digitalData.events),
+              _step2;
 
           try {
-            for (_iterator.s(); !(_step = _iterator.n()).done;) {
-              var event = _step.value;
+            for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
+              var event = _step2.value;
 
               wem._completeEvent(event);
             }
           } catch (err) {
-            _iterator.e(err);
+            _iterator2.e(err);
           } finally {
-            _iterator.f();
+            _iterator2.f();
           }
         }
       },
       _dispatchJSExperienceDisplayedEvents: function 
_dispatchJSExperienceDisplayedEvents() {
         if (wem.digitalData && wem.digitalData.events) {
-          var _iterator2 = _createForOfIteratorHelper(wem.digitalData.events),
-              _step2;
+          var _iterator3 = _createForOfIteratorHelper(wem.digitalData.events),
+              _step3;
 
           try {
-            for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
-              var event = _step2.value;
+            for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
+              var event = _step3.value;
 
               if (event.eventType === 'optimizationTestEvent' || 
event.eventType === 'personalizationEvent') {
                 wem._dispatchJSExperienceDisplayedEvent(event);
               }
             }
           } catch (err) {
-            _iterator2.e(err);
+            _iterator3.e(err);
           } finally {
-            _iterator2.f();
+            _iterator3.f();
           }
         }
       },
@@ -2495,12 +2529,12 @@
             personalizationEvent: 'personalization'
           };
 
-          var _iterator3 = 
_createForOfIteratorHelper(experienceUnomiEvent.target.properties.variants),
-              _step3;
+          var _iterator4 = 
_createForOfIteratorHelper(experienceUnomiEvent.target.properties.variants),
+              _step4;
 
           try {
-            for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
-              var variant = _step3.value;
+            for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
+              var variant = _step4.value;
               var jsEventDetail = {
                 id: variant.id,
                 name: variant.systemName,
@@ -2522,9 +2556,9 @@
               wem.dispatchJSEvent('displayWemVariant', false, false, 
jsEventDetail);
             }
           } catch (err) {
-            _iterator3.e(err);
+            _iterator4.e(err);
           } finally {
-            _iterator3.f();
+            _iterator4.f();
           }
         }
       },
@@ -2854,6 +2888,28 @@
 
         console.log("Wem ".concat(enable ? 'enabled' : 'disabled'));
       },
+      _deepMergeObjects: function _deepMergeObjects(source, target) {
+        if (!wem._isObject(target) || !wem._isObject(source)) {
+          return source;
+        }
+
+        Object.keys(source).forEach(function (key) {
+          var targetValue = target[key];
+          var sourceValue = source[key]; // concat arrays || merge objects || 
add new props
+
+          if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {
+            target[key] = targetValue.concat(sourceValue);
+          } else if (wem._isObject(targetValue) && wem._isObject(sourceValue)) 
{
+            target[key] = wem._deepMergeObjects(sourceValue, Object.assign({}, 
targetValue));
+          } else {
+            target[key] = sourceValue;
+          }
+        });
+        return target;
+      },
+      _isObject: function _isObject(obj) {
+        return obj && _typeof(obj) === 'object';
+      },
       _isInControlGroup: function _isInControlGroup(id) {
         if (wem.cxs.profileProperties && 
wem.cxs.profileProperties.unomiControlGroups) {
           var controlGroup = 
wem.cxs.profileProperties.unomiControlGroups.find(function (controlGroup) {
diff --git a/src/tracker/tracker.js b/src/tracker/tracker.js
index 7cbe13f..edb44cb 100644
--- a/src/tracker/tracker.js
+++ b/src/tracker/tracker.js
@@ -31,8 +31,11 @@ export const newTracker = () => {
 
         /**
          * This function start the tracker by loading the context in the page
+         * Note: that the tracker will start once the current DOM is complete 
loaded, using listener on current document: DOMContentLoaded
+         *
+         * @param {object[]} digitalDataOverrides optional, list of 
digitalData extensions, they will be merged with original digitalData before 
context loading
          */
-        startTracker: function () {
+        startTracker: function (digitalDataOverrides = undefined) {
             // Check before start
             let cookieDisabled = !navigator.cookieEnabled;
             let noSessionID = !wem.sessionID || wem.sessionID === '';
@@ -48,7 +51,7 @@ export const newTracker = () => {
                 return;
             }
 
-            // Base callback
+            // Register base context callback
             wem._registerCallback(function () {
                 if (wem.cxs.profileId) {
                     wem.setCookie(wem.trackerProfileIdCookieName, 
wem.cxs.profileId);
@@ -64,6 +67,9 @@ export const newTracker = () => {
             document.addEventListener('DOMContentLoaded', function () {
                 wem.DOMLoaded = true;
 
+                // enrich digital data considering extensions
+                wem._handleDigitalDataOverrides(digitalDataOverrides);
+
                 // complete already registered events
                 wem._checkUncompleteRegisteredEvents();
 
@@ -688,6 +694,14 @@ export const newTracker = () => {
         /*************************************/
         /* Private functions under this line */
         /*************************************/
+        _handleDigitalDataOverrides: function (digitalDataOverrides) {
+            if (digitalDataOverrides && digitalDataOverrides.length > 0) {
+                for (const digitalDataOverride of digitalDataOverrides) {
+                    wem.digitalData = 
wem._deepMergeObjects(digitalDataOverride, wem.digitalData);
+                }
+            }
+        },
+
         _registerListenersForTrackedConditions: function () {
             var videoNamesToWatch = [];
             var clickToWatch = [];
@@ -1112,6 +1126,32 @@ export const newTracker = () => {
             console.log(`Wem ${enable ? 'enabled' : 'disabled'}`);
         },
 
+        _deepMergeObjects: function (source, target) {
+            if (!wem._isObject(target) || !wem._isObject(source)) {
+                return source;
+            }
+
+            Object.keys(source).forEach(key => {
+                const targetValue = target[key];
+                const sourceValue = source[key];
+
+                // concat arrays || merge objects || add new props
+                if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {
+                    target[key] = targetValue.concat(sourceValue);
+                } else if (wem._isObject(targetValue) && 
wem._isObject(sourceValue)) {
+                    target[key] = wem._deepMergeObjects(sourceValue, 
Object.assign({}, targetValue));
+                } else {
+                    target[key] = sourceValue;
+                }
+            });
+
+            return target;
+        },
+
+        _isObject: function (obj) {
+            return obj && typeof obj === 'object';
+        },
+
         _isInControlGroup: function (id) {
             if (wem.cxs.profileProperties && 
wem.cxs.profileProperties.unomiControlGroups) {
                 let controlGroup = 
wem.cxs.profileProperties.unomiControlGroups.find(controlGroup => 
controlGroup.id === id);

Reply via email to