Commit d45f7746ac174146dbfc0fc04628dea3369a859a

Authored by Palak Handa
1 parent f263889f05
Exists in master and in 1 other branch paytm

file add

dist/angular-google-analytics.js
File was created 1 /**
2 * Angular Google Analytics - Easy tracking for your AngularJS application
3 * @version v1.1.8 - 2016-12-30
4 * @link http://github.com/revolunet/angular-google-analytics
5 * @author Julien Bouquillon <julien@revolunet.com> (https://github.com/revolunet)
6 * @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)
7 * @license MIT License, http://www.opensource.org/licenses/MIT
8 */
9 /* globals define */
10 (function (root, factory) {
11 'use strict';
12 if (typeof module !== 'undefined' && module.exports) {
13 if (typeof angular === 'undefined') {
14 factory(require('angular'));
15 } else {
16 factory(angular);
17 }
18 module.exports = 'angular-google-analytics';
19 } else if (typeof define === 'function' && define.amd) {
20 define(['angular'], factory);
21 } else {
22 factory(root.angular);
23 }
24 }(this, function (angular, undefined) {
25 'use strict';
26 angular.module('angular-google-analytics', [])
27 .provider('Analytics', function () {
28 var accounts,
29 analyticsJS = true,
30 cookieConfig = 'auto', // DEPRECATED
31 created = false,
32 crossDomainLinker = false,
33 crossLinkDomains,
34 currency = 'USD',
35 debugMode = false,
36 delayScriptTag = false,
37 displayFeatures = false,
38 disableAnalytics = false,
39 domainName,
40 ecommerce = false,
41 enhancedEcommerce = false,
42 enhancedLinkAttribution = false,
43 experimentId,
44 ignoreFirstPageLoad = false,
45 logAllCalls = false,
46 hybridMobileSupport = false,
47 offlineMode = false,
48 pageEvent = '$routeChangeSuccess',
49 readFromRoute = false,
50 removeRegExp,
51 testMode = false,
52 traceDebuggingMode = false,
53 trackPrefix = '',
54 trackRoutes = true,
55 trackUrlParams = false;
56
57 this.log = [];
58 this.offlineQueue = [];
59
60 /**
61 * Configuration Methods
62 **/
63
64 this.setAccount = function (tracker) {
65 if (angular.isUndefined(tracker) || tracker === false) {
66 accounts = undefined;
67 } else if (angular.isArray(tracker)) {
68 accounts = tracker;
69 } else if (angular.isObject(tracker)) {
70 accounts = [tracker];
71 } else {
72 // In order to preserve an existing behavior with how the _trackEvent function works,
73 // the trackEvent property must be set to true when there is only a single tracker.
74 accounts = [{ tracker: tracker, trackEvent: true }];
75 }
76 return this;
77 };
78
79 this.trackPages = function (val) {
80 trackRoutes = !!val;
81 return this;
82 };
83
84 this.trackPrefix = function (prefix) {
85 trackPrefix = prefix;
86 return this;
87 };
88
89 this.setDomainName = function (domain) {
90 domainName = domain;
91 return this;
92 };
93
94 this.useDisplayFeatures = function (val) {
95 displayFeatures = !!val;
96 return this;
97 };
98
99 this.useAnalytics = function (val) {
100 analyticsJS = !!val;
101 return this;
102 };
103
104 this.useEnhancedLinkAttribution = function (val) {
105 enhancedLinkAttribution = !!val;
106 return this;
107 };
108
109 this.useCrossDomainLinker = function (val) {
110 crossDomainLinker = !!val;
111 return this;
112 };
113
114 this.setCrossLinkDomains = function (domains) {
115 crossLinkDomains = domains;
116 return this;
117 };
118
119 this.setPageEvent = function (name) {
120 pageEvent = name;
121 return this;
122 };
123
124 /* DEPRECATED */
125 this.setCookieConfig = function (config) {
126 cookieConfig = config;
127 return this;
128 };
129
130 this.useECommerce = function (val, enhanced) {
131 ecommerce = !!val;
132 enhancedEcommerce = !!enhanced;
133 return this;
134 };
135
136 this.setCurrency = function (currencyCode) {
137 currency = currencyCode;
138 return this;
139 };
140
141 this.setRemoveRegExp = function (regex) {
142 if (regex instanceof RegExp) {
143 removeRegExp = regex;
144 }
145 return this;
146 };
147
148 this.setExperimentId = function (id) {
149 experimentId = id;
150 return this;
151 };
152
153 this.ignoreFirstPageLoad = function (val) {
154 ignoreFirstPageLoad = !!val;
155 return this;
156 };
157
158 this.trackUrlParams = function (val) {
159 trackUrlParams = !!val;
160 return this;
161 };
162
163 this.disableAnalytics = function (val) {
164 disableAnalytics = !!val;
165 return this;
166 };
167
168 this.setHybridMobileSupport = function (val) {
169 hybridMobileSupport = !!val;
170 return this;
171 };
172
173 this.startOffline = function (val) {
174 offlineMode = !!val;
175 if (offlineMode === true) {
176 this.delayScriptTag(true);
177 }
178 return this;
179 };
180
181 this.delayScriptTag = function (val) {
182 delayScriptTag = !!val;
183 return this;
184 };
185
186 this.logAllCalls = function (val) {
187 logAllCalls = !!val;
188 return this;
189 };
190
191 this.enterTestMode = function () {
192 testMode = true;
193 return this;
194 };
195
196 this.enterDebugMode = function (enableTraceDebugging) {
197 debugMode = true;
198 traceDebuggingMode = !!enableTraceDebugging;
199 return this;
200 };
201
202 // Enable reading page url from route object
203 this.readFromRoute = function(val) {
204 readFromRoute = !!val;
205 return this;
206 };
207
208 /**
209 * Public Service
210 */
211 this.$get = ['$document', // To read page title
212 '$location', //
213 '$log', //
214 '$rootScope',//
215 '$window', //
216 '$injector', // To access ngRoute module without declaring a fixed dependency
217 function ($document, $location, $log, $rootScope, $window, $injector) {
218 var that = this;
219
220 /**
221 * Side-effect Free Helper Methods
222 **/
223
224 var isPropertyDefined = function (key, config) {
225 return angular.isObject(config) && angular.isDefined(config[key]);
226 };
227
228 var isPropertySetTo = function (key, config, value) {
229 return isPropertyDefined(key, config) && config[key] === value;
230 };
231
232 var generateCommandName = function (commandName, config) {
233 if (angular.isString(config)) {
234 return config + '.' + commandName;
235 }
236 return isPropertyDefined('name', config) ? (config.name + '.' + commandName) : commandName;
237 };
238
239 // Try to read route configuration and log warning if not possible
240 var $route = {};
241 if (readFromRoute) {
242 if (!$injector.has('$route')) {
243 $log.warn('$route service is not available. Make sure you have included ng-route in your application dependencies.');
244 } else {
245 $route = $injector.get('$route');
246 }
247 }
248
249 // Get url for current page
250 var getUrl = function () {
251 // Using ngRoute provided tracking urls
252 if (readFromRoute && $route.current && ('pageTrack' in $route.current)) {
253 return $route.current.pageTrack;
254 }
255
256 // Otherwise go the old way
257 var url = trackUrlParams ? $location.url() : $location.path();
258 return removeRegExp ? url.replace(removeRegExp, '') : url;
259 };
260
261 var getUtmParams = function () {
262 var utmToCampaignVar = {
263 utm_source: 'campaignSource',
264 utm_medium: 'campaignMedium',
265 utm_term: 'campaignTerm',
266 utm_content: 'campaignContent',
267 utm_campaign: 'campaignName'
268 };
269 var object = {};
270
271 angular.forEach($location.search(), function (value, key) {
272 var campaignVar = utmToCampaignVar[key];
273
274 if (angular.isDefined(campaignVar)) {
275 object[campaignVar] = value;
276 }
277 });
278
279 return object;
280 };
281
282 /**
283 * get ActionFieldObject
284 * https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce#action-data
285 * @param id
286 * @param affliation
287 * @param revenue
288 * @param tax
289 * @param shipping
290 * @param coupon
291 * @param list
292 * @param step
293 * @param option
294 */
295 var getActionFieldObject = function (id, affiliation, revenue, tax, shipping, coupon, list, step, option) {
296 var obj = {};
297 if (id) { obj.id = id; }
298 if (affiliation) { obj.affiliation = affiliation; }
299 if (revenue) { obj.revenue = revenue; }
300 if (tax) { obj.tax = tax; }
301 if (shipping) { obj.shipping = shipping; }
302 if (coupon) { obj.coupon = coupon; }
303 if (list) { obj.list = list; }
304 if (step) { obj.step = step; }
305 if (option) { obj.option = option; }
306 return obj;
307 };
308
309 /**
310 * Private Methods
311 */
312
313 var _getProtocol = function (httpPostfix, httpsPostfix) {
314 var protocol = '',
315 isSslEnabled = document.location.protocol === 'https:',
316 isChromeExtension = document.location.protocol === 'chrome-extension:',
317 isHybridApplication = analyticsJS === true && hybridMobileSupport === true;
318 httpPostfix = angular.isString(httpPostfix) ? httpPostfix : '';
319 httpsPostfix = angular.isString(httpsPostfix) ? httpsPostfix : '';
320 if (httpPostfix !== '') {
321 protocol = 'http:' + httpPostfix;
322 }
323 if (isChromeExtension || isHybridApplication || (isSslEnabled && httpsPostfix !== '')) {
324 protocol = 'https:' + httpsPostfix;
325 }
326 return protocol;
327 };
328
329 var _gaJs = function (fn) {
330 if (!analyticsJS && $window._gaq && typeof fn === 'function') {
331 fn();
332 }
333 };
334
335 var _gaq = function () {
336 var args = Array.prototype.slice.call(arguments);
337 if (offlineMode === true) {
338 that.offlineQueue.push([_gaq, args]);
339 return;
340 }
341 if (!$window._gaq) {
342 $window._gaq = [];
343 }
344 if (logAllCalls === true) {
345 that._log.apply(that, args);
346 }
347 $window._gaq.push(args);
348 };
349
350 var _analyticsJs = function (fn) {
351 if (analyticsJS && $window.ga && typeof fn === 'function') {
352 fn();
353 }
354 };
355
356 var _ga = function () {
357 var args = Array.prototype.slice.call(arguments);
358 if (offlineMode === true) {
359 that.offlineQueue.push([_ga, args]);
360 return;
361 }
362 if (typeof $window.ga !== 'function') {
363 that._log('warn', 'ga function not set on window');
364 return;
365 }
366 if (logAllCalls === true) {
367 that._log.apply(that, args);
368 }
369 $window.ga.apply(null, args);
370 };
371
372 var _gaMultipleTrackers = function (includeFn) {
373 // Drop the includeFn from the arguments and preserve the original command name
374 var args = Array.prototype.slice.call(arguments, 1),
375 commandName = args[0],
376 trackers = [];
377 if (typeof includeFn === 'function') {
378 accounts.forEach(function (account) {
379 if (includeFn(account)) {
380 trackers.push(account);
381 }
382 });
383 } else {
384 // No include function indicates that all accounts are to be used
385 trackers = accounts;
386 }
387
388 // To preserve backwards compatibility fallback to _ga method if no account
389 // matches the specified includeFn. This preserves existing behaviors by
390 // performing the single tracker operation.
391 if (trackers.length === 0) {
392 _ga.apply(that, args);
393 return;
394 }
395
396 trackers.forEach(function (tracker) {
397 // Check tracker 'select' function, if it exists, for whether the tracker should be used with the current command.
398 // If the 'select' function returns false then the tracker will not be used with the current command.
399 if (isPropertyDefined('select', tracker) && typeof tracker.select === 'function' && !tracker.select(args)) {
400 return;
401 }
402 args[0] = generateCommandName(commandName, tracker);
403 _ga.apply(that, args);
404 });
405 };
406
407 this._log = function () {
408 var args = Array.prototype.slice.call(arguments);
409 if (args.length > 0) {
410 if (args.length > 1) {
411 switch (args[0]) {
412 case 'debug':
413 case 'error':
414 case 'info':
415 case 'log':
416 case 'warn':
417 $log[args[0]](args.slice(1));
418 break;
419 }
420 }
421 that.log.push(args);
422 }
423 };
424
425 /* DEPRECATED */
426 this._createScriptTag = function () {
427 that._registerScriptTags();
428 that._registerTrackers();
429 };
430
431 /* DEPRECATED */
432 this._createAnalyticsScriptTag = function () {
433 that._registerScriptTags();
434 that._registerTrackers();
435 };
436
437 this._registerScriptTags = function () {
438 var document = $document[0],
439 protocol = _getProtocol(),
440 scriptSource;
441
442 if (created === true) {
443 that._log('warn', 'Script tags already created');
444 return;
445 }
446
447 if (disableAnalytics === true) {
448 accounts.forEach(function (trackerObj) {
449 that._log('info', 'Analytics disabled: ' + trackerObj.tracker);
450 $window['ga-disable-' + trackerObj.tracker] = true;
451 });
452 }
453
454 //
455 // Universal Analytics
456 //
457 if (analyticsJS === true) {
458 scriptSource = protocol + '//www.google-analytics.com/' + (debugMode ? 'analytics_debug.js' : 'analytics.js');
459 if (testMode !== true) {
460 // If not in test mode inject the Google Analytics tag
461 (function (i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function (){
462 (i[r].q=i[r].q||[]).push(arguments);},i[r].l=1*new Date();a=s.createElement(o),
463 m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m);
464 })(window,document,'script',scriptSource,'ga');
465 } else {
466 if (typeof $window.ga !== 'function') {
467 // In test mode create a ga function if none exists that is a noop sink.
468 $window.ga = function () {};
469 }
470 // Log script injection.
471 that._log('inject', scriptSource);
472 }
473
474 if (traceDebuggingMode) {
475 $window.ga_debug = { trace: true };
476 }
477
478 if (experimentId) {
479 var expScript = document.createElement('script'),
480 s = document.getElementsByTagName('script')[0];
481 expScript.src = protocol + '//www.google-analytics.com/cx/api.js?experiment=' + experimentId;
482 s.parentNode.insertBefore(expScript, s);
483 }
484 //
485 // Classic Analytics
486 //
487 } else {
488 scriptSource = _getProtocol('//www', '//ssl') + '.google-analytics.com/ga.js';
489 if (displayFeatures === true) {
490 scriptSource = protocol + '//stats.g.doubleclick.net/dc.js';
491 }
492
493 if (testMode !== true) {
494 // If not in test mode inject the Google Analytics tag
495 (function () {
496 var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
497 ga.src = scriptSource;
498 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
499 })();
500 } else {
501 // Log the source location for validation
502 that._log('inject', scriptSource);
503 }
504 }
505
506 created = true;
507 return true;
508 };
509
510 this._registerTrackers = function () {
511 if (!accounts || accounts.length < 1) {
512 that._log('warn', 'No accounts to register');
513 return;
514 }
515
516 //
517 // Universal Analytics
518 //
519 if (analyticsJS === true) {
520 accounts.forEach(function (trackerObj) {
521 trackerObj.crossDomainLinker = isPropertyDefined('crossDomainLinker', trackerObj) ? trackerObj.crossDomainLinker : crossDomainLinker;
522 trackerObj.crossLinkDomains = isPropertyDefined('crossLinkDomains', trackerObj) ? trackerObj.crossLinkDomains : crossLinkDomains;
523 trackerObj.displayFeatures = isPropertyDefined('displayFeatures', trackerObj) ? trackerObj.displayFeatures : displayFeatures;
524 trackerObj.enhancedLinkAttribution = isPropertyDefined('enhancedLinkAttribution', trackerObj) ? trackerObj.enhancedLinkAttribution : enhancedLinkAttribution;
525 trackerObj.set = isPropertyDefined('set', trackerObj) ? trackerObj.set : {};
526 trackerObj.trackEcommerce = isPropertyDefined('trackEcommerce', trackerObj) ? trackerObj.trackEcommerce : ecommerce;
527 trackerObj.trackEvent = isPropertyDefined('trackEvent', trackerObj) ? trackerObj.trackEvent : false;
528
529 // Logic to choose the account fields to be used.
530 // cookieConfig is being deprecated for a tracker specific property: fields.
531 var fields = {};
532 if (isPropertyDefined('fields', trackerObj)) {
533 fields = trackerObj.fields;
534 } else if (isPropertyDefined('cookieConfig', trackerObj)) {
535 if (angular.isString(trackerObj.cookieConfig)) {
536 fields.cookieDomain = trackerObj.cookieConfig;
537 } else {
538 fields = trackerObj.cookieConfig;
539 }
540 } else if (angular.isString(cookieConfig)) {
541 fields.cookieDomain = cookieConfig;
542 } else if (cookieConfig) {
543 fields = cookieConfig;
544 }
545 if (trackerObj.crossDomainLinker === true) {
546 fields.allowLinker = true;
547 }
548 if (isPropertyDefined('name', trackerObj)) {
549 fields.name = trackerObj.name;
550 }
551 trackerObj.fields = fields;
552
553 _ga('create', trackerObj.tracker, trackerObj.fields);
554
555 // Hybrid mobile application support
556 // https://developers.google.com/analytics/devguides/collection/analyticsjs/tasks
557 if (hybridMobileSupport === true) {
558 _ga(generateCommandName('set', trackerObj), 'checkProtocolTask', null);
559 }
560
561 // Send all custom set commands from the trackerObj.set property
562 for (var key in trackerObj.set) {
563 if (trackerObj.set.hasOwnProperty(key)) {
564 _ga(generateCommandName('set', trackerObj), key, trackerObj.set[key]);
565 }
566 }
567
568 if (trackerObj.crossDomainLinker === true) {
569 _ga(generateCommandName('require', trackerObj), 'linker');
570 if (angular.isDefined(trackerObj.crossLinkDomains)) {
571 _ga(generateCommandName('linker:autoLink', trackerObj), trackerObj.crossLinkDomains);
572 }
573 }
574
575 if (trackerObj.displayFeatures) {
576 _ga(generateCommandName('require', trackerObj), 'displayfeatures');
577 }
578
579 if (trackerObj.trackEcommerce) {
580 if (!enhancedEcommerce) {
581 _ga(generateCommandName('require', trackerObj), 'ecommerce');
582 } else {
583 _ga(generateCommandName('require', trackerObj), 'ec');
584 _ga(generateCommandName('set', trackerObj), '&cu', currency);
585 }
586 }
587
588 if (trackerObj.enhancedLinkAttribution) {
589 _ga(generateCommandName('require', trackerObj), 'linkid');
590 }
591
592 if (trackRoutes && !ignoreFirstPageLoad) {
593 _ga(generateCommandName('send', trackerObj), 'pageview', trackPrefix + getUrl());
594 }
595 });
596 //
597 // Classic Analytics
598 //
599 } else {
600 if (accounts.length > 1) {
601 that._log('warn', 'Multiple trackers are not supported with ga.js. Using first tracker only');
602 accounts = accounts.slice(0, 1);
603 }
604
605 _gaq('_setAccount', accounts[0].tracker);
606 if(domainName) {
607 _gaq('_setDomainName', domainName);
608 }
609 if (enhancedLinkAttribution) {
610 _gaq('_require', 'inpage_linkid', '//www.google-analytics.com/plugins/ga/inpage_linkid.js');
611 }
612 if (trackRoutes && !ignoreFirstPageLoad) {
613 if (removeRegExp) {
614 _gaq('_trackPageview', getUrl());
615 } else {
616 _gaq('_trackPageview');
617 }
618 }
619 }
620
621 return true;
622 };
623
624 this._ecommerceEnabled = function (warn, command) {
625 var result = ecommerce && !enhancedEcommerce;
626 if (warn === true && result === false) {
627 if (ecommerce && enhancedEcommerce) {
628 that._log('warn', command + ' is not available when Enhanced Ecommerce is enabled with analytics.js');
629 } else {
630 that._log('warn', 'Ecommerce must be enabled to use ' + command + ' with analytics.js');
631 }
632 }
633 return result;
634 };
635
636 this._enhancedEcommerceEnabled = function (warn, command) {
637 var result = ecommerce && enhancedEcommerce;
638 if (warn === true && result === false) {
639 that._log('warn', 'Enhanced Ecommerce must be enabled to use ' + command + ' with analytics.js');
640 }
641 return result;
642 };
643
644 /**
645 * Track page
646 https://developers.google.com/analytics/devguides/collection/gajs/
647 https://developers.google.com/analytics/devguides/collection/analyticsjs/pages
648 * @param url
649 * @param title
650 * @param custom
651 * @private
652 */
653 this._trackPage = function (url, title, custom) {
654 url = url ? url : getUrl();
655 title = title ? title : $document[0].title;
656 _gaJs(function () {
657 // http://stackoverflow.com/questions/7322288/how-can-i-set-a-page-title-with-google-analytics
658 _gaq('_set', 'title', title);
659 _gaq('_trackPageview', (trackPrefix + url));
660 });
661 _analyticsJs(function () {
662 var opt_fieldObject = {
663 'page': trackPrefix + url,
664 'title': title
665 };
666 angular.extend(opt_fieldObject, getUtmParams());
667 if (angular.isObject(custom)) {
668 angular.extend(opt_fieldObject, custom);
669 }
670 _gaMultipleTrackers(undefined, 'send', 'pageview', opt_fieldObject);
671 });
672 };
673
674 /**
675 * Track event
676 https://developers.google.com/analytics/devguides/collection/gajs/eventTrackerGuide
677 https://developers.google.com/analytics/devguides/collection/analyticsjs/events
678 * @param category
679 * @param action
680 * @param label
681 * @param value
682 * @param noninteraction
683 * @param custom
684 * @private
685 */
686 this._trackEvent = function (category, action, label, value, noninteraction, custom) {
687 _gaJs(function () {
688 _gaq('_trackEvent', category, action, label, value, !!noninteraction);
689 });
690 _analyticsJs(function () {
691 var opt_fieldObject = {};
692 var includeFn = function (trackerObj) {
693 return isPropertySetTo('trackEvent', trackerObj, true);
694 };
695
696 if (angular.isDefined(noninteraction)) {
697 opt_fieldObject.nonInteraction = !!noninteraction;
698 }
699 if (angular.isObject(custom)) {
700 angular.extend(opt_fieldObject, custom);
701 }
702 if (!angular.isDefined(opt_fieldObject.page)) {
703 opt_fieldObject.page = getUrl();
704 }
705 _gaMultipleTrackers(includeFn, 'send', 'event', category, action, label, value, opt_fieldObject);
706 });
707 };
708
709 /**
710 * Add transaction
711 * https://developers.google.com/analytics/devguides/collection/gajs/methods/gaJSApiEcommerce#_gat.GA_Tracker_._addTrans
712 * https://developers.google.com/analytics/devguides/collection/analyticsjs/ecommerce#addTrans
713 * @param transactionId
714 * @param affiliation
715 * @param total
716 * @param tax
717 * @param shipping
718 * @param city
719 * @param state
720 * @param country
721 * @private
722 */
723 this._addTrans = function (transactionId, affiliation, total, tax, shipping, city, state, country, currency) {
724 _gaJs(function () {
725 _gaq('_addTrans', transactionId, affiliation, total, tax, shipping, city, state, country);
726 });
727 _analyticsJs(function () {
728 if (that._ecommerceEnabled(true, 'addTrans')) {
729 var includeFn = function (trackerObj) {
730 return isPropertySetTo('trackEcommerce', trackerObj, true);
731 };
732
733 _gaMultipleTrackers(
734 includeFn,
735 'ecommerce:addTransaction',
736 {
737 id: transactionId,
738 affiliation: affiliation,
739 revenue: total,
740 tax: tax,
741 shipping: shipping,
742 currency: currency || 'USD'
743 });
744 }
745 });
746 };
747
748 /**
749 * Add item to transaction
750 * https://developers.google.com/analytics/devguides/collection/gajs/methods/gaJSApiEcommerce#_gat.GA_Tracker_._addItem
751 * https://developers.google.com/analytics/devguides/collection/analyticsjs/ecommerce#addItem
752 * @param transactionId
753 * @param sku
754 * @param name
755 * @param category
756 * @param price
757 * @param quantity
758 * @private
759 */
760 this._addItem = function (transactionId, sku, name, category, price, quantity) {
761 _gaJs(function () {
762 _gaq('_addItem', transactionId, sku, name, category, price, quantity);
763 });
764 _analyticsJs(function () {
765 if (that._ecommerceEnabled(true, 'addItem')) {
766 var includeFn = function (trackerObj) {
767 return isPropertySetTo('trackEcommerce', trackerObj, true);
768 };
769
770 _gaMultipleTrackers(
771 includeFn,
772 'ecommerce:addItem',
773 {
774 id: transactionId,
775 name: name,
776 sku: sku,
777 category: category,
778 price: price,
779 quantity: quantity
780 });
781 }
782 });
783 };
784
785 /**
786 * Track transaction
787 * https://developers.google.com/analytics/devguides/collection/gajs/methods/gaJSApiEcommerce#_gat.GA_Tracker_._trackTrans
788 * https://developers.google.com/analytics/devguides/collection/analyticsjs/ecommerce#sendingData
789 * @private
790 */
791 this._trackTrans = function () {
792 _gaJs(function () {
793 _gaq('_trackTrans');
794 });
795 _analyticsJs(function () {
796 if (that._ecommerceEnabled(true, 'trackTrans')) {
797 var includeFn = function (trackerObj) {
798 return isPropertySetTo('trackEcommerce', trackerObj, true);
799 };
800
801 _gaMultipleTrackers(includeFn, 'ecommerce:send');
802 }
803 });
804 };
805
806 /**
807 * Clear transaction
808 * https://developers.google.com/analytics/devguides/collection/analyticsjs/ecommerce#clearingData
809 * @private
810 */
811 this._clearTrans = function () {
812 _analyticsJs(function () {
813 if (that._ecommerceEnabled(true, 'clearTrans')) {
814 var includeFn = function (trackerObj) {
815 return isPropertySetTo('trackEcommerce', trackerObj, true);
816 };
817
818 _gaMultipleTrackers(includeFn, 'ecommerce:clear');
819 }
820 });
821 };
822
823 /**
824 * Enhanced Ecommerce
825 */
826
827 /**
828 * Add Product
829 * https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce#product-data
830 * @param productId
831 * @param name
832 * @param category
833 * @param brand
834 * @param variant
835 * @param price
836 * @param quantity
837 * @param coupon
838 * @param position
839 * @param custom
840 * @private
841 */
842 this._addProduct = function (productId, name, category, brand, variant, price, quantity, coupon, position, custom) {
843 _gaJs(function () {
844 _gaq('_addProduct', productId, name, category, brand, variant, price, quantity, coupon, position);
845 });
846 _analyticsJs(function () {
847 if (that._enhancedEcommerceEnabled(true, 'addProduct')) {
848 var includeFn = function (trackerObj) {
849 return isPropertySetTo('trackEcommerce', trackerObj, true);
850 };
851 var details = {
852 id: productId,
853 name: name,
854 category: category,
855 brand: brand,
856 variant: variant,
857 price: price,
858 quantity: quantity,
859 coupon: coupon,
860 position: position
861 };
862 if (angular.isObject(custom)) {
863 angular.extend(details, custom);
864 }
865 _gaMultipleTrackers(includeFn, 'ec:addProduct', details);
866 }
867 });
868 };
869
870 /**
871 * Add Impression
872 * https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce#impression-data
873 * @param id
874 * @param name
875 * @param list
876 * @param brand
877 * @param category
878 * @param variant
879 * @param position
880 * @param price
881 * @private
882 */
883 this._addImpression = function (id, name, list, brand, category, variant, position, price){
884 _gaJs(function () {
885 _gaq('_addImpression', id, name, list, brand, category, variant, position, price);
886 });
887 _analyticsJs(function () {
888 if (that._enhancedEcommerceEnabled(true, 'addImpression')) {
889 var includeFn = function (trackerObj) {
890 return isPropertySetTo('trackEcommerce', trackerObj, true);
891 };
892
893 _gaMultipleTrackers(
894 includeFn,
895 'ec:addImpression',
896 {
897 id: id,
898 name: name,
899 category: category,
900 brand: brand,
901 variant: variant,
902 list: list,
903 position: position,
904 price: price
905 });
906 }
907 });
908 };
909
910 /**
911 * Add Promo
912 * https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce
913 * @param productId
914 * @param name
915 * @param creative
916 * @param position
917 * @private
918 */
919 this._addPromo = function (productId, name, creative, position) {
920 _gaJs(function () {
921 _gaq('_addPromo', productId, name, creative, position);
922 });
923 _analyticsJs(function () {
924 if (that._enhancedEcommerceEnabled(true, 'addPromo')) {
925 var includeFn = function (trackerObj) {
926 return isPropertySetTo('trackEcommerce', trackerObj, true);
927 };
928
929 _gaMultipleTrackers(
930 includeFn,
931 'ec:addPromo',
932 {
933 id: productId,
934 name: name,
935 creative: creative,
936 position: position
937 });
938 }
939 });
940 };
941
942 /**
943 * Set Action
944 * https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce#measuring-actions
945 * https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce#action-types
946 * @param action
947 * @param obj
948 * @private
949 */
950 this._setAction = function (action, obj){
951 _gaJs(function () {
952 _gaq('_setAction', action, obj);
953 });
954 _analyticsJs(function () {
955 if (that._enhancedEcommerceEnabled(true, 'setAction')) {
956 var includeFn = function (trackerObj) {
957 return isPropertySetTo('trackEcommerce', trackerObj, true);
958 };
959
960 _gaMultipleTrackers(includeFn, 'ec:setAction', action, obj);
961 }
962 });
963 };
964
965 /**
966 * Track Transaction
967 * https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce#measuring-transactions
968 * @param transactionId
969 * @param affiliation
970 * @param revenue
971 * @param tax
972 * @param shipping
973 * @param coupon
974 * @param list
975 * @param step
976 * @param option
977 * @private
978 */
979 this._trackTransaction = function (transactionId, affiliation, revenue, tax, shipping, coupon, list, step, option) {
980 this._setAction('purchase', getActionFieldObject(transactionId, affiliation, revenue, tax, shipping, coupon, list, step, option));
981 };
982
983 /**
984 * Track Refund
985 * https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce#measuring-refunds
986 * @param transactionId
987 * @private
988 */
989 this._trackRefund = function (transactionId) {
990 this._setAction('refund', getActionFieldObject(transactionId));
991 };
992
993 /**
994 * Track Checkout
995 * https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce#measuring-checkout
996 * @param step
997 * @param option
998 * @private
999 */
1000 this._trackCheckOut = function (step, option) {
1001 this._setAction('checkout', getActionFieldObject(null, null, null, null, null, null, null, step, option));
1002 };
1003
1004 /**
1005 * Track detail
1006 * @private
1007 */
1008 this._trackDetail = function () {
1009 this._setAction('detail');
1010 this._pageView();
1011 };
1012
1013 /**
1014 * Track add/remove to cart
1015 * https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce#add-remove-cart
1016 * @param action
1017 * @param list
1018 * @private
1019 */
1020 this._trackCart = function (action, listName) {
1021 if (['add', 'remove'].indexOf(action) !== -1) {
1022 this._setAction(action, { list: listName });
1023 this._trackEvent('UX', 'click', action + (action === 'add' ? ' to cart' : ' from cart'));
1024 }
1025 };
1026
1027 /**
1028 * Track promo click
1029 * https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce#measuring-promo-clicks
1030 * @param promotionName
1031 * @private
1032 */
1033 this._promoClick = function (promotionName) {
1034 this._setAction('promo_click');
1035 this._trackEvent('Internal Promotions', 'click', promotionName);
1036 };
1037
1038 /**
1039 * Track product click
1040 * https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce#measuring-promo-clicks
1041 * @param promotionName
1042 * @private
1043 */
1044 this._productClick = function (listName) {
1045 this._setAction('click', getActionFieldObject(null, null, null, null, null, null, listName, null, null));
1046 this._trackEvent('UX', 'click', listName);
1047 };
1048
1049 /**
1050 * Send page view
1051 * @param trackerName
1052 * @private
1053 */
1054 this._pageView = function (trackerName) {
1055 _analyticsJs(function () {
1056 _ga(generateCommandName('send', trackerName), 'pageview');
1057 });
1058 };
1059
1060 /**
1061 * Send custom events
1062 * https://developers.google.com/analytics/devguides/collection/analyticsjs/user-timings#implementation
1063 * https://developers.google.com/analytics/devguides/collection/analyticsjs/social-interactions#implementation
1064 * @private
1065 */
1066 this._send = function () {
1067 var args = Array.prototype.slice.call(arguments);
1068 args.unshift('send');
1069 _analyticsJs(function () {
1070 _ga.apply(that, args);
1071 });
1072 };
1073
1074 /**
1075 * Set custom dimensions, metrics or experiment
1076 * https://developers.google.com/analytics/devguides/collection/analyticsjs/custom-dims-mets
1077 * https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#customs
1078 * @param name (Required)
1079 * @param value (Required)
1080 * @param trackerName (Optional)
1081 * @private
1082 */
1083 this._set = function (name, value, trackerName) {
1084 _analyticsJs(function () {
1085 _ga(generateCommandName('set', trackerName), name, value);
1086 });
1087 };
1088
1089 /**
1090 * Track user timings
1091 * @param timingCategory (Required): A string for categorizing all user timing variables into logical groups(e.g jQuery).
1092 * @param timingVar (Required): A string to identify the variable being recorded(e.g. JavaScript Load).
1093 * @param timingValue (Required): The number of milliseconds in elapsed time to report to Google Analytics(e.g. 20).
1094 * @param timingLabel (Optional): A string that can be used to add flexibility in visualizing user timings in the reports(e.g. Google CDN).
1095 * @private
1096 */
1097 this._trackTimings = function (timingCategory, timingVar, timingValue, timingLabel) {
1098 _analyticsJs(function () {
1099 _gaMultipleTrackers(undefined, 'send', 'timing', timingCategory, timingVar, timingValue, timingLabel);
1100 });
1101 };
1102
1103 /**
1104 * Exception tracking
1105 * https://developers.google.com/analytics/devguides/collection/analyticsjs/exceptions
1106 * @param description (Optional): A description of the exception.
1107 * @param isFatal (Optional): true if the exception was fatal, false otherwise.
1108 * @private
1109 */
1110 this._trackException = function (description, isFatal) {
1111 _analyticsJs(function () {
1112 _gaMultipleTrackers(undefined, 'send', 'exception', { exDescription: description, exFatal: !!isFatal});
1113 });
1114 };
1115
1116 // creates the Google Analytics tracker
1117 if (!delayScriptTag) {
1118 this._registerScriptTags();
1119 this._registerTrackers();
1120 }
1121
1122 // activates page tracking
1123 if (trackRoutes) {
1124 $rootScope.$on(pageEvent, function () {
1125 // Apply $route based filtering if configured
1126 if (readFromRoute) {
1127 // Avoid tracking undefined routes, routes without template (e.g. redirect routes)
1128 // and those explicitly marked as 'do not track'
1129 if (!$route.current || !$route.current.templateUrl || $route.current.doNotTrack) {
1130 return;
1131 }
1132 }
1133
1134 that._trackPage();
1135 });
1136 }
1137
1138 return {
1139 log: that.log,
1140 offlineQueue: that.offlineQueue,
1141 configuration: {
1142 accounts: accounts,
1143 universalAnalytics: analyticsJS,
1144 crossDomainLinker: crossDomainLinker,
1145 crossLinkDomains: crossLinkDomains,
1146 currency: currency,
1147 debugMode: debugMode,
1148 delayScriptTag: delayScriptTag,
1149 disableAnalytics: disableAnalytics,
1150 displayFeatures: displayFeatures,
1151 domainName: domainName,
1152 ecommerce: that._ecommerceEnabled(),
1153 enhancedEcommerce: that._enhancedEcommerceEnabled(),
1154 enhancedLinkAttribution: enhancedLinkAttribution,
1155 experimentId: experimentId,
1156 hybridMobileSupport: hybridMobileSupport,
1157 ignoreFirstPageLoad: ignoreFirstPageLoad,
1158 logAllCalls: logAllCalls,
1159 pageEvent: pageEvent,
1160 readFromRoute: readFromRoute,
1161 removeRegExp: removeRegExp,
1162 testMode: testMode,
1163 traceDebuggingMode: traceDebuggingMode,
1164 trackPrefix: trackPrefix,
1165 trackRoutes: trackRoutes,
1166 trackUrlParams: trackUrlParams
1167 },
1168 getUrl: getUrl,
1169 /* DEPRECATED */
1170 setCookieConfig: function (config) {
1171 that._log('warn', 'DEPRECATION WARNING: setCookieConfig method is deprecated. Please use tracker fields instead.');
1172 return that._setCookieConfig.apply(that, arguments);
1173 },
1174 /* DEPRECATED */
1175 getCookieConfig: function () {
1176 that._log('warn', 'DEPRECATION WARNING: getCookieConfig method is deprecated. Please use tracker fields instead.');
1177 return cookieConfig;
1178 },
1179 /* DEPRECATED */
1180 createAnalyticsScriptTag: function (config) {
1181 that._log('warn', 'DEPRECATION WARNING: createAnalyticsScriptTag method is deprecated. Please use registerScriptTags and registerTrackers methods instead.');
1182 if (config) {
1183 cookieConfig = config;
1184 }
1185 return that._createAnalyticsScriptTag();
1186 },
1187 /* DEPRECATED */
1188 createScriptTag: function () {
1189 that._log('warn', 'DEPRECATION WARNING: createScriptTag method is deprecated. Please use registerScriptTags and registerTrackers methods instead.');
1190 return that._createScriptTag();
1191 },
1192 registerScriptTags: function () {
1193 return that._registerScriptTags();
1194 },
1195 registerTrackers: function () {
1196 return that._registerTrackers();
1197 },
1198 offline: function (mode) {
1199 if (mode === true && offlineMode === false) {
1200 // Go to offline mode
1201 offlineMode = true;
1202 }
1203 if (mode === false && offlineMode === true) {
1204 // Go to online mode and process the offline queue
1205 offlineMode = false;
1206 while (that.offlineQueue.length > 0) {
1207 var obj = that.offlineQueue.shift();
1208 obj[0].apply(that, obj[1]);
1209 }
1210 }
1211 return offlineMode;
1212 },
1213 trackPage: function (url, title, custom) {
1214 that._trackPage.apply(that, arguments);
1215 },
1216 trackEvent: function (category, action, label, value, noninteraction, custom) {
1217 that._trackEvent.apply(that, arguments);
1218 },
1219 addTrans: function (transactionId, affiliation, total, tax, shipping, city, state, country, currency) {
1220 that._addTrans.apply(that, arguments);
1221 },
1222 addItem: function (transactionId, sku, name, category, price, quantity) {
1223 that._addItem.apply(that, arguments);
1224 },
1225 trackTrans: function () {
1226 that._trackTrans.apply(that, arguments);
1227 },
1228 clearTrans: function () {
1229 that._clearTrans.apply(that, arguments);
1230 },
1231 addProduct: function (productId, name, category, brand, variant, price, quantity, coupon, position, custom) {
1232 that._addProduct.apply(that, arguments);
1233 },
1234 addPromo: function (productId, name, creative, position) {
1235 that._addPromo.apply(that, arguments);
1236 },
1237 addImpression: function (productId, name, list, brand, category, variant, position, price) {
1238 that._addImpression.apply(that, arguments);
1239 },
1240 productClick: function (listName) {
1241 that._productClick.apply(that, arguments);
1242 },
1243 promoClick : function (promotionName) {
1244 that._promoClick.apply(that, arguments);
1245 },
1246 trackDetail: function () {
1247 that._trackDetail.apply(that, arguments);
1248 },
1249 trackCart: function (action, list) {
1250 that._trackCart.apply(that, arguments);
1251 },
1252 trackCheckout: function (step, option) {
1253 that._trackCheckOut.apply(that, arguments);
1254 },
1255 trackTimings: function (timingCategory, timingVar, timingValue, timingLabel) {
1256 that._trackTimings.apply(that, arguments);
1257 },
1258 trackTransaction: function (transactionId, affiliation, revenue, tax, shipping, coupon, list, step, option) {
1259 that._trackTransaction.apply(that, arguments);
1260 },
1261 trackException: function (description, isFatal) {
1262 that._trackException.apply(that, arguments);
1263 },
1264 setAction: function (action, obj) {
1265 that._setAction.apply(that, arguments);
1266 },
1267 pageView: function () {
1268 that._pageView.apply(that, arguments);
1269 },
1270 send: function (obj) {
1271 that._send.apply(that, arguments);
1272 },
1273 set: function (name, value, trackerName) {
1274 that._set.apply(that, arguments);
1275 }
1276 };
1277 }];
1278 })
1279
1280 .directive('gaTrackEvent', ['Analytics', '$parse', function (Analytics, $parse) {
1281 return {
1282 restrict: 'A',
1283 link: function (scope, element, attrs) {
1284 var options = $parse(attrs.gaTrackEvent);
1285 element.bind('click', function () {
1286 if(attrs.gaTrackEventIf){
1287 if(!scope.$eval(attrs.gaTrackEventIf)){
1288 return; // Cancel this event if we don't pass the ga-track-event-if condition
1289 }
1290 }
1291 if (options.length > 1) {
1292 Analytics.trackEvent.apply(Analytics, options(scope));
1293 }
1294 });
1295 }
1296 };
1297 }]);
1298 return angular.module('angular-google-analytics');
1299 }));
1300
dist/angular-google-analytics.min.js
File was created 1 /**
2 * Angular Google Analytics - Easy tracking for your AngularJS application
3 * @version v1.1.8 - 2016-12-30
4 * @link http://github.com/revolunet/angular-google-analytics
5 * @author Julien Bouquillon <julien@revolunet.com> (https://github.com/revolunet)
6 * @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)
7 * @license MIT License, http://www.opensource.org/licenses/MIT
8 */
9 !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")});