services/analytics-service.js

/**
 * AngularJS Service for Google Analytics.
 *
 * @module analyticsService
 * @see https://docs.angularjs.org/api/ng/type/angular.Module#service
 */
angular.module('tgaApp').service('analyticsService', ['$window', '$log',
  function analyticsService($window, $log) {
    /**
     * Check whether Google Analytics is disabled.
     *
     * @returns {boolean}
     */
    this.noGA = () => !$window.ga || angular.isUndefined($window.ga);

    /**
     * Send Google Analytics `timing` hit for page load.
     */
    this.sendPageLoad = () => {
      if (this.noGA()) return;
      // Feature detects Navigation Timing API support.
      if ($window.performance) {
        // Gets the number of milliseconds since page load
        // (and rounds the result since the value must be an integer).
        const timeSincePageLoad = Math.round($window.performance.now());
        // Sends the timing hit to Google Analytics.
        $window.ga('send', 'timing', 'Dependencies', 'load', timeSincePageLoad);
        $log.debug('page load analytics fired');
      }
    };

    /**
     * Send configurable Google Analytics `timing` hit.
     *
     * @see https://developers.google.com/analytics/devguides/collection/analyticsjs/user-timings
     *
     * @param {Object} data
     * @param {string} data.category - A string for categorizing all user timing variables into logical groups
     *                                 (e.g. `JS Dependencies`).
     * @param {string} data.var - The number of milliseconds in elapsed time to report to Google Analytics (e.g. `20`).
     * @param {number} data.value - A string that can be used to add flexibility in visualizing user timings in the
     *                              reports (e.g. `Google CDN`).
     */
    this.sendTimingEvent = (data) => {
      if (this.noGA()) return;
      $window.ga('send', 'timing', data.category, data.var, data.value);
      $log.debug('page timing event fired:', data);
    };

    /**
     * Send configurable Google Analytics `event` hit.
     *
     * @see https://developers.google.com/analytics/devguides/collection/analyticsjs/events
     * @see https://developers.google.com/analytics/devguides/collection/analyticsjs/sending-hits#the_send_method
     *
     * @param {Object} data
     * @param {string} data.category - Typically the object that was interacted with (e.g. `Video`).
     * @param {string} data.action - The type of interaction (e.g. `play`).
     * @param {string} data.label - Useful for categorizing events (e.g. `Fall Campaign`).
     * @param {number} data.value - A numeric value associated with the event (e.g. `42`).
     */
    this.sendEvent = (data) => {
      if (this.noGA()) return;
      const eventDetails = {
        hitType: 'event',
        eventCategory: data.category,
        eventAction: data.action,
      };

      if (data.label != null) eventDetails.eventLabel = data.label;
      if (data.value != null) eventDetails.eventValue = data.value;

      $window.ga('send', eventDetails);
      $log.debug('analytics event fired:', data);
    };
  },
]);