插件 - 网络跟踪 (analytics.js)

本指南介绍了插件。这是一种高级功能,可允许开发者将他们的自定义跟踪库打包为异步加载的脚本,并与 analytics.js 命令队列直接互动。

概览

高级用户经常会构建数百行的自定义代码来帮助跟踪复杂网站,或是实现 analytics.js 中未提供的扩展功能。这些自定义库通常从源自某个网站的单独 JavaScript 文件中加载。为了快速加载这些脚本而不对网站的加载和渲染造成干扰,我们建议您始终以异步方式加载这些脚本。

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

由于 analytics.js 也是异步加载,要协调您的自定义跟踪脚本与 analytics.js 命令队列的执行可能会是个挑战。analytics.js 插件系统使用两个简单的命令来解决这个问题:requireprovide

Require

require 命令接受插件名称作为参数,并会在目标插件加载和执行之前阻止后续命令的执行。

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

在上例中,如果 'myplugin' 尚未加载,则 analytics.js 命令队列将会暂停,直到该插件加载和执行完毕。在这之前,'send' 命令及网页中的后续命令都不会得到执行。

Provide

要在 analytics.js 中注册您的自定义插件,请使用 provide 命令。provide 命令接受两个参数:插件的名称,以及一个构造器函数(用于创建您的插件的新实例)。

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

在此例中,myplugin.js 包含一个简单的插件函数,会在加载后弹出一个警告讯息框。此函数将会在每次调用 ga('require', 'myplugin'); 时被调用。

实现

我们已经介绍了 analytics.js 插件系统的基础知识,下面将详细介绍如何创建插件脚本、配置插件实例以及定义插件方法的相关细节。

创建插件脚本

除了其他自定义逻辑之外,每个插件脚本都应至少包含一个插件构造器函数,并调用 provide 命令来注册该插件。即使 analytics.js 代码段被配置为针对 ga 全局对象使用自定义标识符,插件脚本也需要能正常工作,因此我们不能简单地调用 ga('provide', ..) 命令。相对地,我们在每个插件脚本中都加入 providePlugin 函数的副本(如下所示),并使用该函数来注册插件。

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);

配置插件实例

除了指定要加载的插件的名称之外,require 命令还允许您传递一个配置对象,以便在初始化插件实例时使用。

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

该配置对象会作为第二个参数传递到插件构造器。

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);

定义插件方法

插件可以暴露其自有的方法,这些方法将可以使用 ga 命令队列语法来调用:

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

其中 targetName 是跟踪器的名称。如果未指定 targetName,则将使用默认目标名称 't0'。pluginName 是插件的名称。methodName 是插件实例中的某个方法的名称。如果 methodName 在该插件中不存在,或该插件不存在,则会出现错误。

示例插件方法调用:

// 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);

示例插件方法定义:

// 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;
}:

示例

下例中的插件用于捕获网页网址中的自定义广告系列值并将其传递到跟踪器。此插件演示了如何定义和注册插件脚本,传递插件配置参数,以及定义和调用插件方法。

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>

    ...