UNPKG

mobify-analytics-sdk

Version:

A unified way to setup Mobify analytics

2,425 lines 77.2 kB
// [AIV] Build version: 0.0.24 
 (function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory();
	else if(typeof define === 'function' && define.amd)
		define([], factory);
	else if(typeof exports === 'object')
		exports["mobify-analytics-sdk"] = factory();
	else
		root["mobify-analytics-sdk"] = factory();
})(this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};

/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {

/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId])
/******/ 			return installedModules[moduleId].exports;

/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			exports: {},
/******/ 			id: moduleId,
/******/ 			loaded: false
/******/ 		};

/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/ 		// Flag the module as loaded
/******/ 		module.loaded = true;

/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}


/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;

/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;

/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "https://localhost:8443/public/bundle/";

/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {

	module.exports = __webpack_require__(1);


/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	    value: true
	});
	exports.u = exports.t = exports.debug = exports.setDebug = exports.init = exports.version = undefined;

	var _configuration = __webpack_require__(2);

	Object.keys(_configuration).forEach(function (key) {
	    if (key === "default" || key === "__esModule") return;
	    Object.defineProperty(exports, key, {
	        enumerable: true,
	        get: function get() {
	            return _configuration[key];
	        }
	    });
	});

	var _events = __webpack_require__(5);

	Object.keys(_events).forEach(function (key) {
	    if (key === "default" || key === "__esModule") return;
	    Object.defineProperty(exports, key, {
	        enumerable: true,
	        get: function get() {
	            return _events[key];
	        }
	    });
	});

	__webpack_require__(3);

	var configuration = _interopRequireWildcard(_configuration);

	var eventSender = _interopRequireWildcard(_events);

	var _tester = __webpack_require__(10);

	var tester = _interopRequireWildcard(_tester);

	var _utils = __webpack_require__(6);

	var utils = _interopRequireWildcard(_utils);

	var _sandy = __webpack_require__(12);

	var _sandy2 = _interopRequireDefault(_sandy);

	var _debugger = __webpack_require__(13);

	var _debugger2 = _interopRequireDefault(_debugger);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

	var version = exports.version = '0.0.24';

	/**
	 * Initialize the SDK - the first method to call
	 *
	 * @param {Object} options - options include config, integrations
	 *                    instrumentDCL - if we setup domReady listener
	 *                    pollFrequency - frequency of polling function
	 *                    SPA - if was force single page app mode - even if not on progressive
	 *                    firstPageview - if we want to send first pageview
	 *                    mobilePageview - if we want to send mobile pageview
	 */
	/**
	 * Analytic SDK - Main function from analyticsSDK
	 *
	 * @module analyticsSDK/main
	 */

	var init = exports.init = function init(options) {

	    configuration.parseConfig(options.config);
	    if (options.integrations) {
	        utils.forEach(options.integrations, function (integration) {
	            if (integration === 'sandy') {
	                eventSender.addIntegration('sandy', new _sandy2.default());
	            }
	        });
	    }

	    configuration.setupInstrument(options);

	    return exports;
	};

	/**
	 * Set the debug mode
	 */
	var setDebug = exports.setDebug = function setDebug() {
	    eventSender.addIntegration('debugger', new _debugger2.default());
	    return exports;
	};

	/**
	 * Sets debug and highlight mode
	 */
	var debug = exports.debug = function debug() {
	    setDebug();
	    configuration.highlight();
	    return exports;
	};

	var t = exports.t = tester;
	var u = exports.u = utils;

