Shoora
9/27/2019 - 11:55 AM

analytics.js

/**
 * @class Analytics
 * @author Joshua Russell <josh.russell@holler.com.au>
 * 
 * A wrapper class for sending Google Analytics events
 * https://developers.google.com/analytics/devguides/collection/analyticsjs/events
 * ga('send', 'event', [eventCategory], [eventAction], [eventLabel], [eventValue]);
 * 
 * Usage:
 * Add a data-ga to html elements to track `click` events
 * <a href="/" data-ga="cta|click|Site Logo">Site Logo</a>
 * 
 * Format:
 * eventCategory(required)|eventAction(required)|eventLabel(required)|dynamicValue(optional)
 * The dynamicValue is used to take the value from input fields to construct the label
 * 
 * Events:
 * @event analyticsRebuild
 *  - Rebuilds all click listeners
 *  - Handy when HTML is dynamically generated with `data-ga` attributes
 */
export default class Analytics {
  constructor(key) {
    this.devMode = false;
    this.key = key;
    this.links = [];
    this.delimiter = '|';

    // Append event listeners
    window.addEventListener('Analytics.appendLink', (data) => {
      if (!data.detail.link) return;

      const link = document.querySelector(data.detail.link);

      if (link && link.dataset.ga) {
        link.addEventListener('click', this.handleClick.bind(this, link));
      }
    });

    // Init
    this.init();
  }

  /**
   * @function links
   * Creates event listeners for all [data-ga] links
   */
  init() {
    this.links = document.querySelectorAll('[data-ga]');
    
    this.links.forEach(link => {
      link.addEventListener('click', this.handleClick.bind(this, link));
    });
  }

  /**
   * @function handleClick
   * @param {HTMLElement} link 
   * @param {Event} e 
   */
  handleClick(link, e) {
    if (this.devMode) e.preventDefault();
    this.click(link);
  }

  /**
   * @function click
   * @param {HTMLElement} link 
   * Handles clicking on an element with [data-ga] attributes
   * Determines the GA event data
   * Sends the GA event
   */
  click(link) {
    if (!window.hasOwnProperty('ga')) {
      return console.warn('Cannot initialise Analytics without GA! — analytics.js');
    }

    const parts = link.dataset.ga.split(this.delimiter);

    let category = parts[0];
    let event = parts[1];
    let label = parts[2];
    
    // Get the value from a inputs element
    if (parts[3]) {
      const element = document.querySelector(parts[3]);
      if (element.value) {
        label += ` (${element.value})`;
      }
    }

    // Send the event
    this.send(category, event, label);
  }

  /**
   * @function send
   * @param {String} category
   * @param {String} event
   * @param {String} label
   * Sends the GA Event
   */
  send(category, event, label) {
    if (!window.hasOwnProperty('ga')) {
      return console.warn('Google Analytics not installed correctly! — analytics.js');
    }

    const trackerName = ga.getAll()[0].get('name');

    if (category && event && label) {
      ga(`${trackerName}.send`, 'event', category, event, label);
    }
  }
}