From d45f7746ac174146dbfc0fc04628dea3369a859a Mon Sep 17 00:00:00 2001 From: palak Date: Fri, 29 Sep 2017 12:18:15 +0530 Subject: [PATCH] file add --- dist/angular-google-analytics.js | 1299 ++++++++++++++++++++++++++++++++++ dist/angular-google-analytics.min.js | 9 + 2 files changed, 1308 insertions(+) create mode 100644 dist/angular-google-analytics.js create mode 100644 dist/angular-google-analytics.min.js diff --git a/dist/angular-google-analytics.js b/dist/angular-google-analytics.js new file mode 100644 index 0000000..7a9fb30 --- /dev/null +++ b/dist/angular-google-analytics.js @@ -0,0 +1,1299 @@ +/** + * Angular Google Analytics - Easy tracking for your AngularJS application + * @version v1.1.8 - 2016-12-30 + * @link http://github.com/revolunet/angular-google-analytics + * @author Julien Bouquillon (https://github.com/revolunet) + * @contributors Julien Bouquillon (https://github.com/revolunet),Justin Saunders (https://github.com/justinsa),Chris Esplin (https://github.com/deltaepsilon),Adam Misiorny (https://github.com/adam187) + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +/* globals define */ +(function (root, factory) { + 'use strict'; + if (typeof module !== 'undefined' && module.exports) { + if (typeof angular === 'undefined') { + factory(require('angular')); + } else { + factory(angular); + } + module.exports = 'angular-google-analytics'; + } else if (typeof define === 'function' && define.amd) { + define(['angular'], factory); + } else { + factory(root.angular); + } +}(this, function (angular, undefined) { + 'use strict'; + angular.module('angular-google-analytics', []) + .provider('Analytics', function () { + var accounts, + analyticsJS = true, + cookieConfig = 'auto', // DEPRECATED + created = false, + crossDomainLinker = false, + crossLinkDomains, + currency = 'USD', + debugMode = false, + delayScriptTag = false, + displayFeatures = false, + disableAnalytics = false, + domainName, + ecommerce = false, + enhancedEcommerce = false, + enhancedLinkAttribution = false, + experimentId, + ignoreFirstPageLoad = false, + logAllCalls = false, + hybridMobileSupport = false, + offlineMode = false, + pageEvent = '$routeChangeSuccess', + readFromRoute = false, + removeRegExp, + testMode = false, + traceDebuggingMode = false, + trackPrefix = '', + trackRoutes = true, + trackUrlParams = false; + + this.log = []; + this.offlineQueue = []; + + /** + * Configuration Methods + **/ + + this.setAccount = function (tracker) { + if (angular.isUndefined(tracker) || tracker === false) { + accounts = undefined; + } else if (angular.isArray(tracker)) { + accounts = tracker; + } else if (angular.isObject(tracker)) { + accounts = [tracker]; + } else { + // In order to preserve an existing behavior with how the _trackEvent function works, + // the trackEvent property must be set to true when there is only a single tracker. + accounts = [{ tracker: tracker, trackEvent: true }]; + } + return this; + }; + + this.trackPages = function (val) { + trackRoutes = !!val; + return this; + }; + + this.trackPrefix = function (prefix) { + trackPrefix = prefix; + return this; + }; + + this.setDomainName = function (domain) { + domainName = domain; + return this; + }; + + this.useDisplayFeatures = function (val) { + displayFeatures = !!val; + return this; + }; + + this.useAnalytics = function (val) { + analyticsJS = !!val; + return this; + }; + + this.useEnhancedLinkAttribution = function (val) { + enhancedLinkAttribution = !!val; + return this; + }; + + this.useCrossDomainLinker = function (val) { + crossDomainLinker = !!val; + return this; + }; + + this.setCrossLinkDomains = function (domains) { + crossLinkDomains = domains; + return this; + }; + + this.setPageEvent = function (name) { + pageEvent = name; + return this; + }; + + /* DEPRECATED */ + this.setCookieConfig = function (config) { + cookieConfig = config; + return this; + }; + + this.useECommerce = function (val, enhanced) { + ecommerce = !!val; + enhancedEcommerce = !!enhanced; + return this; + }; + + this.setCurrency = function (currencyCode) { + currency = currencyCode; + return this; + }; + + this.setRemoveRegExp = function (regex) { + if (regex instanceof RegExp) { + removeRegExp = regex; + } + return this; + }; + + this.setExperimentId = function (id) { + experimentId = id; + return this; + }; + + this.ignoreFirstPageLoad = function (val) { + ignoreFirstPageLoad = !!val; + return this; + }; + + this.trackUrlParams = function (val) { + trackUrlParams = !!val; + return this; + }; + + this.disableAnalytics = function (val) { + disableAnalytics = !!val; + return this; + }; + + this.setHybridMobileSupport = function (val) { + hybridMobileSupport = !!val; + return this; + }; + + this.startOffline = function (val) { + offlineMode = !!val; + if (offlineMode === true) { + this.delayScriptTag(true); + } + return this; + }; + + this.delayScriptTag = function (val) { + delayScriptTag = !!val; + return this; + }; + + this.logAllCalls = function (val) { + logAllCalls = !!val; + return this; + }; + + this.enterTestMode = function () { + testMode = true; + return this; + }; + + this.enterDebugMode = function (enableTraceDebugging) { + debugMode = true; + traceDebuggingMode = !!enableTraceDebugging; + return this; + }; + + // Enable reading page url from route object + this.readFromRoute = function(val) { + readFromRoute = !!val; + return this; + }; + + /** + * Public Service + */ + this.$get = ['$document', // To read page title + '$location', // + '$log', // + '$rootScope',// + '$window', // + '$injector', // To access ngRoute module without declaring a fixed dependency + function ($document, $location, $log, $rootScope, $window, $injector) { + var that = this; + + /** + * Side-effect Free Helper Methods + **/ + + var isPropertyDefined = function (key, config) { + return angular.isObject(config) && angular.isDefined(config[key]); + }; + + var isPropertySetTo = function (key, config, value) { + return isPropertyDefined(key, config) && config[key] === value; + }; + + var generateCommandName = function (commandName, config) { + if (angular.isString(config)) { + return config + '.' + commandName; + } + return isPropertyDefined('name', config) ? (config.name + '.' + commandName) : commandName; + }; + + // Try to read route configuration and log warning if not possible + var $route = {}; + if (readFromRoute) { + if (!$injector.has('$route')) { + $log.warn('$route service is not available. Make sure you have included ng-route in your application dependencies.'); + } else { + $route = $injector.get('$route'); + } + } + + // Get url for current page + var getUrl = function () { + // Using ngRoute provided tracking urls + if (readFromRoute && $route.current && ('pageTrack' in $route.current)) { + return $route.current.pageTrack; + } + + // Otherwise go the old way + var url = trackUrlParams ? $location.url() : $location.path(); + return removeRegExp ? url.replace(removeRegExp, '') : url; + }; + + var getUtmParams = function () { + var utmToCampaignVar = { + utm_source: 'campaignSource', + utm_medium: 'campaignMedium', + utm_term: 'campaignTerm', + utm_content: 'campaignContent', + utm_campaign: 'campaignName' + }; + var object = {}; + + angular.forEach($location.search(), function (value, key) { + var campaignVar = utmToCampaignVar[key]; + + if (angular.isDefined(campaignVar)) { + object[campaignVar] = value; + } + }); + + return object; + }; + + /** + * get ActionFieldObject + * https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce#action-data + * @param id + * @param affliation + * @param revenue + * @param tax + * @param shipping + * @param coupon + * @param list + * @param step + * @param option + */ + var getActionFieldObject = function (id, affiliation, revenue, tax, shipping, coupon, list, step, option) { + var obj = {}; + if (id) { obj.id = id; } + if (affiliation) { obj.affiliation = affiliation; } + if (revenue) { obj.revenue = revenue; } + if (tax) { obj.tax = tax; } + if (shipping) { obj.shipping = shipping; } + if (coupon) { obj.coupon = coupon; } + if (list) { obj.list = list; } + if (step) { obj.step = step; } + if (option) { obj.option = option; } + return obj; + }; + + /** + * Private Methods + */ + + var _getProtocol = function (httpPostfix, httpsPostfix) { + var protocol = '', + isSslEnabled = document.location.protocol === 'https:', + isChromeExtension = document.location.protocol === 'chrome-extension:', + isHybridApplication = analyticsJS === true && hybridMobileSupport === true; + httpPostfix = angular.isString(httpPostfix) ? httpPostfix : ''; + httpsPostfix = angular.isString(httpsPostfix) ? httpsPostfix : ''; + if (httpPostfix !== '') { + protocol = 'http:' + httpPostfix; + } + if (isChromeExtension || isHybridApplication || (isSslEnabled && httpsPostfix !== '')) { + protocol = 'https:' + httpsPostfix; + } + return protocol; + }; + + var _gaJs = function (fn) { + if (!analyticsJS && $window._gaq && typeof fn === 'function') { + fn(); + } + }; + + var _gaq = function () { + var args = Array.prototype.slice.call(arguments); + if (offlineMode === true) { + that.offlineQueue.push([_gaq, args]); + return; + } + if (!$window._gaq) { + $window._gaq = []; + } + if (logAllCalls === true) { + that._log.apply(that, args); + } + $window._gaq.push(args); + }; + + var _analyticsJs = function (fn) { + if (analyticsJS && $window.ga && typeof fn === 'function') { + fn(); + } + }; + + var _ga = function () { + var args = Array.prototype.slice.call(arguments); + if (offlineMode === true) { + that.offlineQueue.push([_ga, args]); + return; + } + if (typeof $window.ga !== 'function') { + that._log('warn', 'ga function not set on window'); + return; + } + if (logAllCalls === true) { + that._log.apply(that, args); + } + $window.ga.apply(null, args); + }; + + var _gaMultipleTrackers = function (includeFn) { + // Drop the includeFn from the arguments and preserve the original command name + var args = Array.prototype.slice.call(arguments, 1), + commandName = args[0], + trackers = []; + if (typeof includeFn === 'function') { + accounts.forEach(function (account) { + if (includeFn(account)) { + trackers.push(account); + } + }); + } else { + // No include function indicates that all accounts are to be used + trackers = accounts; + } + + // To preserve backwards compatibility fallback to _ga method if no account + // matches the specified includeFn. This preserves existing behaviors by + // performing the single tracker operation. + if (trackers.length === 0) { + _ga.apply(that, args); + return; + } + + trackers.forEach(function (tracker) { + // Check tracker 'select' function, if it exists, for whether the tracker should be used with the current command. + // If the 'select' function returns false then the tracker will not be used with the current command. + if (isPropertyDefined('select', tracker) && typeof tracker.select === 'function' && !tracker.select(args)) { + return; + } + args[0] = generateCommandName(commandName, tracker); + _ga.apply(that, args); + }); + }; + + this._log = function () { + var args = Array.prototype.slice.call(arguments); + if (args.length > 0) { + if (args.length > 1) { + switch (args[0]) { + case 'debug': + case 'error': + case 'info': + case 'log': + case 'warn': + $log[args[0]](args.slice(1)); + break; + } + } + that.log.push(args); + } + }; + + /* DEPRECATED */ + this._createScriptTag = function () { + that._registerScriptTags(); + that._registerTrackers(); + }; + + /* DEPRECATED */ + this._createAnalyticsScriptTag = function () { + that._registerScriptTags(); + that._registerTrackers(); + }; + + this._registerScriptTags = function () { + var document = $document[0], + protocol = _getProtocol(), + scriptSource; + + if (created === true) { + that._log('warn', 'Script tags already created'); + return; + } + + if (disableAnalytics === true) { + accounts.forEach(function (trackerObj) { + that._log('info', 'Analytics disabled: ' + trackerObj.tracker); + $window['ga-disable-' + trackerObj.tracker] = true; + }); + } + + // + // Universal Analytics + // + if (analyticsJS === true) { + scriptSource = protocol + '//www.google-analytics.com/' + (debugMode ? 'analytics_debug.js' : 'analytics.js'); + if (testMode !== true) { + // If not in test mode inject the Google Analytics tag + (function (i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function (){ + (i[r].q=i[r].q||[]).push(arguments);},i[r].l=1*new Date();a=s.createElement(o), + m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m); + })(window,document,'script',scriptSource,'ga'); + } else { + if (typeof $window.ga !== 'function') { + // In test mode create a ga function if none exists that is a noop sink. + $window.ga = function () {}; + } + // Log script injection. + that._log('inject', scriptSource); + } + + if (traceDebuggingMode) { + $window.ga_debug = { trace: true }; + } + + if (experimentId) { + var expScript = document.createElement('script'), + s = document.getElementsByTagName('script')[0]; + expScript.src = protocol + '//www.google-analytics.com/cx/api.js?experiment=' + experimentId; + s.parentNode.insertBefore(expScript, s); + } + // + // Classic Analytics + // + } else { + scriptSource = _getProtocol('//www', '//ssl') + '.google-analytics.com/ga.js'; + if (displayFeatures === true) { + scriptSource = protocol + '//stats.g.doubleclick.net/dc.js'; + } + + if (testMode !== true) { + // If not in test mode inject the Google Analytics tag + (function () { + var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; + ga.src = scriptSource; + var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); + })(); + } else { + // Log the source location for validation + that._log('inject', scriptSource); + } + } + + created = true; + return true; + }; + + this._registerTrackers = function () { + if (!accounts || accounts.length < 1) { + that._log('warn', 'No accounts to register'); + return; + } + + // + // Universal Analytics + // + if (analyticsJS === true) { + accounts.forEach(function (trackerObj) { + trackerObj.crossDomainLinker = isPropertyDefined('crossDomainLinker', trackerObj) ? trackerObj.crossDomainLinker : crossDomainLinker; + trackerObj.crossLinkDomains = isPropertyDefined('crossLinkDomains', trackerObj) ? trackerObj.crossLinkDomains : crossLinkDomains; + trackerObj.displayFeatures = isPropertyDefined('displayFeatures', trackerObj) ? trackerObj.displayFeatures : displayFeatures; + trackerObj.enhancedLinkAttribution = isPropertyDefined('enhancedLinkAttribution', trackerObj) ? trackerObj.enhancedLinkAttribution : enhancedLinkAttribution; + trackerObj.set = isPropertyDefined('set', trackerObj) ? trackerObj.set : {}; + trackerObj.trackEcommerce = isPropertyDefined('trackEcommerce', trackerObj) ? trackerObj.trackEcommerce : ecommerce; + trackerObj.trackEvent = isPropertyDefined('trackEvent', trackerObj) ? trackerObj.trackEvent : false; + + // Logic to choose the account fields to be used. + // cookieConfig is being deprecated for a tracker specific property: fields. + var fields = {}; + if (isPropertyDefined('fields', trackerObj)) { + fields = trackerObj.fields; + } else if (isPropertyDefined('cookieConfig', trackerObj)) { + if (angular.isString(trackerObj.cookieConfig)) { + fields.cookieDomain = trackerObj.cookieConfig; + } else { + fields = trackerObj.cookieConfig; + } + } else if (angular.isString(cookieConfig)) { + fields.cookieDomain = cookieConfig; + } else if (cookieConfig) { + fields = cookieConfig; + } + if (trackerObj.crossDomainLinker === true) { + fields.allowLinker = true; + } + if (isPropertyDefined('name', trackerObj)) { + fields.name = trackerObj.name; + } + trackerObj.fields = fields; + + _ga('create', trackerObj.tracker, trackerObj.fields); + + // Hybrid mobile application support + // https://developers.google.com/analytics/devguides/collection/analyticsjs/tasks + if (hybridMobileSupport === true) { + _ga(generateCommandName('set', trackerObj), 'checkProtocolTask', null); + } + + // Send all custom set commands from the trackerObj.set property + for (var key in trackerObj.set) { + if (trackerObj.set.hasOwnProperty(key)) { + _ga(generateCommandName('set', trackerObj), key, trackerObj.set[key]); + } + } + + if (trackerObj.crossDomainLinker === true) { + _ga(generateCommandName('require', trackerObj), 'linker'); + if (angular.isDefined(trackerObj.crossLinkDomains)) { + _ga(generateCommandName('linker:autoLink', trackerObj), trackerObj.crossLinkDomains); + } + } + + if (trackerObj.displayFeatures) { + _ga(generateCommandName('require', trackerObj), 'displayfeatures'); + } + + if (trackerObj.trackEcommerce) { + if (!enhancedEcommerce) { + _ga(generateCommandName('require', trackerObj), 'ecommerce'); + } else { + _ga(generateCommandName('require', trackerObj), 'ec'); + _ga(generateCommandName('set', trackerObj), '&cu', currency); + } + } + + if (trackerObj.enhancedLinkAttribution) { + _ga(generateCommandName('require', trackerObj), 'linkid'); + } + + if (trackRoutes && !ignoreFirstPageLoad) { + _ga(generateCommandName('send', trackerObj), 'pageview', trackPrefix + getUrl()); + } + }); + // + // Classic Analytics + // + } else { + if (accounts.length > 1) { + that._log('warn', 'Multiple trackers are not supported with ga.js. Using first tracker only'); + accounts = accounts.slice(0, 1); + } + + _gaq('_setAccount', accounts[0].tracker); + if(domainName) { + _gaq('_setDomainName', domainName); + } + if (enhancedLinkAttribution) { + _gaq('_require', 'inpage_linkid', '//www.google-analytics.com/plugins/ga/inpage_linkid.js'); + } + if (trackRoutes && !ignoreFirstPageLoad) { + if (removeRegExp) { + _gaq('_trackPageview', getUrl()); + } else { + _gaq('_trackPageview'); + } + } + } + + return true; + }; + + this._ecommerceEnabled = function (warn, command) { + var result = ecommerce && !enhancedEcommerce; + if (warn === true && result === false) { + if (ecommerce && enhancedEcommerce) { + that._log('warn', command + ' is not available when Enhanced Ecommerce is enabled with analytics.js'); + } else { + that._log('warn', 'Ecommerce must be enabled to use ' + command + ' with analytics.js'); + } + } + return result; + }; + + this._enhancedEcommerceEnabled = function (warn, command) { + var result = ecommerce && enhancedEcommerce; + if (warn === true && result === false) { + that._log('warn', 'Enhanced Ecommerce must be enabled to use ' + command + ' with analytics.js'); + } + return result; + }; + + /** + * Track page + https://developers.google.com/analytics/devguides/collection/gajs/ + https://developers.google.com/analytics/devguides/collection/analyticsjs/pages + * @param url + * @param title + * @param custom + * @private + */ + this._trackPage = function (url, title, custom) { + url = url ? url : getUrl(); + title = title ? title : $document[0].title; + _gaJs(function () { + // http://stackoverflow.com/questions/7322288/how-can-i-set-a-page-title-with-google-analytics + _gaq('_set', 'title', title); + _gaq('_trackPageview', (trackPrefix + url)); + }); + _analyticsJs(function () { + var opt_fieldObject = { + 'page': trackPrefix + url, + 'title': title + }; + angular.extend(opt_fieldObject, getUtmParams()); + if (angular.isObject(custom)) { + angular.extend(opt_fieldObject, custom); + } + _gaMultipleTrackers(undefined, 'send', 'pageview', opt_fieldObject); + }); + }; + + /** + * Track event + https://developers.google.com/analytics/devguides/collection/gajs/eventTrackerGuide + https://developers.google.com/analytics/devguides/collection/analyticsjs/events + * @param category + * @param action + * @param label + * @param value + * @param noninteraction + * @param custom + * @private + */ + this._trackEvent = function (category, action, label, value, noninteraction, custom) { + _gaJs(function () { + _gaq('_trackEvent', category, action, label, value, !!noninteraction); + }); + _analyticsJs(function () { + var opt_fieldObject = {}; + var includeFn = function (trackerObj) { + return isPropertySetTo('trackEvent', trackerObj, true); + }; + + if (angular.isDefined(noninteraction)) { + opt_fieldObject.nonInteraction = !!noninteraction; + } + if (angular.isObject(custom)) { + angular.extend(opt_fieldObject, custom); + } + if (!angular.isDefined(opt_fieldObject.page)) { + opt_fieldObject.page = getUrl(); + } + _gaMultipleTrackers(includeFn, 'send', 'event', category, action, label, value, opt_fieldObject); + }); + }; + + /** + * Add transaction + * https://developers.google.com/analytics/devguides/collection/gajs/methods/gaJSApiEcommerce#_gat.GA_Tracker_._addTrans + * https://developers.google.com/analytics/devguides/collection/analyticsjs/ecommerce#addTrans + * @param transactionId + * @param affiliation + * @param total + * @param tax + * @param shipping + * @param city + * @param state + * @param country + * @private + */ + this._addTrans = function (transactionId, affiliation, total, tax, shipping, city, state, country, currency) { + _gaJs(function () { + _gaq('_addTrans', transactionId, affiliation, total, tax, shipping, city, state, country); + }); + _analyticsJs(function () { + if (that._ecommerceEnabled(true, 'addTrans')) { + var includeFn = function (trackerObj) { + return isPropertySetTo('trackEcommerce', trackerObj, true); + }; + + _gaMultipleTrackers( + includeFn, + 'ecommerce:addTransaction', + { + id: transactionId, + affiliation: affiliation, + revenue: total, + tax: tax, + shipping: shipping, + currency: currency || 'USD' + }); + } + }); + }; + + /** + * Add item to transaction + * https://developers.google.com/analytics/devguides/collection/gajs/methods/gaJSApiEcommerce#_gat.GA_Tracker_._addItem + * https://developers.google.com/analytics/devguides/collection/analyticsjs/ecommerce#addItem + * @param transactionId + * @param sku + * @param name + * @param category + * @param price + * @param quantity + * @private + */ + this._addItem = function (transactionId, sku, name, category, price, quantity) { + _gaJs(function () { + _gaq('_addItem', transactionId, sku, name, category, price, quantity); + }); + _analyticsJs(function () { + if (that._ecommerceEnabled(true, 'addItem')) { + var includeFn = function (trackerObj) { + return isPropertySetTo('trackEcommerce', trackerObj, true); + }; + + _gaMultipleTrackers( + includeFn, + 'ecommerce:addItem', + { + id: transactionId, + name: name, + sku: sku, + category: category, + price: price, + quantity: quantity + }); + } + }); + }; + + /** + * Track transaction + * https://developers.google.com/analytics/devguides/collection/gajs/methods/gaJSApiEcommerce#_gat.GA_Tracker_._trackTrans + * https://developers.google.com/analytics/devguides/collection/analyticsjs/ecommerce#sendingData + * @private + */ + this._trackTrans = function () { + _gaJs(function () { + _gaq('_trackTrans'); + }); + _analyticsJs(function () { + if (that._ecommerceEnabled(true, 'trackTrans')) { + var includeFn = function (trackerObj) { + return isPropertySetTo('trackEcommerce', trackerObj, true); + }; + + _gaMultipleTrackers(includeFn, 'ecommerce:send'); + } + }); + }; + + /** + * Clear transaction + * https://developers.google.com/analytics/devguides/collection/analyticsjs/ecommerce#clearingData + * @private + */ + this._clearTrans = function () { + _analyticsJs(function () { + if (that._ecommerceEnabled(true, 'clearTrans')) { + var includeFn = function (trackerObj) { + return isPropertySetTo('trackEcommerce', trackerObj, true); + }; + + _gaMultipleTrackers(includeFn, 'ecommerce:clear'); + } + }); + }; + + /** + * Enhanced Ecommerce + */ + + /** + * Add Product + * https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce#product-data + * @param productId + * @param name + * @param category + * @param brand + * @param variant + * @param price + * @param quantity + * @param coupon + * @param position + * @param custom + * @private + */ + this._addProduct = function (productId, name, category, brand, variant, price, quantity, coupon, position, custom) { + _gaJs(function () { + _gaq('_addProduct', productId, name, category, brand, variant, price, quantity, coupon, position); + }); + _analyticsJs(function () { + if (that._enhancedEcommerceEnabled(true, 'addProduct')) { + var includeFn = function (trackerObj) { + return isPropertySetTo('trackEcommerce', trackerObj, true); + }; + var details = { + id: productId, + name: name, + category: category, + brand: brand, + variant: variant, + price: price, + quantity: quantity, + coupon: coupon, + position: position + }; + if (angular.isObject(custom)) { + angular.extend(details, custom); + } + _gaMultipleTrackers(includeFn, 'ec:addProduct', details); + } + }); + }; + + /** + * Add Impression + * https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce#impression-data + * @param id + * @param name + * @param list + * @param brand + * @param category + * @param variant + * @param position + * @param price + * @private + */ + this._addImpression = function (id, name, list, brand, category, variant, position, price){ + _gaJs(function () { + _gaq('_addImpression', id, name, list, brand, category, variant, position, price); + }); + _analyticsJs(function () { + if (that._enhancedEcommerceEnabled(true, 'addImpression')) { + var includeFn = function (trackerObj) { + return isPropertySetTo('trackEcommerce', trackerObj, true); + }; + + _gaMultipleTrackers( + includeFn, + 'ec:addImpression', + { + id: id, + name: name, + category: category, + brand: brand, + variant: variant, + list: list, + position: position, + price: price + }); + } + }); + }; + + /** + * Add Promo + * https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce + * @param productId + * @param name + * @param creative + * @param position + * @private + */ + this._addPromo = function (productId, name, creative, position) { + _gaJs(function () { + _gaq('_addPromo', productId, name, creative, position); + }); + _analyticsJs(function () { + if (that._enhancedEcommerceEnabled(true, 'addPromo')) { + var includeFn = function (trackerObj) { + return isPropertySetTo('trackEcommerce', trackerObj, true); + }; + + _gaMultipleTrackers( + includeFn, + 'ec:addPromo', + { + id: productId, + name: name, + creative: creative, + position: position + }); + } + }); + }; + + /** + * Set Action + * https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce#measuring-actions + * https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce#action-types + * @param action + * @param obj + * @private + */ + this._setAction = function (action, obj){ + _gaJs(function () { + _gaq('_setAction', action, obj); + }); + _analyticsJs(function () { + if (that._enhancedEcommerceEnabled(true, 'setAction')) { + var includeFn = function (trackerObj) { + return isPropertySetTo('trackEcommerce', trackerObj, true); + }; + + _gaMultipleTrackers(includeFn, 'ec:setAction', action, obj); + } + }); + }; + + /** + * Track Transaction + * https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce#measuring-transactions + * @param transactionId + * @param affiliation + * @param revenue + * @param tax + * @param shipping + * @param coupon + * @param list + * @param step + * @param option + * @private + */ + this._trackTransaction = function (transactionId, affiliation, revenue, tax, shipping, coupon, list, step, option) { + this._setAction('purchase', getActionFieldObject(transactionId, affiliation, revenue, tax, shipping, coupon, list, step, option)); + }; + + /** + * Track Refund + * https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce#measuring-refunds + * @param transactionId + * @private + */ + this._trackRefund = function (transactionId) { + this._setAction('refund', getActionFieldObject(transactionId)); + }; + + /** + * Track Checkout + * https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce#measuring-checkout + * @param step + * @param option + * @private + */ + this._trackCheckOut = function (step, option) { + this._setAction('checkout', getActionFieldObject(null, null, null, null, null, null, null, step, option)); + }; + + /** + * Track detail + * @private + */ + this._trackDetail = function () { + this._setAction('detail'); + this._pageView(); + }; + + /** + * Track add/remove to cart + * https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce#add-remove-cart + * @param action + * @param list + * @private + */ + this._trackCart = function (action, listName) { + if (['add', 'remove'].indexOf(action) !== -1) { + this._setAction(action, { list: listName }); + this._trackEvent('UX', 'click', action + (action === 'add' ? ' to cart' : ' from cart')); + } + }; + + /** + * Track promo click + * https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce#measuring-promo-clicks + * @param promotionName + * @private + */ + this._promoClick = function (promotionName) { + this._setAction('promo_click'); + this._trackEvent('Internal Promotions', 'click', promotionName); + }; + + /** + * Track product click + * https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce#measuring-promo-clicks + * @param promotionName + * @private + */ + this._productClick = function (listName) { + this._setAction('click', getActionFieldObject(null, null, null, null, null, null, listName, null, null)); + this._trackEvent('UX', 'click', listName); + }; + + /** + * Send page view + * @param trackerName + * @private + */ + this._pageView = function (trackerName) { + _analyticsJs(function () { + _ga(generateCommandName('send', trackerName), 'pageview'); + }); + }; + + /** + * Send custom events + * https://developers.google.com/analytics/devguides/collection/analyticsjs/user-timings#implementation + * https://developers.google.com/analytics/devguides/collection/analyticsjs/social-interactions#implementation + * @private + */ + this._send = function () { + var args = Array.prototype.slice.call(arguments); + args.unshift('send'); + _analyticsJs(function () { + _ga.apply(that, args); + }); + }; + + /** + * Set custom dimensions, metrics or experiment + * https://developers.google.com/analytics/devguides/collection/analyticsjs/custom-dims-mets + * https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#customs + * @param name (Required) + * @param value (Required) + * @param trackerName (Optional) + * @private + */ + this._set = function (name, value, trackerName) { + _analyticsJs(function () { + _ga(generateCommandName('set', trackerName), name, value); + }); + }; + + /** + * Track user timings + * @param timingCategory (Required): A string for categorizing all user timing variables into logical groups(e.g jQuery). + * @param timingVar (Required): A string to identify the variable being recorded(e.g. JavaScript Load). + * @param timingValue (Required): The number of milliseconds in elapsed time to report to Google Analytics(e.g. 20). + * @param timingLabel (Optional): A string that can be used to add flexibility in visualizing user timings in the reports(e.g. Google CDN). + * @private + */ + this._trackTimings = function (timingCategory, timingVar, timingValue, timingLabel) { + _analyticsJs(function () { + _gaMultipleTrackers(undefined, 'send', 'timing', timingCategory, timingVar, timingValue, timingLabel); + }); + }; + + /** + * Exception tracking + * https://developers.google.com/analytics/devguides/collection/analyticsjs/exceptions + * @param description (Optional): A description of the exception. + * @param isFatal (Optional): true if the exception was fatal, false otherwise. + * @private + */ + this._trackException = function (description, isFatal) { + _analyticsJs(function () { + _gaMultipleTrackers(undefined, 'send', 'exception', { exDescription: description, exFatal: !!isFatal}); + }); + }; + + // creates the Google Analytics tracker + if (!delayScriptTag) { + this._registerScriptTags(); + this._registerTrackers(); + } + + // activates page tracking + if (trackRoutes) { + $rootScope.$on(pageEvent, function () { + // Apply $route based filtering if configured + if (readFromRoute) { + // Avoid tracking undefined routes, routes without template (e.g. redirect routes) + // and those explicitly marked as 'do not track' + if (!$route.current || !$route.current.templateUrl || $route.current.doNotTrack) { + return; + } + } + + that._trackPage(); + }); + } + + return { + log: that.log, + offlineQueue: that.offlineQueue, + configuration: { + accounts: accounts, + universalAnalytics: analyticsJS, + crossDomainLinker: crossDomainLinker, + crossLinkDomains: crossLinkDomains, + currency: currency, + debugMode: debugMode, + delayScriptTag: delayScriptTag, + disableAnalytics: disableAnalytics, + displayFeatures: displayFeatures, + domainName: domainName, + ecommerce: that._ecommerceEnabled(), + enhancedEcommerce: that._enhancedEcommerceEnabled(), + enhancedLinkAttribution: enhancedLinkAttribution, + experimentId: experimentId, + hybridMobileSupport: hybridMobileSupport, + ignoreFirstPageLoad: ignoreFirstPageLoad, + logAllCalls: logAllCalls, + pageEvent: pageEvent, + readFromRoute: readFromRoute, + removeRegExp: removeRegExp, + testMode: testMode, + traceDebuggingMode: traceDebuggingMode, + trackPrefix: trackPrefix, + trackRoutes: trackRoutes, + trackUrlParams: trackUrlParams + }, + getUrl: getUrl, + /* DEPRECATED */ + setCookieConfig: function (config) { + that._log('warn', 'DEPRECATION WARNING: setCookieConfig method is deprecated. Please use tracker fields instead.'); + return that._setCookieConfig.apply(that, arguments); + }, + /* DEPRECATED */ + getCookieConfig: function () { + that._log('warn', 'DEPRECATION WARNING: getCookieConfig method is deprecated. Please use tracker fields instead.'); + return cookieConfig; + }, + /* DEPRECATED */ + createAnalyticsScriptTag: function (config) { + that._log('warn', 'DEPRECATION WARNING: createAnalyticsScriptTag method is deprecated. Please use registerScriptTags and registerTrackers methods instead.'); + if (config) { + cookieConfig = config; + } + return that._createAnalyticsScriptTag(); + }, + /* DEPRECATED */ + createScriptTag: function () { + that._log('warn', 'DEPRECATION WARNING: createScriptTag method is deprecated. Please use registerScriptTags and registerTrackers methods instead.'); + return that._createScriptTag(); + }, + registerScriptTags: function () { + return that._registerScriptTags(); + }, + registerTrackers: function () { + return that._registerTrackers(); + }, + offline: function (mode) { + if (mode === true && offlineMode === false) { + // Go to offline mode + offlineMode = true; + } + if (mode === false && offlineMode === true) { + // Go to online mode and process the offline queue + offlineMode = false; + while (that.offlineQueue.length > 0) { + var obj = that.offlineQueue.shift(); + obj[0].apply(that, obj[1]); + } + } + return offlineMode; + }, + trackPage: function (url, title, custom) { + that._trackPage.apply(that, arguments); + }, + trackEvent: function (category, action, label, value, noninteraction, custom) { + that._trackEvent.apply(that, arguments); + }, + addTrans: function (transactionId, affiliation, total, tax, shipping, city, state, country, currency) { + that._addTrans.apply(that, arguments); + }, + addItem: function (transactionId, sku, name, category, price, quantity) { + that._addItem.apply(that, arguments); + }, + trackTrans: function () { + that._trackTrans.apply(that, arguments); + }, + clearTrans: function () { + that._clearTrans.apply(that, arguments); + }, + addProduct: function (productId, name, category, brand, variant, price, quantity, coupon, position, custom) { + that._addProduct.apply(that, arguments); + }, + addPromo: function (productId, name, creative, position) { + that._addPromo.apply(that, arguments); + }, + addImpression: function (productId, name, list, brand, category, variant, position, price) { + that._addImpression.apply(that, arguments); + }, + productClick: function (listName) { + that._productClick.apply(that, arguments); + }, + promoClick : function (promotionName) { + that._promoClick.apply(that, arguments); + }, + trackDetail: function () { + that._trackDetail.apply(that, arguments); + }, + trackCart: function (action, list) { + that._trackCart.apply(that, arguments); + }, + trackCheckout: function (step, option) { + that._trackCheckOut.apply(that, arguments); + }, + trackTimings: function (timingCategory, timingVar, timingValue, timingLabel) { + that._trackTimings.apply(that, arguments); + }, + trackTransaction: function (transactionId, affiliation, revenue, tax, shipping, coupon, list, step, option) { + that._trackTransaction.apply(that, arguments); + }, + trackException: function (description, isFatal) { + that._trackException.apply(that, arguments); + }, + setAction: function (action, obj) { + that._setAction.apply(that, arguments); + }, + pageView: function () { + that._pageView.apply(that, arguments); + }, + send: function (obj) { + that._send.apply(that, arguments); + }, + set: function (name, value, trackerName) { + that._set.apply(that, arguments); + } + }; + }]; + }) + + .directive('gaTrackEvent', ['Analytics', '$parse', function (Analytics, $parse) { + return { + restrict: 'A', + link: function (scope, element, attrs) { + var options = $parse(attrs.gaTrackEvent); + element.bind('click', function () { + if(attrs.gaTrackEventIf){ + if(!scope.$eval(attrs.gaTrackEventIf)){ + return; // Cancel this event if we don't pass the ga-track-event-if condition + } + } + if (options.length > 1) { + Analytics.trackEvent.apply(Analytics, options(scope)); + } + }); + } + }; + }]); + return angular.module('angular-google-analytics'); +})); diff --git a/dist/angular-google-analytics.min.js b/dist/angular-google-analytics.min.js new file mode 100644 index 0000000..f8c8cf5 --- /dev/null +++ b/dist/angular-google-analytics.min.js @@ -0,0 +1,9 @@ +/** + * Angular Google Analytics - Easy tracking for your AngularJS application + * @version v1.1.8 - 2016-12-30 + * @link http://github.com/revolunet/angular-google-analytics + * @author Julien Bouquillon (https://github.com/revolunet) + * @contributors Julien Bouquillon (https://github.com/revolunet),Justin Saunders (https://github.com/justinsa),Chris Esplin (https://github.com/deltaepsilon),Adam Misiorny (https://github.com/adam187) + * @license MIT License, http://www.opensource.org/licenses/MIT + */ +!function(a,b){"use strict";"undefined"!=typeof module&&module.exports?(b("undefined"==typeof angular?require("angular"):angular),module.exports="angular-google-analytics"):"function"==typeof define&&define.amd?define(["angular"],b):b(a.angular)}(this,function(a,b){"use strict";return a.module("angular-google-analytics",[]).provider("Analytics",function(){var c,d,e,f,g,h=!0,i="auto",j=!1,k=!1,l="USD",m=!1,n=!1,o=!1,p=!1,q=!1,r=!1,s=!1,t=!1,u=!1,v=!1,w=!1,x="$routeChangeSuccess",y=!1,z=!1,A=!1,B="",C=!0,D=!1;this.log=[],this.offlineQueue=[],this.setAccount=function(d){return c=a.isUndefined(d)||d===!1?b:a.isArray(d)?d:a.isObject(d)?[d]:[{tracker:d,trackEvent:!0}],this},this.trackPages=function(a){return C=!!a,this},this.trackPrefix=function(a){return B=a,this},this.setDomainName=function(a){return e=a,this},this.useDisplayFeatures=function(a){return o=!!a,this},this.useAnalytics=function(a){return h=!!a,this},this.useEnhancedLinkAttribution=function(a){return s=!!a,this},this.useCrossDomainLinker=function(a){return k=!!a,this},this.setCrossLinkDomains=function(a){return d=a,this},this.setPageEvent=function(a){return x=a,this},this.setCookieConfig=function(a){return i=a,this},this.useECommerce=function(a,b){return q=!!a,r=!!b,this},this.setCurrency=function(a){return l=a,this},this.setRemoveRegExp=function(a){return a instanceof RegExp&&(g=a),this},this.setExperimentId=function(a){return f=a,this},this.ignoreFirstPageLoad=function(a){return t=!!a,this},this.trackUrlParams=function(a){return D=!!a,this},this.disableAnalytics=function(a){return p=!!a,this},this.setHybridMobileSupport=function(a){return v=!!a,this},this.startOffline=function(a){return w=!!a,w===!0&&this.delayScriptTag(!0),this},this.delayScriptTag=function(a){return n=!!a,this},this.logAllCalls=function(a){return u=!!a,this},this.enterTestMode=function(){return z=!0,this},this.enterDebugMode=function(a){return m=!0,A=!!a,this},this.readFromRoute=function(a){return y=!!a,this},this.$get=["$document","$location","$log","$rootScope","$window","$injector",function(E,F,G,H,I,J){var K=this,L=function(b,c){return a.isObject(c)&&a.isDefined(c[b])},M=function(a,b,c){return L(a,b)&&b[a]===c},N=function(b,c){return a.isString(c)?c+"."+b:L("name",c)?c.name+"."+b:b},O={};y&&(J.has("$route")?O=J.get("$route"):G.warn("$route service is not available. Make sure you have included ng-route in your application dependencies."));var P=function(){if(y&&O.current&&"pageTrack"in O.current)return O.current.pageTrack;var a=D?F.url():F.path();return g?a.replace(g,""):a},Q=function(){var b={utm_source:"campaignSource",utm_medium:"campaignMedium",utm_term:"campaignTerm",utm_content:"campaignContent",utm_campaign:"campaignName"},c={};return a.forEach(F.search(),function(d,e){var f=b[e];a.isDefined(f)&&(c[f]=d)}),c},R=function(a,b,c,d,e,f,g,h,i){var j={};return a&&(j.id=a),b&&(j.affiliation=b),c&&(j.revenue=c),d&&(j.tax=d),e&&(j.shipping=e),f&&(j.coupon=f),g&&(j.list=g),h&&(j.step=h),i&&(j.option=i),j},S=function(b,c){var d="",e="https:"===document.location.protocol,f="chrome-extension:"===document.location.protocol,g=h===!0&&v===!0;return b=a.isString(b)?b:"",c=a.isString(c)?c:"",""!==b&&(d="http:"+b),(f||g||e&&""!==c)&&(d="https:"+c),d},T=function(a){!h&&I._gaq&&"function"==typeof a&&a()},U=function(){var a=Array.prototype.slice.call(arguments);return w===!0?void K.offlineQueue.push([U,a]):(I._gaq||(I._gaq=[]),u===!0&&K._log.apply(K,a),void I._gaq.push(a))},V=function(a){h&&I.ga&&"function"==typeof a&&a()},W=function(){var a=Array.prototype.slice.call(arguments);return w===!0?void K.offlineQueue.push([W,a]):"function"!=typeof I.ga?void K._log("warn","ga function not set on window"):(u===!0&&K._log.apply(K,a),void I.ga.apply(null,a))},X=function(a){var b=Array.prototype.slice.call(arguments,1),d=b[0],e=[];return"function"==typeof a?c.forEach(function(b){a(b)&&e.push(b)}):e=c,0===e.length?void W.apply(K,b):void e.forEach(function(a){L("select",a)&&"function"==typeof a.select&&!a.select(b)||(b[0]=N(d,a),W.apply(K,b))})};return this._log=function(){var a=Array.prototype.slice.call(arguments);if(a.length>0){if(a.length>1)switch(a[0]){case"debug":case"error":case"info":case"log":case"warn":G[a[0]](a.slice(1))}K.log.push(a)}},this._createScriptTag=function(){K._registerScriptTags(),K._registerTrackers()},this._createAnalyticsScriptTag=function(){K._registerScriptTags(),K._registerTrackers()},this._registerScriptTags=function(){var a,b=E[0],d=S();if(j===!0)return void K._log("warn","Script tags already created");if(p===!0&&c.forEach(function(a){K._log("info","Analytics disabled: "+a.tracker),I["ga-disable-"+a.tracker]=!0}),h===!0){if(a=d+"//www.google-analytics.com/"+(m?"analytics_debug.js":"analytics.js"),z!==!0?!function(a,b,c,d,e,f,g){a.GoogleAnalyticsObject=e,a[e]=a[e]||function(){(a[e].q=a[e].q||[]).push(arguments)},a[e].l=1*new Date,f=b.createElement(c),g=b.getElementsByTagName(c)[0],f.async=1,f.src=d,g.parentNode.insertBefore(f,g)}(window,b,"script",a,"ga"):("function"!=typeof I.ga&&(I.ga=function(){}),K._log("inject",a)),A&&(I.ga_debug={trace:!0}),f){var e=b.createElement("script"),g=b.getElementsByTagName("script")[0];e.src=d+"//www.google-analytics.com/cx/api.js?experiment="+f,g.parentNode.insertBefore(e,g)}}else a=S("//www","//ssl")+".google-analytics.com/ga.js",o===!0&&(a=d+"//stats.g.doubleclick.net/dc.js"),z!==!0?!function(){var c=b.createElement("script");c.type="text/javascript",c.async=!0,c.src=a;var d=b.getElementsByTagName("script")[0];d.parentNode.insertBefore(c,d)}():K._log("inject",a);return j=!0,!0},this._registerTrackers=function(){return!c||c.length<1?void K._log("warn","No accounts to register"):(h===!0?c.forEach(function(b){b.crossDomainLinker=L("crossDomainLinker",b)?b.crossDomainLinker:k,b.crossLinkDomains=L("crossLinkDomains",b)?b.crossLinkDomains:d,b.displayFeatures=L("displayFeatures",b)?b.displayFeatures:o,b.enhancedLinkAttribution=L("enhancedLinkAttribution",b)?b.enhancedLinkAttribution:s,b.set=L("set",b)?b.set:{},b.trackEcommerce=L("trackEcommerce",b)?b.trackEcommerce:q,b.trackEvent=!!L("trackEvent",b)&&b.trackEvent;var c={};L("fields",b)?c=b.fields:L("cookieConfig",b)?a.isString(b.cookieConfig)?c.cookieDomain=b.cookieConfig:c=b.cookieConfig:a.isString(i)?c.cookieDomain=i:i&&(c=i),b.crossDomainLinker===!0&&(c.allowLinker=!0),L("name",b)&&(c.name=b.name),b.fields=c,W("create",b.tracker,b.fields),v===!0&&W(N("set",b),"checkProtocolTask",null);for(var e in b.set)b.set.hasOwnProperty(e)&&W(N("set",b),e,b.set[e]);b.crossDomainLinker===!0&&(W(N("require",b),"linker"),a.isDefined(b.crossLinkDomains)&&W(N("linker:autoLink",b),b.crossLinkDomains)),b.displayFeatures&&W(N("require",b),"displayfeatures"),b.trackEcommerce&&(r?(W(N("require",b),"ec"),W(N("set",b),"&cu",l)):W(N("require",b),"ecommerce")),b.enhancedLinkAttribution&&W(N("require",b),"linkid"),C&&!t&&W(N("send",b),"pageview",B+P())}):(c.length>1&&(K._log("warn","Multiple trackers are not supported with ga.js. Using first tracker only"),c=c.slice(0,1)),U("_setAccount",c[0].tracker),e&&U("_setDomainName",e),s&&U("_require","inpage_linkid","//www.google-analytics.com/plugins/ga/inpage_linkid.js"),C&&!t&&(g?U("_trackPageview",P()):U("_trackPageview"))),!0)},this._ecommerceEnabled=function(a,b){var c=q&&!r;return a===!0&&c===!1&&(q&&r?K._log("warn",b+" is not available when Enhanced Ecommerce is enabled with analytics.js"):K._log("warn","Ecommerce must be enabled to use "+b+" with analytics.js")),c},this._enhancedEcommerceEnabled=function(a,b){var c=q&&r;return a===!0&&c===!1&&K._log("warn","Enhanced Ecommerce must be enabled to use "+b+" with analytics.js"),c},this._trackPage=function(c,d,e){c=c?c:P(),d=d?d:E[0].title,T(function(){U("_set","title",d),U("_trackPageview",B+c)}),V(function(){var f={page:B+c,title:d};a.extend(f,Q()),a.isObject(e)&&a.extend(f,e),X(b,"send","pageview",f)})},this._trackEvent=function(b,c,d,e,f,g){T(function(){U("_trackEvent",b,c,d,e,!!f)}),V(function(){var h={},i=function(a){return M("trackEvent",a,!0)};a.isDefined(f)&&(h.nonInteraction=!!f),a.isObject(g)&&a.extend(h,g),a.isDefined(h.page)||(h.page=P()),X(i,"send","event",b,c,d,e,h)})},this._addTrans=function(a,b,c,d,e,f,g,h,i){T(function(){U("_addTrans",a,b,c,d,e,f,g,h)}),V(function(){if(K._ecommerceEnabled(!0,"addTrans")){var f=function(a){return M("trackEcommerce",a,!0)};X(f,"ecommerce:addTransaction",{id:a,affiliation:b,revenue:c,tax:d,shipping:e,currency:i||"USD"})}})},this._addItem=function(a,b,c,d,e,f){T(function(){U("_addItem",a,b,c,d,e,f)}),V(function(){if(K._ecommerceEnabled(!0,"addItem")){var g=function(a){return M("trackEcommerce",a,!0)};X(g,"ecommerce:addItem",{id:a,name:c,sku:b,category:d,price:e,quantity:f})}})},this._trackTrans=function(){T(function(){U("_trackTrans")}),V(function(){if(K._ecommerceEnabled(!0,"trackTrans")){var a=function(a){return M("trackEcommerce",a,!0)};X(a,"ecommerce:send")}})},this._clearTrans=function(){V(function(){if(K._ecommerceEnabled(!0,"clearTrans")){var a=function(a){return M("trackEcommerce",a,!0)};X(a,"ecommerce:clear")}})},this._addProduct=function(b,c,d,e,f,g,h,i,j,k){T(function(){U("_addProduct",b,c,d,e,f,g,h,i,j)}),V(function(){if(K._enhancedEcommerceEnabled(!0,"addProduct")){var l=function(a){return M("trackEcommerce",a,!0)},m={id:b,name:c,category:d,brand:e,variant:f,price:g,quantity:h,coupon:i,position:j};a.isObject(k)&&a.extend(m,k),X(l,"ec:addProduct",m)}})},this._addImpression=function(a,b,c,d,e,f,g,h){T(function(){U("_addImpression",a,b,c,d,e,f,g,h)}),V(function(){if(K._enhancedEcommerceEnabled(!0,"addImpression")){var i=function(a){return M("trackEcommerce",a,!0)};X(i,"ec:addImpression",{id:a,name:b,category:e,brand:d,variant:f,list:c,position:g,price:h})}})},this._addPromo=function(a,b,c,d){T(function(){U("_addPromo",a,b,c,d)}),V(function(){if(K._enhancedEcommerceEnabled(!0,"addPromo")){var e=function(a){return M("trackEcommerce",a,!0)};X(e,"ec:addPromo",{id:a,name:b,creative:c,position:d})}})},this._setAction=function(a,b){T(function(){U("_setAction",a,b)}),V(function(){if(K._enhancedEcommerceEnabled(!0,"setAction")){var c=function(a){return M("trackEcommerce",a,!0)};X(c,"ec:setAction",a,b)}})},this._trackTransaction=function(a,b,c,d,e,f,g,h,i){this._setAction("purchase",R(a,b,c,d,e,f,g,h,i))},this._trackRefund=function(a){this._setAction("refund",R(a))},this._trackCheckOut=function(a,b){this._setAction("checkout",R(null,null,null,null,null,null,null,a,b))},this._trackDetail=function(){this._setAction("detail"),this._pageView()},this._trackCart=function(a,b){["add","remove"].indexOf(a)!==-1&&(this._setAction(a,{list:b}),this._trackEvent("UX","click",a+("add"===a?" to cart":" from cart")))},this._promoClick=function(a){this._setAction("promo_click"),this._trackEvent("Internal Promotions","click",a)},this._productClick=function(a){this._setAction("click",R(null,null,null,null,null,null,a,null,null)),this._trackEvent("UX","click",a)},this._pageView=function(a){V(function(){W(N("send",a),"pageview")})},this._send=function(){var a=Array.prototype.slice.call(arguments);a.unshift("send"),V(function(){W.apply(K,a)})},this._set=function(a,b,c){V(function(){W(N("set",c),a,b)})},this._trackTimings=function(a,c,d,e){V(function(){X(b,"send","timing",a,c,d,e)})},this._trackException=function(a,c){V(function(){X(b,"send","exception",{exDescription:a,exFatal:!!c})})},n||(this._registerScriptTags(),this._registerTrackers()),C&&H.$on(x,function(){(!y||O.current&&O.current.templateUrl&&!O.current.doNotTrack)&&K._trackPage()}),{log:K.log,offlineQueue:K.offlineQueue,configuration:{accounts:c,universalAnalytics:h,crossDomainLinker:k,crossLinkDomains:d,currency:l,debugMode:m,delayScriptTag:n,disableAnalytics:p,displayFeatures:o,domainName:e,ecommerce:K._ecommerceEnabled(),enhancedEcommerce:K._enhancedEcommerceEnabled(),enhancedLinkAttribution:s,experimentId:f,hybridMobileSupport:v,ignoreFirstPageLoad:t,logAllCalls:u,pageEvent:x,readFromRoute:y,removeRegExp:g,testMode:z,traceDebuggingMode:A,trackPrefix:B,trackRoutes:C,trackUrlParams:D},getUrl:P,setCookieConfig:function(a){return K._log("warn","DEPRECATION WARNING: setCookieConfig method is deprecated. Please use tracker fields instead."),K._setCookieConfig.apply(K,arguments)},getCookieConfig:function(){return K._log("warn","DEPRECATION WARNING: getCookieConfig method is deprecated. Please use tracker fields instead."),i},createAnalyticsScriptTag:function(a){return K._log("warn","DEPRECATION WARNING: createAnalyticsScriptTag method is deprecated. Please use registerScriptTags and registerTrackers methods instead."),a&&(i=a),K._createAnalyticsScriptTag()},createScriptTag:function(){return K._log("warn","DEPRECATION WARNING: createScriptTag method is deprecated. Please use registerScriptTags and registerTrackers methods instead."),K._createScriptTag()},registerScriptTags:function(){return K._registerScriptTags()},registerTrackers:function(){return K._registerTrackers()},offline:function(a){if(a===!0&&w===!1&&(w=!0),a===!1&&w===!0)for(w=!1;K.offlineQueue.length>0;){var b=K.offlineQueue.shift();b[0].apply(K,b[1])}return w},trackPage:function(a,b,c){K._trackPage.apply(K,arguments)},trackEvent:function(a,b,c,d,e,f){K._trackEvent.apply(K,arguments)},addTrans:function(a,b,c,d,e,f,g,h,i){K._addTrans.apply(K,arguments)},addItem:function(a,b,c,d,e,f){K._addItem.apply(K,arguments)},trackTrans:function(){K._trackTrans.apply(K,arguments)},clearTrans:function(){K._clearTrans.apply(K,arguments)},addProduct:function(a,b,c,d,e,f,g,h,i,j){K._addProduct.apply(K,arguments)},addPromo:function(a,b,c,d){K._addPromo.apply(K,arguments)},addImpression:function(a,b,c,d,e,f,g,h){K._addImpression.apply(K,arguments)},productClick:function(a){K._productClick.apply(K,arguments)},promoClick:function(a){K._promoClick.apply(K,arguments)},trackDetail:function(){K._trackDetail.apply(K,arguments)},trackCart:function(a,b){K._trackCart.apply(K,arguments)},trackCheckout:function(a,b){K._trackCheckOut.apply(K,arguments)},trackTimings:function(a,b,c,d){K._trackTimings.apply(K,arguments)},trackTransaction:function(a,b,c,d,e,f,g,h,i){K._trackTransaction.apply(K,arguments)},trackException:function(a,b){K._trackException.apply(K,arguments)},setAction:function(a,b){K._setAction.apply(K,arguments)},pageView:function(){K._pageView.apply(K,arguments)},send:function(a){K._send.apply(K,arguments)},set:function(a,b,c){K._set.apply(K,arguments)}}}]}).directive("gaTrackEvent",["Analytics","$parse",function(a,b){return{restrict:"A",link:function(c,d,e){var f=b(e.gaTrackEvent);d.bind("click",function(){e.gaTrackEventIf&&!c.$eval(e.gaTrackEventIf)||f.length>1&&a.trackEvent.apply(a,f(c))})}}}]),a.module("angular-google-analytics")}); \ No newline at end of file -- 2.0.0