/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	    value: true
	});
	exports.listInstrumented = exports.setupInstrument = exports.registerRouteChange = exports.parseConfig = exports.getConfig = exports.highlight = exports.clear = exports.clearInstrumented = exports.uninstrument = exports.contentDimension = exports.checkerDimension = exports.elementTarget = exports.checker = exports.extractor = exports.lifeCycle = exports.components = exports.events = exports.routeTimer = exports.numberOfTimerTrigger = exports.instrumentTimer = undefined;

	__webpack_require__(3);

	var _domready = __webpack_require__(4);

	var _domready2 = _interopRequireDefault(_domready);

	var _events = __webpack_require__(5);

	var eventSender = _interopRequireWildcard(_events);

	var _utils = __webpack_require__(6);

	var utils = _interopRequireWildcard(_utils);

	var _dimensions = __webpack_require__(7);

	var dimensionsModule = _interopRequireWildcard(_dimensions);

	var _events2 = __webpack_require__(9);

	var eventsModule = _interopRequireWildcard(_events2);

	var _configUtils = __webpack_require__(8);

	var configUtils = _interopRequireWildcard(_configUtils);

	function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

	function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } /**
	                                                                                                                                                                                                     * Responsible for configuration file parsing and implementation
	                                                                                                                                                                                                     *
	                                                                                                                                                                                                     * @module analyticsSDK/configuration
	                                                                                                                                                                                                     */


	var logger = window.Mobify.Debug('analytic-sdk');

	/**
	 * Poll timer
	 */
	var instrumentTimer = exports.instrumentTimer = null;
	var numberOfTimerTrigger = exports.numberOfTimerTrigger = 0;

	/**
	 * Max number of cycles until dropping untilSeen elements
	 */
	var maxUntilSeen = 20;

	/**
	 * Setup route monitor
	 */
	var routeTimer = exports.routeTimer = null;

	var capturesToAdd = [];
	var styleSheetAdded = false;

	/**
	 * Access this list of constants by using `analyticsSDK.c.<name>`
	 *
	 * @namespace c
	 */
	var events = exports.events = {
	    /**
	     * A constant for defining AddToCart event
	     *
	     * @const
	     */
	    addToCart: 'addToCart',
	    removeFromCart: 'removeFromCart',
	    search: 'search',
	    formInteraction: 'formInteraction'
	};

	var components = exports.components = {
	    /**
	     * Capture the events only in progressive
	     * we check for `window.Progressive`
	     * @const
	     */
	    PWA: 'PWA',
	    /**
	     * Capture in adaptive
	     *
	     * @const
	     */
	    Adaptive: 'Adaptive',
	    /**
	     * Capture the events only in astro
	     * we check for `window.Astro`
	     * @const
	     */
	    Astro: 'Astro'
	};

	var lifeCycle = exports.lifeCycle = configUtils.lifeCycle;

	var extractorToString = function extractorToString(funcName) {
	    for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
	        args[_key - 1] = arguments[_key];
	    }

	    return JSON.stringify([funcName].concat(args));
	};

	var c = configUtils.c;

	/**
	 * Various extractor used to extract value
	 */
	var extractor = exports.extractor = {};
	utils.inEach(c.extractor, function (name) {
	    extractor[name] = function () {
	        for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
	            args[_key2] = arguments[_key2];
	        }

	        return extractorToString.apply(undefined, [name].concat(args));
	    };
	});

	/**
	 * Return Boolean expression for defining checks
	 */
	var checker = exports.checker = {};
	utils.inEach(c.checker, function (name) {
	    checker[name] = function () {
	        for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
	            args[_key3] = arguments[_key3];
	        }

	        return extractorToString.apply(undefined, [name].concat(args));
	    };
	});

	/**
	 * Use target element to determine the dimension
	 */
	var elementTarget = exports.elementTarget = {};
	utils.inEach(c.elementTarget, function (name) {
	    elementTarget[name] = function () {
	        for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
	            args[_key4] = arguments[_key4];
	        }

	        return extractorToString.apply(undefined, [name].concat(args));
	    };
	});

	/**
	 * Dimensions using checker
	 */
	var checkerDimension = exports.checkerDimension = {
	    funnel_step: 'funnel_step'

	    /**
	     * Dimensions using extractor
	     */
	};var contentDimension = exports.contentDimension = {
	    product_category: 'product_category',
	    product_id: 'product_id',
	    product_name: 'product_name',
	    product_stock: 'product_stock',
	    product_price: 'product_price'
	};

	var addStyleSheet = function addStyleSheet() {
	    var styleEl = document.createElement('style');
	    document.head.appendChild(styleEl);
	    var styleSheet = styleEl.sheet;
	    styleSheet.insertRule('.mobify-highlight {-webkit-box-shadow: 0px 0px 10px 10px rgba(255,0,0,1) !important; -moz-box-shadow: 0px 0px 10px 10px rgba(255,0,0,1) !important; box-shadow: 0px 0px 10px 10px rgba(255,0,0,1) !important; }', 0); // eslint-disable-line max-len
	};

	var uninstrument = exports.uninstrument = function uninstrument() {
	    logger.log('Removing listeners');
	    utils.forEach(capturesToAdd, function (c) {
	        if (styleSheetAdded) {
	            c.applyToElements(function (e) {
	                return e.classList.remove('mobify-highlight');
	            });
	        }
	        c.uninstrument();
	    });
	    eventSender.clearDimensions();
	    return true;
	};

	/**
	 * Clear current instrumentation
	 */
	var clearInstrumented = exports.clearInstrumented = function clearInstrumented() {
	    uninstrument();
	    capturesToAdd = [];
	    exports.numberOfTimerTrigger = numberOfTimerTrigger = 0;

	    if (instrumentTimer) {
	        clearInterval(instrumentTimer);
	        exports.instrumentTimer = instrumentTimer = null;
	    }
	};

	/**
	 * Clear instrumentation and timers
	 */
	var clear = exports.clear = function clear() {
	    clearInstrumented();
	    exports.numberOfTimerTrigger = numberOfTimerTrigger = 0;

	    if (routeTimer) {
	        clearInterval(routeTimer);
	        exports.routeTimer = routeTimer = null;
	    }
	};

	/**
	 * Highlight available elements
	 */
	var highlight = exports.highlight = function highlight() {
	    logger.log('Highlight ' + capturesToAdd.length + ' elements');
	    if (!styleSheetAdded) {
	        addStyleSheet();
	        styleSheetAdded = true;
	    }
	    utils.forEach(capturesToAdd, function (c) {
	        c.applyToElements(function (e) {
	            return e.classList.add('mobify-highlight');
	        });
	    });
	    return true;
	};

	var currentConfig = null;

	/**
	 * Exposing current config used
	 */
	var getConfig = exports.getConfig = function getConfig() {
	    return currentConfig;
	};

	/**
	 * Instrument the page
	 *
	 * @param {Object} config - configuration of instrumentation
	 */
	var parseConfig = exports.parseConfig = function parseConfig(config) {
	    if (capturesToAdd) {
	        clearInstrumented();
	    }

	    if (!config) {
	        logger.log('WARNING: no config rule set');
	        return null;
	    }

	    currentConfig = config;

	    if (config.events) {
	        logger.log('Initializing config with ' + utils.size(config.events) + ' rules');
	        utils.inEach(config.events, function (eventConfig, eventType) {
	            var newCaptures = eventsModule.parseEventConfig(eventConfig, eventType);
	            if (newCaptures) {
	                var _capturesToAdd;

	                (_capturesToAdd = capturesToAdd).push.apply(_capturesToAdd, _toConsumableArray(newCaptures));
	            }
	        });
	    }

	    if (config.dimensions) {
	        utils.inEach(config.dimensions, function (dimConfigWithComponents, dimName) {
	            var newCaptures = [];
	            if (dimName in checkerDimension) {
	                newCaptures = dimensionsModule.parseCheckerDimensionConfig(dimConfigWithComponents, dimName, eventSender.setDimension);
	            } else if (dimName in contentDimension) {
	                newCaptures = dimensionsModule.parseDimensionConfig(dimConfigWithComponents, dimName, eventSender.setDimension);
	            } else {
	                logger.log('Incorrect dimension in ' + dimName);
	            }

	            if (newCaptures) {
	                var _capturesToAdd2;

	                (_capturesToAdd2 = capturesToAdd).push.apply(_capturesToAdd2, _toConsumableArray(newCaptures));
	            }
	        });
	    }

	    return capturesToAdd;
	};

	/**
	 * Signal that a new pageview is triggered by PWA
	 *
	 * @param {Object} dimension to send along with routeChange
	 * @param {Boolean} noPageviewEvent - if we dont want  to send mobile pageview
	 */
	var registerRouteChange = exports.registerRouteChange = function registerRouteChange(dimensions, noPageviewEvent) {
	    uninstrument();
	    // we have to reparse the config since url have changed
	    parseConfig(currentConfig);
	    // eslint-disable-next-line no-use-before-define
	    setupInstrument({
	        instrumentDCL: false,
	        mobilePageview: !noPageviewEvent
	    });

	    if (!noPageviewEvent) {
	        // send a virtual pageview, after dimension have been updated
	        var pageviewEvent = {
	            action: 'pageview',
	            location: document.location.href
	        };
	        if (dimensions) {
	            utils.extend(pageviewEvent, dimensions);
	        }
	        eventSender.send(pageviewEvent);
	    }
	};

	/**
	 * Setup instrumentation
	 *
	 * @param {Object} options - options include config, integrations
	 *                    instrumentDCL - if we setup domReady listener
	 *                    pollFrequency - frequency of polling function
	 *                    SPA - if was use single page app mode (monitor route change)
	 *                    firstPageview - if we want to send first pageview
	 *                    mobilePageview - if we want to send mobile pageview
	 */
	var setupInstrument = exports.setupInstrument = function setupInstrument(options) {
	    var _lifeCycleQueue;

	    var instrumentDCL = options.instrumentDCL,
	        pollFrequency = options.pollFrequency,
	        SPA = options.SPA,
	        firstPageview = options.firstPageview,
	        mobilePageview = options.mobilePageview;

	    var lifeCycleQueue = (_lifeCycleQueue = {}, _defineProperty(_lifeCycleQueue, lifeCycle.ASAP, []), _defineProperty(_lifeCycleQueue, lifeCycle.DCL, []), _defineProperty(_lifeCycleQueue, 'polling', []), _lifeCycleQueue);
	    utils.forEach(capturesToAdd, function (c) {
	        if (c.lifeCycle in lifeCycleQueue) {
	            lifeCycleQueue[c.lifeCycle].push(c);
	        } else {
	            lifeCycleQueue.polling.push(c);
	        }
	    });

	    // instrumenting ASAP elements
	    utils.forEach(lifeCycleQueue[lifeCycle.ASAP], function (c) {
	        c.instrument();
	    });

	    if (lifeCycleQueue[lifeCycle.DCL].length) {
	        if (instrumentDCL) {
	            // instrumenting DCL elements in one call
	            (0, _domready2.default)(function () {
	                utils.forEach(lifeCycleQueue[lifeCycle.DCL], function (c) {
	                    return c.instrument();
	                });
	            });
	        } else {
	            utils.forEach(lifeCycleQueue[lifeCycle.DCL], function (c) {
	                return c.instrument();
	            });
	        }
	    }

	    // instrument untilSeen elements
	    if (instrumentTimer) {
	        clearInterval(instrumentTimer);
	    }
	    var pollElements = lifeCycleQueue.polling;
	    if (pollElements.length) {
	        exports.instrumentTimer = instrumentTimer = setInterval(function () {
	            var nextElementSet = [];
	            exports.numberOfTimerTrigger = numberOfTimerTrigger += 1;
	            utils.forEach(pollElements, function (c) {
	                var foundElement = c.instrument();
	                if (c.lifeCycle === lifeCycle.monitor) {
	                    nextElementSet.push(c);
	                } else if (!(foundElement && c.hasValue()) && numberOfTimerTrigger < maxUntilSeen) {
	                    nextElementSet.push(c);
	                }
	            });
	            pollElements = nextElementSet;
	            if (!nextElementSet.length) {
	                clearInterval(instrumentTimer);
	                exports.instrumentTimer = instrumentTimer = null;
	            }
	        }, pollFrequency || 500);
	    }

	    if ((SPA || configUtils.isProgressive()) && !routeTimer) {
	        var lastRoute = document.location.href;
	        // NOTE: we can use history.onpush here but we risk interfering with hook
	        exports.routeTimer = routeTimer = setInterval(function () {
	            if (document.location.href !== lastRoute) {
	                logger.log('[Analytics SDK] Route change: ' + lastRoute + ' -> ' + document.location.href);
	                lastRoute = document.location.href;
	                registerRouteChange(null, !mobilePageview);
	            }
	        }, pollFrequency || 500);
	    }

	    if (firstPageview) {
	        eventSender.send({
	            action: 'pageview',
	            location: document.location.href
	        });
	    }

	    if (styleSheetAdded) {
	        highlight();
	    }
	};

	/**
	 * Show all instrumented elements
	 */
	var listInstrumented = exports.listInstrumented = function listInstrumented() {
	    return capturesToAdd;
	};

