Commit d45f7746ac174146dbfc0fc04628dea3369a859a
1 parent
f263889f05
Exists in
master
and in
1 other branch
file add
Showing
2 changed files
with
1308 additions
and
0 deletions
Show diff stats
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")}); |