diff --git a/package.json b/package.json
index b66b5e0..d74ed6e 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
   "name": "digital-data-manager",
   "description": "The hassle-free way to integrate Digital Data Layer on your website.",
   "author": "Driveback LLC <opensource@driveback.ru>",
-  "version": "1.2.14",
+  "version": "1.2.15",
   "license": "MIT",
   "main": "dist/dd-manager.js",
   "scripts": {
diff --git a/src/EventDataEnricher.js b/src/EventDataEnricher.js
index 6342b5e..992ef33 100644
--- a/src/EventDataEnricher.js
+++ b/src/EventDataEnricher.js
@@ -31,20 +31,58 @@ class EventDataEnricher
   }
 
   static enrichIntegrationData(event, digitalData, integration) {
-    const enrichedEvent = clone(event);
+    const eventName = event.name;
+    let enrichedEvent = clone(event);
     const enrichableProps = integration.getEnrichableEventProps(event);
     for (const prop of enrichableProps) {
-      if (!dotProp.getProp(event, prop)) {
+      if (!dotProp.getProp(event, prop) && digitalData) {
         const ddlPropValue = dotProp.getProp(digitalData, prop);
         if (ddlPropValue !== undefined) {
           dotProp.setProp(enrichedEvent, prop, ddlPropValue);
         }
       }
     }
-    integration.overrideEvent(enrichedEvent);
+
+    // handle event override
+    if (integration.getEventOverrideFunction()) {
+      integration.getEventOverrideFunction()(enrichedEvent);
+    }
+    // handle product override
+    if (integration.getProductOverrideFunction()) {
+      enrichedEvent = EventDataEnricher.overrideEventProducts(enrichedEvent, integration);
+    }
+
     return enrichedEvent;
   }
 
+  static overrideEventProducts(event, integration) {
+    const eventName = event.name;
+    if (event.product) {
+      integration.getProductOverrideFunction()(event.product);
+    } else if (event.listing && event.listing.items) {
+      for (const product of event.listing.items) {
+        integration.getProductOverrideFunction()(product);
+      }
+    } else if (event.cart && event.cart.lineItems) {
+      for (const lineItem of event.cart.lineItems) {
+        integration.getProductOverrideFunction()(lineItem.product);
+      }
+    } else if (event.transaction && event.transaction.lineItems) {
+      for (const lineItem of event.transaction.lineItems) {
+        integration.getProductOverrideFunction()(lineItem.product);
+      }
+    } else if (event.listItem || event.listItems) {
+      if (event.listItem) {
+        integration.getProductOverrideFunction()(event.listItem.product);
+      } else if (event.listItems) {
+        for (const listItem of event.listItems) {
+          integration.getProductOverrideFunction()(listItem.product);
+        }
+      }
+    }
+    return event;
+  }
+
   static product(product, digitalData) {
     let productId;
 
diff --git a/src/Integration.js b/src/Integration.js
index d7e3398..eaa401f 100644
--- a/src/Integration.js
+++ b/src/Integration.js
@@ -4,6 +4,7 @@ import loadIframe from './functions/loadIframe';
 import loadPixel from './functions/loadPixel';
 import format from './functions/format';
 import noop from './functions/noop';
+import log from './functions/log';
 import each from './functions/each';
 import deleteProperty from './functions/deleteProperty';
 import debug from 'debug';
@@ -15,6 +16,7 @@ class Integration extends EventEmitter
   constructor(digitalData, options, tags) {
     super();
     this.options = options;
+    this.overrideFunctions = {};
     if (options && options.overrideFunctions) {
       this.defineOverrideFunctions(options.overrideFunctions);
     }
@@ -22,17 +24,49 @@ class Integration extends EventEmitter
     this.tags = tags || {};
     this.onLoad = this.onLoad.bind(this);
     this._isEnriched = false;
+    this._productOverrideErrorFired = false;
   }
 
   defineOverrideFunctions(overrideFunctions) {
     if (overrideFunctions.event) {
-      this.overrideEvent = overrideFunctions.event.bind(this);
+      this.overrideFunctions.event = (event) => {
+        try {
+          overrideFunctions.event.bind(this)(event);
+        } catch (e) {
+          log(`function override error for event ${event.name} in integration ${this.getName()}: ${e}`, log.ERROR);
+        }
+      };
     }
     if (overrideFunctions.product) {
-      this.overrideProduct = overrideFunctions.product.bind(this);
+      this.overrideFunctions.product = (product) => {
+        try {
+          overrideFunctions.product.bind(this)(product);
+        } catch (e) {
+          if (!this._productOverrideErrorFired) {
+            log(`function override error for product in integration ${this.getName()}: ${e}`, log.ERROR);
+            this._productOverrideErrorFired = true;
+          }
+        }
+      };
     }
   }
 
+  getProductOverrideFunction() {
+    return this.overrideFunctions.product;
+  }
+
+  getEventOverrideFunction() {
+    return this.overrideFunctions.event;
+  }
+
+  setName(name) {
+    this.name = name;
+  }
+
+  getName() {
+    return this.name;
+  }
+
   overrideProduct() {
     // abstract
   }
diff --git a/src/ddManager.js b/src/ddManager.js
index dcc7ae5..e5457fa 100644
--- a/src/ddManager.js
+++ b/src/ddManager.js
@@ -188,7 +188,7 @@ function _initializeIntegrations(settings) {
 
 ddManager = {
 
-  VERSION: '1.2.14',
+  VERSION: '1.2.15',
 
   setAvailableIntegrations: (availableIntegrations) => {
     _availableIntegrations = availableIntegrations;
@@ -276,8 +276,11 @@ ddManager = {
     if (!integration instanceof Integration || !name) {
       throw new TypeError('attempted to add an invalid integration');
     }
-    _integrations[name] = integration;
+
+    integration.setName(name);
     integration.setDDManager(ddManager);
+
+    _integrations[name] = integration;
   },
 
   getIntegration: (name) => {
diff --git a/src/functions/log.js b/src/functions/log.js
new file mode 100644
index 0000000..7d63119
--- /dev/null
+++ b/src/functions/log.js
@@ -0,0 +1,26 @@
+import noop from './noop';
+
+const MESSAGE = 'message';
+const WARNING = 'warning';
+const ERROR = 'error';
+
+function log(msg, type) {
+  /* eslint-disable */
+  console.log = console.log || noop;
+  console.warn = console.warn || console.log;
+  console.error = console.error || console.warn;
+  if (!type) {
+    console.log(msg);
+  } else if (type === WARNING) {
+    console.warn(msg);
+  } else if (type === ERROR) {
+    console.error(msg);
+  }
+  /* eslint-enable */
+}
+
+log.MESSAGE = MESSAGE;
+log.WARNING = WARNING;
+log.ERROR = ERROR;
+
+export default log;
diff --git a/src/integrations/Emarsys.js b/src/integrations/Emarsys.js
index c6eff24..893c754 100644
--- a/src/integrations/Emarsys.js
+++ b/src/integrations/Emarsys.js
@@ -12,10 +12,9 @@ function calculateLineItemSubtotal(lineItem) {
   return price * quantity;
 }
 
-function mapLineItems(lineItems, overrideProduct) {
+function mapLineItems(lineItems) {
   return lineItems.map((lineItem) => {
     const product = lineItem.product;
-    overrideProduct(product);
     const lineItemSubtotal = lineItem.subtotal || calculateLineItemSubtotal(lineItem);
     return {
       item: product.id || product.skuCode,
@@ -149,7 +148,7 @@ class Emarsys extends Integration {
       window.ScarabQueue.push(['setCustomerId', user.userId]);
     }
     if (cart.lineItems && cart.lineItems.length > 0) {
-      window.ScarabQueue.push(['cart', mapLineItems(cart.lineItems, this.overrideProduct)]);
+      window.ScarabQueue.push(['cart', mapLineItems(cart.lineItems)]);
     } else {
       window.ScarabQueue.push(['cart', []]);
     }
@@ -174,7 +173,6 @@ class Emarsys extends Integration {
 
   onViewedProductDetail(event) {
     const product = event.product || {};
-    this.overrideProduct(product);
     if (product.id || product.skuCode) {
       window.ScarabQueue.push(['view', product.id || product.skuCode]);
     }
@@ -194,7 +192,7 @@ class Emarsys extends Integration {
     if (transaction.orderId && transaction.lineItems) {
       window.ScarabQueue.push(['purchase', {
         orderId: transaction.orderId,
-        items: mapLineItems(transaction.lineItems, this.overrideProduct),
+        items: mapLineItems(transaction.lineItems),
       }]);
     }
     go();
diff --git a/src/integrations/RetailRocket.js b/src/integrations/RetailRocket.js
index c6311e9..5e69cc9 100644
--- a/src/integrations/RetailRocket.js
+++ b/src/integrations/RetailRocket.js
@@ -234,7 +234,6 @@ class RetailRocket extends Integration {
         break;
       }
       const product = lineItems[i].product;
-      this.overrideProduct(product);
       items.push({
         id: product.id,
         qnt: lineItems[i].quantity,
@@ -329,7 +328,6 @@ class RetailRocket extends Integration {
     let isValid = this.validateLineItem(lineItem);
 
     const product = lineItem.product;
-    this.overrideProduct(product);
     if (!product.id) {
       isValid = false;
     }
@@ -345,7 +343,6 @@ class RetailRocket extends Integration {
 
   getProductId(product) {
     product = product || {};
-    this.overrideProduct(product);
     const productId = product.id;
 
     return productId;
diff --git a/test/EventDataEnricherSpec.js b/test/EventDataEnricherSpec.js
index efe0732..9d96704 100644
--- a/test/EventDataEnricherSpec.js
+++ b/test/EventDataEnricherSpec.js
@@ -479,9 +479,8 @@ describe('EventDataEnricher', () => {
           id: '123'
         }
       };
-      emarsys.initialize();
-      emarsys.trackEvent(event);
-      assert.equal(window.ScarabQueue[0][1], 's/123');
+      const enrichedEvent = EventDataEnricher.enrichIntegrationData(event, _digitalData, emarsys);
+      assert.equal(enrichedEvent.product.id, 's/123');
     });
   });
 
diff --git a/test/integrations/RetailRocketSpec.js b/test/integrations/RetailRocketSpec.js
index 97158c7..30f36ab 100644
--- a/test/integrations/RetailRocketSpec.js
+++ b/test/integrations/RetailRocketSpec.js
@@ -16,7 +16,9 @@ describe('Integrations: RetailRocket', () => {
     userIdProperty: 'user.email',
     overrideFunctions: {
       product: (product) => {
-        product.id = product.id.replace(/_/g, '');
+        if (product && product.id) {
+          product.id = product.id.replace(/_/g, '');
+        }    
       },
     },
   };