/***/ }),
/* 3 */
/***/ (function(module, exports) {

	// reserved words in javascript: debug, debugger, console
	(function(window, document) {
	    "use strict";

	    // If defined, chill.
	    if (window.Mobify && window.Mobify.Debug) {
	        return
	    }

	    // FIXME: Make this smarter. Persist whether enabled. Read from cookies.
	    // Just enough logic to make this work!
	    var isEnabled = false;
	    if (/MOBIFY_DEBUG=1/.test(window.location)) {
	        isEnabled = true
	    }

	    var Mobify = window.Mobify = window.Mobify || {};

	    var Debug = Mobify.Debug = function(namespace) {
	        return new Debugger(namespace)
	    };

	    function Debugger(namespace) {
	        this.namespace = namespace
	    }

	    Debugger.prototype.log = function(callback) {
	        if (!isEnabled) {
	            return
	        }

	        if (typeof callback === "function") {
	            callback()
	        } else {
	            var args = [].slice.call(arguments);
	            //push namespace text at the beginning arguments
	            args.unshift(this.namespace + ": ");
	            console.log.apply(console, args);
	        }
	    };

	    /**
	     * is debugger enabled?
	     * @returns {boolean} - true if enabled
	     */
	    Debugger.prototype.isEnabled = function(){
	      return isEnabled;
	    };

	    if (isEnabled) {
	        console.log('Mobify Debug Mode is enabled!')
	    }

	})(window, document);


/***/ }),
/* 4 */
/***/ (function(module, exports, __webpack_require__) {

	var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
	  * domready (c) Dustin Diaz 2014 - License MIT
	  */
	!function (name, definition) {

	  if (typeof exports !== 'undefined' && this.exports !== exports) module.exports = definition(true)
	  else if (true) !(__WEBPACK_AMD_DEFINE_FACTORY__ = (definition), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))
	  else this[name] = definition()

	}('domready', function () {

	  if (!document.addEventListener) {
	    var ret = function() {};
	    ret.nodom = true;
	    return ret;
	  }

	  var fns = [], listener
	    , doc = document
	    , hack = doc.documentElement.doScroll
	    , domContentLoaded = 'DOMContentLoaded'
	    , loaded = (hack ? /^loaded|^c/ : /^loaded|^i|^c/).test(doc.readyState)


	  if (!loaded)
	  doc.addEventListener(domContentLoaded, listener = function () {
	    doc.removeEventListener(domContentLoaded, listener)
	    loaded = 1
	    while (listener = fns.shift()) listener()
	  })

	  return function (fn) {
	    loaded ? setTimeout(fn, 0) : fns.push(fn)
	  }

	})


/***/ }),
/* 5 */
/***/ (function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	    value: true
	});
	exports.clearDimensions = exports.getDimensions = exports.setDimension = exports.send = exports.callIntegration = exports.addIntegration = exports.Evt = undefined;

	var _utils = __webpack_require__(6);

	var utils = _interopRequireWildcard(_utils);

	function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /**
	                                                                                                                                                           * Send events to related downstream system
	                                                                                                                                                           *
	                                                                                                                                                           * @module analyticsSDK/events
	                                                                                                                                                           */

	var integrations = {};
	var dimensions = {};

	/**
	 * Event class which represent event getting sent to downstream integration
	 * @class
	 */

	var Evt =
	/**
	 * @param {Object} evt - an object representing the event to be sent
	 */
	exports.Evt = function Evt(evt) {
	    _classCallCheck(this, Evt);

	    this.evt = evt;
	};

	/**
	 * Add an integration downstream
	 *
	 * @param {String} name - Name of the integration
	 * @param {Object} integration - An object of the integration
	 */


	var addIntegration = exports.addIntegration = function addIntegration(name, integration) {
	    integrations[name] = integration;
	};

	/**
	 * Proxy call to integration
	 *
	 * @param {String} name - Name of integration
	 * @param {String} method - Method to call
	 * @param {Object} optional parameters to pass on
	 * @return Return from integrations
	 */
	var callIntegration = exports.callIntegration = function callIntegration(name, method) {
	    for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
	        args[_key - 2] = arguments[_key];
	    }

	    return integrations[name][method](args);
	};

	/**
	 * Send events to downstream integrations
	 *
	 * @param {Evt} - send event to all integrations
	 */
	var send = exports.send = function send(evt) {
	    for (var name in integrations) {
	        if (integrations.hasOwnProperty(name)) {
	            integrations[name].sendEvent(evt, dimensions);
	        }
	    }
	};

	/**
	 * Send events to downstream integrations
	 *
	 * @param {String} dimension
	 * @param {String} value
	 */
	var setDimension = exports.setDimension = function setDimension(dimName, value) {
	    dimensions[dimName] = value;
	    for (var name in integrations) {
	        if (integrations.hasOwnProperty(name)) {
	            integrations[name].setDimension(dimName, value);
	        }
	    }
	};

	/**
	 * Send events to downstream integrations
	 *
	 * @return Return current dimensions
	 */
	var getDimensions = exports.getDimensions = function getDimensions() {
	    return dimensions;
	};

	/**
	 * Clear dimensions
	 */
	var clearDimensions = exports.clearDimensions = function clearDimensions() {
	    // http://stackoverflow.com/questions/684575/how-to-quickly-clear-a-javascript-object
	    utils.inEach(dimensions, function (_, k) {
	        delete dimensions[k];
	    });
	};

/***/ }),
/* 6 */
/***/ (function(module, exports) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	    value: true
	});
	/**
	 * Internal helper functions
	 *
	 * @module utils
	 */
	var getElementsFromSelector = exports.getElementsFromSelector = function getElementsFromSelector(selector) {
	    try {
	        return document.querySelectorAll(selector);
	    } catch (e) {
	        // catch the illegal element exception
	        return null;
	    }
	};

	/**
	 * Check if value is null or undefined
	 * http://stackoverflow.com/questions/2559318/how-to-check-for-an-undefined-or-null-variable-in-javascript
	 *
	 * @private
	 */
	var isNullUndef = exports.isNullUndef = function isNullUndef(val) {
	    return typeof val === 'undefined' || val === null;
	};

	/**
	 * Polyfill for element matches
	 *
	 * Adapted from version at
	 * https://developer.mozilla.org/en/docs/Web/API/Element/matches
	 * @private
	 */
	var elementMatches = exports.elementMatches = function elementMatches(e, selector) {
	    if (e.matches) {
	        // this is the most common way to handle this
	        return e.matches(selector);
	    }
	    var matchAlias = ['matchesSelector', 'mozMatchesSelector', 'msMatchesSelector', 'oMatchesSelector', 'webkitMatchesSelector'];
	    for (var i = 0; i < matchAlias.length; i++) {
	        if (matchAlias[i] in e) {
	            return e[matchAlias[i]](selector);
	        }
	    }

	    // final solution
	    var matches = document.querySelectorAll(selector);

	    for (var _i = 0; _i < matches.length; _i++) {
	        if (matches.item(_i) === e) {
	            return true;
	        }
	    }
	    return false;
	};

	/**
	 * Similar to _.forEach
	 *
	 * A util function to avoid polyfill for Symbols
	 * Since `for (x of array)` syntax will require `Symbol` polyfill
	 *
	 * @private
	 */
	var forEach = exports.forEach = function forEach(array, callback) {
	    for (var i = 0; i < array.length; i++) {
	        callback(array[i], i, array);
	    }
	};

	/**
	 * Similar to _.forEach
	 *
	 * A util function to avoid polyfill for Symbols
	 * Since `for (x in array) ...hasOwnProperty` syntax
	 *
	 * @private
	 */
	var inEach = exports.inEach = function inEach(obj, callback) {
	    for (var key in obj) {
	        if (obj.hasOwnProperty(key)) {
	            callback(obj[key], key, obj);
	        }
	    }
	};

	/**
	 * Similar to _.filter
	 * This wraps around so we can use this on generic list,
	 * instead of just Array (e.g. return from queryAllSelectors)
	 *
	 * @private
	 */
	var filter = exports.filter = function filter(array, callback) {
	    return Array.prototype.filter.call(array, callback);
	};

	/**
	 * Similar to _.extend
	 *
	 * @private
	 */
	var extend = exports.extend = function extend(base) {
	    for (var _len = arguments.length, objs = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
	        objs[_key - 1] = arguments[_key];
	    }

	    forEach(objs, function (o) {
	        inEach(o, function (v, k) {
	            base[k] = v;
	        });
	    });
	};

	/**
	 * Similar to _.size
	 *
	 * @private
	 */
	var size = exports.size = function size(obj) {
	    var size = 0;
	    for (var key in obj) {
	        if (obj.hasOwnProperty(key)) {
	            size++;
	        }
	    }
	    return size;
	};

	/**
	 * Function for handling cross browser implementation for addEventListener
	 * On IE9 this require different implementation
	 *
	 * Reference: http://stackoverflow.com/questions/12783339/how-to-add-a-click-handler-without-using-jquery
	 *
	 * @private
	 */
	var addListener = exports.addListener = function addListener(elem, type, _fn) {
	    if (elem.addEventListener) {
	        elem.addEventListener(type, _fn, false);
	    } else if (elem.attachEvent) {
	        _fn = function fn() {
	            return _fn.call(elem, window.event);
	        };
	        elem.attachEvent('on' + type, _fn);
	    }
	    return _fn;
	};

	/**
	 * Function for handling cross browser implementation for removeEventListener
	 * On IE9 this require different implementation
	 *
	 * Reference: http://stackoverflow.com/questions/12783339/how-to-add-a-click-handler-without-using-jquery
	 *
	 * @private
	 */
	var removeListener = exports.removeListener = function removeListener(elem, type, fn) {
	    if (elem.removeEventListener) {
	        elem.removeEventListener(type, fn, false);
	    } else if (elem.detachEvent) {
	        elem.detachEvent('on' + type, fn);
	    }
	};

