Hide

Plugins - Web Tracking (analytics.js)

This guide describes plugins, an advanced feature allowing developers to package their custom tracking libraries into asynchronously loaded scripts that can interact directly with the analytics.js command queue.

  1. Overview
    1. Require
    2. Provide
  2. Implementation
    1. Creating a Plugin Script
    2. Configuring Plugin Instances
    3. Defining Plugin Methods
  3. Example

Overview

Advanced users can often build up hundreds of lines of customized code to help manage tracking a complex site, or to provide extended features not already available in analytics.js. These custom libraries are typically loaded from a separate JavaScript file sourced throughout a site. In order to load these scripts quickly, without interrupting the loading and rendering of your website, we recommend that you always load such scripts asynchronously.

<script async src="myplugin.js"></script>

Since analytics.js is also loaded asynchronously, it can be challenging to coordinate the execution of your custom tracking script with the analytics.js command queue. The analytics.js plugin system solves this problem with two simple commands: require and provide.

Require

The require command takes the name of a plugin and blocks execution of any subquent commands until the target plugin has been loaded and executed.

ga('create', 'UA-XXXXX-Y', 'auto');
ga('require', 'myplugin');
ga('send', 'pageview');

In the example above, if 'myplugin' has not yet been loaded, the analytics.js command queue would pause until it becomes available. The 'send' command, and any subsequent commands in the page, would be blocked until that time.

Provide

To register your custom plugin with analytics.js, use the provide command. The provide command takes two arguments: the name of your plugin, and a constructor function that creates new instances of your plugin.

function MyPlugin(tracker) {
  alert('Loaded plugin on tracker ' + tracker.get('name'));
}
ga('provide', 'myplugin', MyPlugin);

In this example, myplugin.js contains a simple plugin function that pops up an alert box when loaded. This function will be invoked each time ga('require', 'myplugin'); is called.

Implementation

Now that we've covered the basics of the analytics.js plugin system, we can walk through the details involved in creating a plugin script, configuring plugin instances, and defining plugin methods.

Creating a Plugin Script

In addition to any other custom logic, each plugin script should include at least one plugin constructor function, and a call to the provide command to register that plugin. Since the plugin script needs to function correctly even if the analytics.js snippet has been configured to use a customized identifier for the ga global object, we can't simply call the ga('provide', ..) command. Instead, we include a copy of the providePlugin function shown below in each plugin script and use it to register the plugin.

myplugin.js

// Provides a plugin name and constructor function to analytics.js. This
// function works even if the site has customized the ga global identifier.
function providePlugin(pluginName, pluginConstructor) {
  var ga = window[window['GoogleAnalyticsObject'] || 'ga'];
  if (ga) ga('provide', pluginName, pluginConstructor);
}

// Plugin constructor.
function MyPlugin(tracker) {
  alert('Loaded myplugin on tracker ' + tracker.get('name'));
}

// Register the plugin.
providePlugin('myplugin', MyPlugin);

Configuring Plugin Instances

In addition to specifying the name of the plugin to load, the require command allows you to pass a configuration object used to initialize a plugin instance.

ga('create', 'UA-XXXXX-Y', 'auto');
ga('require', 'localHitSender', {path: '/log', debug: true});
ga('send', 'pageview');

The configuration object is passed to the plugin constructor as the second parameter.

function LocalHitSender(tracker, config) {
  this.url = config.url;
  this.debug = config.debug;
  if (this.debug) {
    alert('Enabled local hit sender for: ' + this.url);
  }
}
providePlugin('localHitSender', LocalHitSender);

Defining Plugin Methods

Plugins can expose their own methods which can be invoked using the ga command queue syntax:

ga('[targetName.][pluginName:]methodName', ...);

Where targetName is the name of the tracker. If targetName is not specified, the default target name 't0' is used. The pluginName is the name of the plugin. The methodName is the name of a method on the plugin instance. If methodName does not exist on the plugin or the plugin does not exist, an error will occur.

