Plugins are scripts that enhance the functionality of analytics.js to help solve problems and aid in measuring user interaction. This guide describes the process of writing your own analytics.js plugins. For information about how to use analytics.js plugins in your own implementations, see Using plugins.
Defining a plugin
Plugins are defined via the provide
command, which must be invoked with the name of the plugin as the first argument followed by the plugin's constructor function. When the provide
command is run, it registers the plugin to be used with the ga()
command queue.
The plugin constructor
The following is the most basic example of an analytics.js plugin:
// Defines the plugin constructor.
function MyPlugin() {
console.log('myplugin has been required...');
}
// Registers the plugin for use.
ga('provide', 'myplugin', MyPlugin);
Plugins need to function correctly even in cases where the global ga
object has been renamed, so if you're writing a plugin for third-party use, you should include a check to see if the GoogleAnalyticsObject
variable has been set to a string other than 'ga'
. The following providePlugin
function does this:
// 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 (typeof ga == 'function') {
ga('provide', pluginName, pluginConstructor);
}
}
Configuring Plugin Instances
When the ga()
command queue executes a require
command, it instantiates a new object using the new
operator on the provided plugin's constructor function. The constructor is passed the tracker object as its first argument, and any configuration options passed to the require
command as its second argument.
Consider the following require
command added to the JavaScript tracking snippet:
ga('create', 'UA-XXXXX-Y', 'auto');
ga('require', 'localHitSender', {path: '/log', debug: true});
ga('send', 'pageview');
And the localHitSender
code:
function LocalHitSender(tracker, config) {
this.path = config.path;
this.debug = config.debug;
if (this.debug) {
console.log('localHitSender enabled for path: ' + this.path);
console.log('on tracker: ' + tracker.get('name'));
}
}
providePlugin('localHitSender', LocalHitSender);
When the require
command is run, the following will be logged to the console (note that the name of the default tracker is "t0"):
// localHitSender enabled for path: /log
// on tracker: t0
Defining Plugin Methods
Plugins can expose their own methods which can be invoked using the ga
command queue syntax:
ga('[trackerName.]pluginName:methodName', ...args);
where trackerName
is optional and methodName
corresponds to the name of a function on the plugin constructors prototype. 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;
}:
Loading plugins
Plugins are typically loaded from a separate JavaScript file or bundled together with your main application code.
<script async src="myplugin.js"></script>
Plugins do not necessarily need to be defined before they are required. Since analytics.js is loaded asynchronously and plugins are often also loaded asynchronously, the ga()
command queue is built to handle this.
If the command queue receives a require
command for a plugin that has not yet been provided, it will hault execution of the remaining items in the queue until the plugin is available.
The following code shows how the ga('require', 'myplugin')
command is not actually executed until the ga('provide', 'myplugin', ...)
command is encountered, three seconds later.
ga('require', 'myplugin');
function MyPlugin() {
console.log('myplugin has been required...');
}
// Waits 3 second after running the `require`
// command before running the `provide` command.
setTimeout(function() {
ga('provide', 'myplugin', MyPlugin);
}, 3000);
Examples
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 (typeof ga == 'function') {
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);
The above code can be included into an HTML page as follows:
<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>
<!--Note: plugin scripts must be included after the tracking snippet. -->
<script async src="campaign-loader.js"></script>
Autotrack plugins
The autotrack library is open source, available on Github, and includes several analytics.js plugins that aid in tracking common user interactions. Refer to the autotrack source code to get a better understanding of how plugins work.