/***/ }),
/* 7 */
/***/ (function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	    value: true
	});
	exports.parseDimensionConfig = exports.parseCheckerDimensionConfig = undefined;

	__webpack_require__(3);

	var _utils = __webpack_require__(6);

	var utils = _interopRequireWildcard(_utils);

	var _configUtils = __webpack_require__(8);

	var configUtils = _interopRequireWildcard(_configUtils);

	function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

	var logger = window.Mobify.Debug('analytic-sdk');

	/**
	 * Given config of a particular checkerDimension, carry out the parsing
	 *
	 * @param eventType {String}
	 * @param eventConfig {String}
	 *
	 * @return a list of Capture to be considered
	 */
	var parseCheckerDimensionConfig = exports.parseCheckerDimensionConfig = function parseCheckerDimensionConfig(dimConfig, dimName, callback) {
	    var capturesToAdd = [];

	    utils.inEach(dimConfig, function (checkerConfig, dimValue) {

	        var selectorParser = new configUtils.SelectorsParser(checkerConfig, function (config) {
	            return config;
	        });

	        var selectorProcessor = function selectorProcessor(sel) {
	            var cmdSelector = null;
	            try {
	                cmdSelector = JSON.parse(sel.selector);
	                if (!cmdSelector) {
	                    throw 'No selector given';
	                }
	            } catch (e) {
	                logger.log('Invalid config extractor: ' + sel.selector);
	                return null;
	            }

	            var command = cmdSelector[0];
	            var selector = cmdSelector.slice(1);

	            if (command in configUtils.c.checker) {
	                var captureCallback = function captureCallback(self, elems, param) {
	                    var command = param.command,
	                        args = param.args,
	                        dimName = param.dimName,
	                        dimValue = param.dimValue;

	                    if (command === configUtils.c.checker.hasElement || command === configUtils.c.checker.itemCountBetween && args[0] <= elems.length <= args[1] || command === configUtils.c.checker.itemCountEqual && args[0] === elems.length || command === configUtils.c.checker.itemCountGreaterThan && args[0] < elems.length || command === configUtils.c.checker.itemCountLessThan && args[0] > elems.length) {
	                        callback(dimName, dimValue);
	                    }
	                    return dimValue;
	                };
	                var newCapture = new configUtils.Capture(new configUtils.Selector(selector[0], sel.lifeCycle, sel), {
	                    command: command,
	                    args: selector.slice(1),
	                    dimName: dimName,
	                    dimValue: dimValue
	                }, captureCallback);
	                capturesToAdd.push(newCapture);
	            } else if (command in configUtils.c.extractor) {
	                var _newCapture = configUtils.getCaptureForExtractor(sel, function (value) {
	                    if (!utils.isNullUndef(value)) {
	                        callback(dimName, dimValue);
	                    }
	                    return dimValue;
	                });
	                if (_newCapture) {
	                    capturesToAdd.push(_newCapture);
	                }
	            } else {
	                logger.log('Unkown checker type: ' + command);
	            }

	            return null;
	        };

	        selectorParser.forEachSelector(selectorProcessor);
	        return null;
	    });

	    return capturesToAdd;
	};

	var parseDimensionConfig = exports.parseDimensionConfig = function parseDimensionConfig(dimConfig, dimName, callback, targetElem) {

	    var capturesToAdd = [];

	    var selectorParser = new configUtils.SelectorsParser(dimConfig, function (config) {
	        return config;
	    });

	    selectorParser.forEachSelector(function (sel) {
	        var newCapture = configUtils.getCaptureForExtractor(sel, function (value) {
	            if (!utils.isNullUndef(value)) {
	                callback(dimName, value);
	            }
	            return value;
	        }, targetElem);
	        if (newCapture) {
	            capturesToAdd.push(newCapture);
	        }
	    });
	    return capturesToAdd;
	};