Example plugin method calls:

// Execute the 'doStuff' method using the 'myplugin' plugin.
ga('create', 'UA-XXXXX-Y', 'auto');
ga('require', 'myplugin');
ga('myplugin:doStuff');

// Execute the 'setEnabled' method of the 'hitCopy' plugin on tracker 't3'.
ga('create', 'UA-XXXXX-Y', 'auto', {name: 't3'});
ga('t3.require', 'hitcopy');
ga('t3.hitcopy:setEnabled', false);

Example plugin method definitions:

// myplugin constructor.
var MyPlugin = function(tracker) {
};

// myplugin:doStuff method definition.
MyPlugin.prototype.doStuff = function() {
  alert('doStuff method called!');
};

// hitcopy plugin.
var HitCopy = function(tracker) {
};

// hitcopy:setEnabled method definition.
HitCopy.prototype.setEnabled = function(isEnabled) {
  this.isEnabled = isEnabled;
}:

Example

The following example plugin is designed to capture custom campaign values from a page's URL and pass them to the tracker. This plugin demonstrates how to define and register a plugin script, pass plugin configuration parameters, and define and call plugin methods.

campaign-loader.js

function providePlugin(pluginName, pluginConstructor) {
  var ga = window[window['GoogleAnalyticsObject'] || 'ga'];
  if (ga) ga('provide', pluginName, pluginConstructor);
}

/**
 * Constructor for the campaignLoader plugin.
 */
var CampaignLoader = function(tracker, config) {
  this.tracker = tracker;
  this.nameParam = config.nameParam || 'name';
  this.sourceParam = config.sourceParam || 'source';
  this.mediumParam = config.mediumParam || 'medium';
  this.isDebug = config.debug;
};

/**
 * Loads campaign fields from the URL and updates the tracker.
 */
CampaignLoader.prototype.loadCampaignFields = function() {
  this.debugMessage('Loading custom campaign parameters');

  var nameValue = getUrlParam(this.nameParam);
  if (nameValue) {
    this.tracker.set('campaignName', nameValue);
    this.debugMessage('Loaded campaign name: ' + nameValue);
  }

  var sourceValue = getUrlParam(this.sourceParam);
  if (sourceValue) {
    this.tracker.set('campaignSource', sourceValue);
    this.debugMessage('Loaded campaign source: ' + sourceValue);
  }

  var mediumValue = getUrlParam(this.mediumParam);
  if (mediumValue) {
    this.tracker.set('campaignMedium', mediumValue);
    this.debugMessage('Loaded campaign medium: ' + mediumValue);
  }
};

/**
 * Enables / disables debug output.
 */
CampaignLoader.prototype.setDebug = function(enabled) {
  this.isDebug = enabled;
};

/**
 * Displays a debug message in the console, if debugging is enabled.
 */
CampaignLoader.prototype.debugMessage = function(message) {
  if (!this.isDebug) return;
  if (console) console.debug(message);
};

/**
 * Utility function to extract a URL parameter value.
 */
function getUrlParam(param) {
  var match = document.location.search.match('(?:\\?|&)' + param + '=([^&#]*)');
  return (match && match.length == 2) ? decodeURIComponent(match[1]) : '';
}

// Register the plugin.
providePlugin('campaignLoader', CampaignLoader);

index.html

<!DOCTYPE html>
<html>
  <head>

    <!-- Google Analytics Snippet-->
    <script>
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

    ga('create', 'UA-XXXXX-Y', 'auto');
    ga('require', 'campaignLoader', {
      debug: true,
      nameParam: 'cname',
      sourceParam: 'csrc',
      mediumParam: 'cmed'
    });
    ga('campaignLoader:loadCampaignFields');

    ga('send', 'pageview');
    </script>

    <!-- Plugin Script (must be sourced after the analytics.js snippet) -->
    <script async src="campaign-loader.js"></script>

  </head>

    ...