/***/ }),
/* 8 */
/***/ (function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	    value: true
	});
	exports.getCaptureForExtractor = exports.extractValueFromElement = exports.SelectorsParser = exports.Selector = exports.Capture = exports.isProgressive = exports.lifeCycle = exports.c = undefined;

	var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();

	__webpack_require__(3);

	var _utils = __webpack_require__(6);

	var utils = _interopRequireWildcard(_utils);

	function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	var logger = window.Mobify.Debug('analytic-sdk');

	var c = exports.c = {
	    extractor: {
	        /**
	         * Extract a item from an array of text elements
	         * Useful for breadcrumb parsing
	         *
	         *    textValueInArray('breadcrump', 2)
	         * @const
	         */
	        textValueInArray: 'textValueInArray',
	        /**
	         * Extract integer value
	         *
	         *   intValue('div.cartcount', 0) // default as 0
	         * @const
	         */
	        intValue: 'intValue',
	        /**
	         * Extract integer value and add addition value to it
	         *
	         *   intValue('div.cartcount', 0, 1) // default as 0
	         * @const
	         */
	        intAddValue: 'intAddValue',
	        /**
	         * Extract text value
	         *
	         *   textValue('input.search', 'default')
	         * @const
	         */
	        textValue: 'textValue',
	        /**
	         * Extract mapping
	         *
	         *   textValueMap('.stock-count', {
	         *      '/in stock/': 1,
	         *      '/out of stock/': 1
	         *   })
	         * @const
	         */
	        textValueMap: 'textValueMap',
	        /**
	         * Extract from URL regex group
	         *
	         *   urlRegex('/product/([^/]*)')
	         * @const
	         */
	        urlRegex: 'urlRegex',
	        /**
	         * Extract from title regex group
	         *
	         *   title('product:(.*)')
	         * @const
	         */
	        titleRegex: 'titleRegex'
	    },

	    checker: {
	        hasElement: 'hasElement',
	        itemCountBetween: 'itemCountBetween',
	        itemCountEqual: 'itemCountEqual',
	        itemCountGreaterThan: 'itemCountGreaterThan',
	        itemCountLessThan: 'itemCountLessThan'
	    },

	    elementTarget: {
	        getAttr: 'getAttr'
	    }
	};

	var lifeCycle = exports.lifeCycle = {
	    ASAP: 'ASAP',
	    DCL: 'DCL',
	    untilSeen: 'untilSeen',
	    monitor: 'monitor'

	    /**
	     * Tell if we are on PWA
	     */
	};var isProgressive = exports.isProgressive = function isProgressive() {
	    return window.Progressive &&
	    // Ensure we are not in non-PWA mode
	    !window.Progressive.PWADisabled;
	};

	/**
	 * A class representing individual capture to be ran
	 */

	var Capture = exports.Capture = function () {
	    /**
	     * @param {Selector} selector - selector object returned by parser
	     * @param {Object} param - specify the parameter used in callback
	     * @param {Function(self, elements, param)} callback - callback function when element is found
	     * @param {boolean} doDefault - callback function even if element is not found
	     */
	    function Capture(sel, param, callback, doDefault) {
	        _classCallCheck(this, Capture);

	        this.selector = sel.selector;
	        this.lifeCycle = sel.lifeCycle;
	        this.param = param;
	        this.callback = callback;
	        if (!callback) {
	            throw 'No callback provided';
	        }
	        this.elemValue = null;
	        this.doDefault = doDefault;
	        this.eventHooks = [];
	    }

	    /**
	     * @return  - return false if element is not found (in default case, if callback is called)
	     */


	    Capture.prototype.instrument = function instrument() {
	        var elems = utils.getElementsFromSelector(this.selector);
	        if (!(elems && elems.length)) {
	            // logger.log(`Cannot find element ${this.selector}`)
	            if (this.doDefault) {
	                this.callback(this, null, this.param);
	                return true;
	            }
	            return false;
	        }
	        // note that we need to explicitly pass in this parameter due to babel
	        // convert this param in callback into undefined
	        // http://stackoverflow.com/questions/34419450/self-invoking-argument-changing-this-to-undefined-in-babel-loader
	        var instrumentedElements = this.allElements();

	        var newElements = utils.filter(elems, function (e) {
	            return instrumentedElements.indexOf(e) === -1;
	        });

	        this.elemValue = this.callback(this, newElements, this.param);
	        return true;
	    };

	    Capture.prototype.hasValue = function hasValue() {
	        return !utils.isNullUndef(this.elemValue);
	    };

	    Capture.prototype.allElements = function allElements() {
	        return this.eventHooks.map(function (hook) {
	            return hook.elem;
	        });
	    };

	    Capture.prototype.applyToElements = function applyToElements(callback) {
	        utils.forEach(this.eventHooks, function (h) {
	            return callback(h.elem);
	        });
	    };

	    Capture.prototype.uninstrument = function uninstrument() {
	        utils.forEach(this.eventHooks, function (h) {
	            return utils.removeListener(h.elem, h.action, h.listener);
	        });
	        this.eventHooks = [];
	    };

	    /**
	     * An internal function for setting the listener for element
	     * Must be called if the callback set any listener (see events.js)
	     */


	    Capture.prototype.setListener = function setListener(elem, action, eventListener) {
	        var listener = utils.addListener(elem, action, eventListener);
	        this.eventHooks.push({ elem: elem, action: action, listener: listener });
	    };

	    return Capture;
	}();

	/**
	 * A class providing a list of selectors
	 */


	var Selector = exports.Selector = function Selector(selector, lc, config) {
	    _classCallCheck(this, Selector);

	    this.selector = selector;
	    this.lifeCycle = lc || lifeCycle.DCL;
	    if (config) {
	        this.action = config.action;
	        this.dimensions = config.dimensions;
	    }
	};

	/**
	 * Represent a class structure that is related to the selector
	 */


	var SelectorsParser = exports.SelectorsParser = function () {

	    /**
	     * Given a top level config structure, collapse callback on
	     * the given url
	     *
	         {
	            default {
	            },
	            components : {
	                PWA : {...}
	            }
	          }
	     *
	     * @param {Object} config
	     * @param {function} callback(config) -> list of selectors
	     * @return list of selectors
	     */
	    function SelectorsParser(config, getSelector) {
	        _classCallCheck(this, SelectorsParser);

	        this.selectors = [];
	        this.config = config;
	        this.selectedConfig = null;

	        this.parseConfig(config, getSelector);
	    }

	    SelectorsParser.prototype.parseConfig = function parseConfig(config, getSelector) {
	        var _this = this;

	        if (!(config && config.default)) {
	            logger.log('Error in parsing selectors ' + config);
	            return null;
	        }

	        var combinedConfig = this.selectedConfig = this.getSelectorByComponent(config);
	        if (combinedConfig.disable) {
	            return null;
	        }

	        var selectors = getSelector(combinedConfig);
	        if (!selectors) {
	            logger.log('No selector found ' + selectors);
	            return null;
	        }

	        var urlSelectorMatcher = function urlSelectorMatcher(urlSelector) {
	            var urlToMatch = document.location.pathname;
	            if (typeof urlSelector === 'string') {
	                // multiple selectors
	                // { default: ['selector1', 'selector2']}
	                _this.selectors.push(new Selector(urlSelector, combinedConfig.lifeCycle, combinedConfig));
	            } else {
	                var urlRegex = urlSelector.url;
	                if (urlRegex && !urlToMatch.match(urlRegex)) {
	                    return null;
	                }

	                if (typeof urlSelector.s === 'string') {
	                    // multiple selectors
	                    // { default: [{u: 'url'}, {s: 'selector2'}]})
	                    _this.selectors.push(new Selector(urlSelector.s, urlSelector.l || combinedConfig.lifeCycle, combinedConfig));
	                } else {
	                    // multiple selectors
	                    // { default: [{u: 'url'}, {s: ['selector1', 'selector2']}]})
	                    utils.forEach(urlSelector.s, function (s) {
	                        _this.selectors.push(new Selector(s, urlSelector.l || combinedConfig.lifeCycle, combinedConfig));
	                    });
	                }
	            }
	            return null;
	        };

	        if (typeof selectors === 'string') {
	            // basic string selector
	            // { default: 'selector'}
	            this.selectors = [new Selector(selectors, combinedConfig.lifeCycle, combinedConfig)];
	            return null;
	        } else if (Array.isArray(selectors)) {
	            // given an array of selector
	            // [{s:...},{s:....}]
	            utils.forEach(selectors, urlSelectorMatcher);
	        } else {
	            // given a single complex selector
	            // {s:...}
	            urlSelectorMatcher(selectors);
	        }

	        return this.selectors;
	    };

	    /**
	     * This function consume a block of the config file,
	     * and return the config you want to consider, dependent on components
	     * you are running
	     *
	     * @return config block to consider
	     */


	    SelectorsParser.prototype.getSelectorByComponent = function getSelectorByComponent(config) {
	        if (!config.components) {
	            return config.default;
	        }

	        var combinedConfig = null;
	        var chosenConfig = null;

	        if (isProgressive() && config.components.PWA) {
	            chosenConfig = config.components.PWA;
	        } else if (window.Adaptive && config.components.Adaptive) {
	            chosenConfig = config.components.Adaptive;
	        } else {
	            return config.default;
	        }

	        if (typeof config.default === 'string') {
	            combinedConfig = chosenConfig || config.default;
	        } else {
	            // If the subsequent config is not disable, override the base disable
	            if (!chosenConfig.disable) {
	                chosenConfig.disable = false;
	            }
	            combinedConfig = {};
	            utils.extend(combinedConfig, config.default, chosenConfig);
	        }
	        return combinedConfig;
	    };

	    SelectorsParser.prototype.forEachSelector = function forEachSelector(callback) {
	        if (!this.selectors) {
	            logger.log('No selector found!');
	            return;
	        }
	        utils.forEach(this.selectors, function (s) {
	            return callback(s);
	        });
	        return;
	    };

	    SelectorsParser.prototype.getDimensions = function getDimensions() {
	        return this.selectedConfig.dimensions;
	    };

	    return SelectorsParser;
	}();

	var getRegexMatch = function getRegexMatch(value, regex, defaultValue) {
	    if (!value) {
	        return null;
	    }
	    var matchedGroups = value.match(regex);
	    if (matchedGroups) {
	        return matchedGroups[1] || defaultValue;
	    }
	    return null;
	};

	/**
	 * Given an extract command, get value from element
	 *  e.g.
	 *    textValue('div.selector')
	 *
	 * @return value from element
	 */
	var extractValueFromElement = exports.extractValueFromElement = function extractValueFromElement(command, elems, args) {
	    if (command === c.extractor.textValue || command === c.extractor.intValue || command === c.extractor.intAddValue || command === c.extractor.textValueMap) {
	        var elemValue = '';

	        if (!elems) {
	            // no elements - return default
	            if (command === c.extractor.intAddValue) {
	                return args[0] + args[1];
	            } else if (command === c.extractor.textValue || command === c.extractor.textValueMap) {
	                return args[1];
	            }
	            return args[0];
	        }

	        if (elems[0].tagName === 'INPUT') {
	            elemValue = elems[0].value.trim();
	        } else {
	            elemValue = elems[0].textContent.trim();
	        }
	        if (command === c.extractor.intValue || command === c.extractor.intAddValue) {
	            elemValue = parseInt(elemValue);
	            if (isNaN(elemValue)) {
	                // default return
	                elemValue = args[0];
	            }
	            if (command === c.extractor.intAddValue) {
	                elemValue += args[1];
	            }
	        } else if (command === c.extractor.textValue) {
	            var regexExtract = args[0];
	            var defaultValue = args[1];
	            if (regexExtract) {
	                elemValue = getRegexMatch(elemValue, regexExtract, defaultValue);
	            }
	        } else if (command === c.extractor.textValueMap) {
	            var regexExtractMap = args[0];
	            var _defaultValue = args[1];
	            if (regexExtractMap) {
	                var valueToMatch = elemValue;
	                elemValue = _defaultValue;
	                utils.inEach(regexExtractMap, function (value, regexExtract) {
	                    if (getRegexMatch(valueToMatch, regexExtract, true)) {
	                        elemValue = value;
	                    }
	                });
	            } else {
	                logger.log('Missing valueMap for textValueMap extractor');
	                elemValue = null;
	            }
	        }

	        return elemValue;
	    } else if (command === c.extractor.textValueInArray) {
	        if (!elems) {
	            // no elements - return default
	            return args[1];
	        }
	        var elem = args[0] >= 0 ? elems[args[0]] : elems[elems.length + args[0]];
	        if (elem) {
	            return elem.textContent.trim();
	        }
	    } else {
	        logger.log('Invalid config unknown extractor type: ' + command);
	    }
	    return null;
	};

	/**
	 * Extract a value given a extractor
	 * e.g.
	 *
	 *     ASDK.extractor.intValue('.mini-cart count')
	 *
	 * @return new capture
	 */
	var getCaptureForExtractor = exports.getCaptureForExtractor = function getCaptureForExtractor(sel, setDimCallback, targetElem) {
	    var cmdSelector = null;
	    var newCapture = null;
	    var valueExtractor = sel.selector;
	    try {
	        cmdSelector = JSON.parse(valueExtractor);
	        if (!cmdSelector) {
	            throw 'No selector given';
	        }
	    } catch (e) {
	        logger.log('Invalid config extractor: ' + valueExtractor);
	        return null;
	    }
	    var command = cmdSelector[0];
	    var selector = cmdSelector.slice(1);

	    if (command === c.extractor.urlRegex || command === c.extractor.titleRegex) {
	        newCapture = new Capture(new Selector('head', lifeCycle.ASAP), {
	            regex: selector[0],
	            command: command
	        }, function (self, es, params) {
	            var regex = params.regex,
	                command = params.command;

	            var text = command === c.extractor.urlRegex ? document.location.pathname : document.title;

	            var regexResult = getRegexMatch(text, regex, true);
	            if (regexResult) {
	                // we set the dimension immediately - no need for captureGroup
	                setDimCallback(regexResult);
	            }
	            return regexResult;
	        }, true);
	    } else if (command === c.elementTarget.getAttr) {
	        // this set of commands parse against element target
	        if (!targetElem) {
	            throw 'getAttr must only be used in dimension';
	        }

	        var _selector = _slicedToArray(selector, 2),
	            attrName = _selector[0],
	            filterSelectors = _selector[1];

	        if (filterSelectors) {
	            var foundMatch = false;
	            utils.forEach(filterSelectors, function (s) {
	                if (utils.elementMatches(targetElem, s)) {
	                    foundMatch = true;
	                }
	            });
	            if (!foundMatch) {
	                return null;
	            }
	        }

	        newCapture = new Capture(new Selector('head', lifeCycle.ASAP), {
	            value: targetElem[attrName]
	        }, function (self, es, params) {
	            var value = params.value;

	            if (value) {
	                setDimCallback(value);
	            }
	            return value;
	        }, true);
	    } else {
	        var captureCallback = function captureCallback(self, elems, param) {
	            var command = param.command,
	                args = param.args;

	            var value = extractValueFromElement(command, elems, args);
	            setDimCallback(value);
	            return value;
	        };
	        newCapture = new Capture(new Selector(selector[0], sel.lifeCycle), {
	            command: command,
	            args: selector.slice(1)
	        }, captureCallback, true);
	    }

	    return newCapture;
	};

/***/ }),
/* 9 */
/***/ (function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	    value: true
	});
	exports.parseEventConfig = undefined;

	__webpack_require__(3);

	var _utils = __webpack_require__(6);

	var utils = _interopRequireWildcard(_utils);

	var _events = __webpack_require__(5);

	var eventSender = _interopRequireWildcard(_events);

	var _dimensions = __webpack_require__(7);

	var dimensionsModule = _interopRequireWildcard(_dimensions);

	var _configUtils = __webpack_require__(8);

	var configUtils = _interopRequireWildcard(_configUtils);

	function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

	var logger = window.Mobify.Debug('analytic-sdk');

	/**
	 * Given config of a particular eventType, carry out the parsing
	 *
	 *      addToCart: {
	 *          default: {....}
	 *      }
	 *
	 * @param eventType {String}
	 * @param eventConfig {String}
	 *
	 * @return a list of Capture to be considered
	 */
	var parseEventConfig = exports.parseEventConfig = function parseEventConfig(eventConfig, eventType) {
	    // const eventLifeCycle = eventConfig.default.instrumentLifeCycle
	    var selectorParser = new configUtils.SelectorsParser(eventConfig, function (config) {
	        return config.selectors;
	    });

	    var getEventListener = function getEventListener() {
	        return function (evt) {
	            var eventToSend = {
	                action: eventType
	            };

	            try {
	                if (eventConfig.default.dimensions) {
	                    var componentDimension = selectorParser.getDimensions();
	                    utils.inEach(componentDimension, function (dimConfig, dimName) {
	                        var captures = dimensionsModule.parseDimensionConfig({ default: dimConfig }, dimName, function (d, v) {
	                            eventToSend[d] = v;
	                        }, evt.target);
	                        // acquire the captures related to the dimension and execute
	                        if (captures && !utils.isNullUndef(captures[0])) {
	                            captures[0].instrument();
	                        }
	                        return true;
	                    });
	                }
	                eventSender.send(eventToSend);
	            } catch (e) {
	                if (console) {
	                    console.error('Error in handling event ' + eventToSend + ': ' + e);
	                }
	            }
	        };
	    };

	    var capturesToAdd = [];

	    selectorParser.forEachSelector(function (eventSelector) {
	        var capture = new configUtils.Capture(eventSelector, {
	            eventType: eventType,
	            eventAction: eventSelector.action
	        }, function (self, elems, param) {
	            logger.log('Instrumenting element ' + param.eventType + '.' + param.eventAction + ' with ' + elems.length + ' elements');
	            utils.forEach(elems, function (elem) {
	                self.setListener(elem, param.eventAction, getEventListener());
	            });
	            return true;
	        });

	        capturesToAdd.push(capture);
	    });

	    return capturesToAdd;
	};

/***/ }),
/* 10 */
/***/ (function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	    value: true
	});
	exports.test = exports.assertEventSentOnce = exports.assertDimensionNotNull = exports.assertDimension = exports.assertEventSent = exports.inputSelect = exports.fireEvent = exports.click = exports.setTest = exports.isTest = undefined;

	var _promisePolyfill = __webpack_require__(11);

	var _promisePolyfill2 = _interopRequireDefault(_promisePolyfill);

	var _utils = __webpack_require__(6);

	var utils = _interopRequireWildcard(_utils);

	var _events = __webpack_require__(5);

	var events = _interopRequireWildcard(_events);

	function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	var logger = window.Mobify.Debug('analytic-sdk'); /**
	                                                   * Provide testing interface for AnalyticsSDK
	                                                   *
	                                                   * @module analyticsSDK/t
	                                                   */


	var eventsSent = [];
	var result = {};

	var logResult = function logResult(msg) {
	    window.console && console.log(msg);
	};

	var captureEvents = function captureEvents(evt) {
	    logger.log('[TEST] Recieved event: ' + evt.actionName);
	    eventsSent.push(evt);
	};

	var isTest = exports.isTest = false;

	/**
	 * Set the test mode
	 */
	var setTest = exports.setTest = function setTest() {
	    exports.isTest = isTest = true;
	};

	/**
	 * Click a specific element
	 *
	 * @params {String} selector - selector to click
	 * @return {DOMElement}
	 */
	var click = exports.click = function click(selector) {
	    var elem = utils.getElementsFromSelector(selector);
	    logger.log('[TEST] Clicking on element ' + selector);
	    utils.forEach(elem, function (e) {
	        e.click();
	    });
	    return elem;
	};

	/**
	 * Fire an event for element
	 * http://stackoverflow.com/questions/2856513/how-can-i-trigger-an-onchange-event-manually
	 */
	var fireEvent = exports.fireEvent = function fireEvent(element, evtName) {
	    if ('createEvent' in document) {
	        var evt = document.createEvent('HTMLEvents');
	        evt.initEvent(evtName, false, true);
	        element.dispatchEvent(evt);
	    } else {
	        element.fireEvent('on' + evtName);
	    }
	};

	/**
	 * Interact with and input on specific elemeent
	 */
	var inputSelect = exports.inputSelect = function inputSelect(selector, value) {
	    var elem = utils.getElementsFromSelector(selector);
	    logger.log('[TEST] Selecting on element ' + selector);
	    utils.forEach(elem, function (e) {
	        fireEvent(e, 'focus');
	        if (value) {
	            e.value = value;
	        }
	        fireEvent(e, 'blur');
	    });
	    return elem;
	};

	/**
	 * Assert that we only receive multiple events
	 *
	 * @params {String} actionName - Name of the action
	 * @params {Object} dimensions - Object of the dimensions
	 * @params {Integer} expectCount - How many events are we expecting
	 * @params {Integer} timeout - How long we would measure the double send
	 */
	var assertEventSent = exports.assertEventSent = function assertEventSent(actionName, dimensions, expectCount, timeout) {

	    timeout = timeout || 1000;

	    return new _promisePolyfill2.default(function (resolve) {
	        setTimeout(function () {
	            var count = eventsSent.length;
	            logger.log('[TEST] Seen ' + count + ' ' + actionName + ' events');
	            if (count !== expectCount) {
	                logResult('\u274C Seen ' + count + ' ' + actionName + ' events when expecting ' + expectCount);
	                result.failed += 1;
	            } else {
	                logResult('\u2705 Seen ' + count + ' ' + actionName + ' events sent');
	                result.passed += 1;
	            }
	            resolve();
	        }, timeout);
	    });
	};

	/**
	 * Assert a dimension is set correctly
	 *
	 * @params {String} dimensionName - Name of the dimension
	 * @params {String} expectedValue - Expected value of the dimension
	 */
	var assertDimension = exports.assertDimension = function assertDimension(dimensionName, expectedValue) {

	    var dimensions = events.getDimensions();
	    var valueSeen = dimensions[dimensionName];

	    return new _promisePolyfill2.default(function (resolve) {
	        if (valueSeen === expectedValue) {
	            logResult('\u2705 Dimension ' + dimensionName + ' is correct - ' + valueSeen);
	            result.passed += 1;
	        } else {
	            logResult('\u274C Seen ' + dimensionName + ' as ' + valueSeen + ' when expecting ' + expectedValue);
	            result.failed += 1;
	        }
	        resolve();
	    });
	};

	/**
	 * Assert a dimension is not null or undefined
	 *
	 * @params {String} dimensionName - Name of the dimension
	 */
	var assertDimensionNotNull = exports.assertDimensionNotNull = function assertDimensionNotNull(dimensionName) {

	    var dimensions = events.getDimensions();
	    var valueSeen = dimensions[dimensionName];

	    return new _promisePolyfill2.default(function (resolve) {
	        if (typeof valueSeen === 'string' || typeof valueSeen === 'number') {
	            logResult('\u2705 Dimension ' + dimensionName + ' is defined - ' + valueSeen);
	            result.passed += 1;
	        } else {
	            logResult('\u274C Dimension ' + dimensionName + ' is not defined');
	            result.failed += 1;
	        }
	        resolve();
	    });
	};

	/**
	 * Assert that we only receive only one event so far from the test
	 *
	 * @params {String} actionName - Name of the action
	 * @params {Object} dimensions - Object of the dimensions
	 * @params {Integer} timeout - How long we would measure the double send
	 */
	var assertEventSentOnce = exports.assertEventSentOnce = function assertEventSentOnce(actionName, dimensions, timeout) {
	    return assertEventSent(actionName, dimensions, 1, timeout);
	};

	/**
	 * Run the test with analytics
	 *
	 * @params {Array} testSpecs - array of test objects
	 * @params {Function} resultCollector - callback which will recieve results on finish - take a done function
	 * @params {string} url - specify url to test
	 * @params {string} testToRun - specify eventName to test
	 */
	var test = exports.test = function test(testSpecs, resultCollector, url, testToRun) {

	    eventsSent.length = 0;
	    result = {
	        testRan: 0,
	        passed: 0,
	        failed: 0
	    };

	    events.callIntegration('debugger', 'setCallback', captureEvents);

	    var chainPromise = new _promisePolyfill2.default(function (r) {
	        return r();
	    });

	    utils.forEach(testSpecs, function (spec) {
	        var urlToMatch = spec.url;
	        var testName = spec.testName;
	        var testFunction = spec.test;

	        if (testToRun && testToRun !== testName || url && url !== urlToMatch) {
	            logResult('[TEST] Skipping test ' + testName + ' @ ' + urlToMatch + '...');
	            return;
	        }

	        logResult('[TEST] Running test for ' + testName + '...');
	        result.testRan += 1;
	        chainPromise = chainPromise.then(function () {
	            return new _promisePolyfill2.default(function (resolve) {
	                testFunction(resolve);
	            });
	        });
	    });

	    chainPromise.then(function () {
	        if (resultCollector) {
	            resultCollector(result);
	        }
	    });
	};

/***/ }),
/* 11 */
/***/ (function(module, exports) {

	(function (root) {

	  // Store setTimeout reference so promise-polyfill will be unaffected by
	  // other code modifying setTimeout (like sinon.useFakeTimers())
	  var setTimeoutFunc = setTimeout;

	  function noop() {}
	  
	  // Polyfill for Function.prototype.bind
	  function bind(fn, thisArg) {
	    return function () {
	      fn.apply(thisArg, arguments);
	    };
	  }

	  function Promise(fn) {
	    if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new');
	    if (typeof fn !== 'function') throw new TypeError('not a function');
	    this._state = 0;
	    this._handled = false;
	    this._value = undefined;
	    this._deferreds = [];

	    doResolve(fn, this);
	  }

	  function handle(self, deferred) {
	    while (self._state === 3) {
	      self = self._value;
	    }
	    if (self._state === 0) {
	      self._deferreds.push(deferred);
	      return;
	    }
	    self._handled = true;
	    Promise._immediateFn(function () {
	      var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
	      if (cb === null) {
	        (self._state === 1 ? resolve : reject)(deferred.promise, self._value);
	        return;
	      }
	      var ret;
	      try {
	        ret = cb(self._value);
	      } catch (e) {
	        reject(deferred.promise, e);
	        return;
	      }
	      resolve(deferred.promise, ret);
	    });
	  }

	  function resolve(self, newValue) {
	    try {
	      // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
	      if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.');
	      if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
	        var then = newValue.then;
	        if (newValue instanceof Promise) {
	          self._state = 3;
	          self._value = newValue;
	          finale(self);
	          return;
	        } else if (typeof then === 'function') {
	          doResolve(bind(then, newValue), self);
	          return;
	        }
	      }
	      self._state = 1;
	      self._value = newValue;
	      finale(self);
	    } catch (e) {
	      reject(self, e);
	    }
	  }

	  function reject(self, newValue) {
	    self._state = 2;
	    self._value = newValue;
	    finale(self);
	  }

	  function finale(self) {
	    if (self._state === 2 && self._deferreds.length === 0) {
	      Promise._immediateFn(function() {
	        if (!self._handled) {
	          Promise._unhandledRejectionFn(self._value);
	        }
	      });
	    }

	    for (var i = 0, len = self._deferreds.length; i < len; i++) {
	      handle(self, self._deferreds[i]);
	    }
	    self._deferreds = null;
	  }

	  function Handler(onFulfilled, onRejected, promise) {
	    this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
	    this.onRejected = typeof onRejected === 'function' ? onRejected : null;
	    this.promise = promise;
	  }

	  /**
	   * Take a potentially misbehaving resolver function and make sure
	   * onFulfilled and onRejected are only called once.
	   *
	   * Makes no guarantees about asynchrony.
	   */
	  function doResolve(fn, self) {
	    var done = false;
	    try {
	      fn(function (value) {
	        if (done) return;
	        done = true;
	        resolve(self, value);
	      }, function (reason) {
	        if (done) return;
	        done = true;
	        reject(self, reason);
	      });
	    } catch (ex) {
	      if (done) return;
	      done = true;
	      reject(self, ex);
	    }
	  }

	  Promise.prototype['catch'] = function (onRejected) {
	    return this.then(null, onRejected);
	  };

	  Promise.prototype.then = function (onFulfilled, onRejected) {
	    var prom = new (this.constructor)(noop);

	    handle(this, new Handler(onFulfilled, onRejected, prom));
	    return prom;
	  };

	  Promise.all = function (arr) {
	    var args = Array.prototype.slice.call(arr);

	    return new Promise(function (resolve, reject) {
	      if (args.length === 0) return resolve([]);
	      var remaining = args.length;

	      function res(i, val) {
	        try {
	          if (val && (typeof val === 'object' || typeof val === 'function')) {
	            var then = val.then;
	            if (typeof then === 'function') {
	              then.call(val, function (val) {
	                res(i, val);
	              }, reject);
	              return;
	            }
	          }
	          args[i] = val;
	          if (--remaining === 0) {
	            resolve(args);
	          }
	        } catch (ex) {
	          reject(ex);
	        }
	      }

	      for (var i = 0; i < args.length; i++) {
	        res(i, args[i]);
	      }
	    });
	  };

	  Promise.resolve = function (value) {
	    if (value && typeof value === 'object' && value.constructor === Promise) {
	      return value;
	    }

	    return new Promise(function (resolve) {
	      resolve(value);
	    });
	  };

	  Promise.reject = function (value) {
	    return new Promise(function (resolve, reject) {
	      reject(value);
	    });
	  };

	  Promise.race = function (values) {
	    return new Promise(function (resolve, reject) {
	      for (var i = 0, len = values.length; i < len; i++) {
	        values[i].then(resolve, reject);
	      }
	    });
	  };

	  // Use polyfill for setImmediate for performance gains
	  Promise._immediateFn = (typeof setImmediate === 'function' && function (fn) { setImmediate(fn); }) ||
	    function (fn) {
	      setTimeoutFunc(fn, 0);
	    };

	  Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) {
	    if (typeof console !== 'undefined' && console) {
	      console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console
	    }
	  };

	  /**
	   * Set the immediate function to execute callbacks
	   * @param fn {function} Function to execute
	   * @deprecated
	   */
	  Promise._setImmediateFn = function _setImmediateFn(fn) {
	    Promise._immediateFn = fn;
	  };

	  /**
	   * Change the function to execute on unhandled rejection
	   * @param {function} fn Function to execute on unhandled rejection
	   * @deprecated
	   */
	  Promise._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) {
	    Promise._unhandledRejectionFn = fn;
	  };
	  
	  if (typeof module !== 'undefined' && module.exports) {
	    module.exports = Promise;
	  } else if (!root.Promise) {
	    root.Promise = Promise;
	  }

	})(this);


/***/ }),
/* 12 */
/***/ (function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	    value: true
	});

	var _utils = __webpack_require__(6);

	var utils = _interopRequireWildcard(_utils);

	function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	/**
	 * Sandy integration - responsible for sending events to sandy
	 *
	 * @module analyticsSDK/integrations/sandy
	 */
	var logger = window.Mobify.Debug('analytic-sdk');

	var SandyIntegration = function () {
	    function SandyIntegration() {
	        _classCallCheck(this, SandyIntegration);
	    }

	    /**
	     * Function to send event to sandy
	     *
	     * @param {Event} evt - Event to be taken by sandy
	     * @return {Boolean} - if event is successfully sent
	     */
	    SandyIntegration.prototype.sendEvent = function sendEvent(evt) {
	        var _this = this;

	        if (!window.sandy) {
	            logger.log('WARN: no sandy initialized');
	            return false;
	        }

	        var tracker = window.sandy;
	        var action = null;
	        var dimensions = {};
	        utils.inEach(evt, function (v, k) {
	            if (k === 'action') {
	                action = v;
	            } else {
	                dimensions[k] = v;
	            }
	        });

	        if (!action) {
	            logger.log('WARN: no action specified for ' + JSON.stringify(evt));
	            return false;
	        }
	        utils.inEach(dimensions, function (v, k) {
	            return _this.setDimension(k, v);
	        });
	        // sink event to timing table (currently our all in one sink for misc events)
	        tracker('send', 'event', 'timing', action);
	        return true;
	    };

	    /**
	     * Set dimension for downstream events
	     *
	     * @param {String} dimension
	     * @param {String} value
	     * @return {Boolean} - if event is successfully sent
	     */


	    SandyIntegration.prototype.setDimension = function setDimension(dimension, value) {
	        if (!window.sandy) {
	            return;
	        }
	        window.sandy('set', dimension, value);
	    };

	    return SandyIntegration;
	}();

	exports.default = SandyIntegration;

/***/ }),
/* 13 */
/***/ (function(module, exports) {

	"use strict";

	Object.defineProperty(exports, "__esModule", {
	    value: true
	});

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	/**
	 * Note we dont use mobify-debug-js here
	 * Since this is already triggered using `setDebug()` call, this eliminate the
	 * need to manually add `MOBIFY_DEBUG=1` to the url
	 *
	 * @private
	 */
	var log = function log() {
	    if (window.console) {
	        var _window$console;

	        (_window$console = window.console).log.apply(_window$console, arguments);
	    }
	};

	/**
	 * Debugger integration - provide debugging experience for SDK
	 *
	 * @module analyticsSDK/integrations/debugger
	 */

	var DebuggerIntegration = function () {
	    function DebuggerIntegration(options) {
	        _classCallCheck(this, DebuggerIntegration);

	        this.callback = (options || {}).callback;
	        this.dimensions = {};
	    }

	    /**
	     * Function to log events sent to Sandy
	     *
	     * @param {Event} evt - Event to be taken by sandy
	     * @return {Boolean} - if event is successfully sent
	     */


	    DebuggerIntegration.prototype.sendEvent = function sendEvent(evt, dimensions) {
	        log("[EVENTS] \uD83D\uDCA1 Sending event: " + evt.action + " (" + JSON.stringify(evt) + ")\uD83D\uDCA1");
	        if (this.callback) {
	            this.callback(evt, dimensions);
	        }
	        return true;
	    };

	    /**
	     * Set dimension for downstream events
	     *
	     * @param {String} dimension
	     * @param {String} value
	     * @return {Boolean} - if event is successfully sent
	     */


	    DebuggerIntegration.prototype.setDimension = function setDimension(dimension, value) {
	        log("[DIMENSION] \uD83D\uDCA1 Setting dimension: " + JSON.stringify(dimension) + " \uD83D\uDCA1");
	        this.dimensions[dimension] = value;
	        return true;
	    };

	    /**
	     * Setting callback to be called on sendEvent
	     * @param {Function(event)} callback - function to be called
	     */


	    DebuggerIntegration.prototype.setCallback = function setCallback(callbacks) {
	        // TODO: allow multiple callbacks
	        var callback = callbacks[0];
	        log("Setting callback: " + callback);
	        this.callback = callback;
	    };

	    return DebuggerIntegration;
	}();

	exports.default = DebuggerIntegration;

/***/ })
/******/ ])
});
;