Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

universal-analytics

Package Overview
Dependencies
Maintainers
1
Versions
44
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

universal-analytics - npm Package Compare versions

Comparing version 0.4.12 to 0.4.13

5

HISTORY.md
# History
## 0.4.13 / 2017-03-29
- Added `screenview` method
- Updated Readme
## 0.4.12 / 2017-03-16

@@ -4,0 +9,0 @@

765

lib/index.js

@@ -16,3 +16,3 @@

function init (tid, cid, options) {
return new Visitor(tid, cid, options);
return new Visitor(tid, cid, options);
}

@@ -22,42 +22,42 @@

if (typeof tid === 'object') {
options = tid;
tid = cid = null;
} else if (typeof cid === 'object') {
options = cid;
cid = null;
}
if (typeof tid === 'object') {
options = tid;
tid = cid = null;
} else if (typeof cid === 'object') {
options = cid;
cid = null;
}
this._queue = [];
this._queue = [];
this.options = options || {};
this.options = options || {};
if(this.options.hostname) {
config.hostname = this.options.hostname;
}
if(this.options.path) {
config.path = this.options.path;
}
if(this.options.hostname) {
config.hostname = this.options.hostname;
}
if(this.options.path) {
config.path = this.options.path;
}
if (this.options.https) {
var parsedHostname = url.parse(config.hostname);
config.hostname = 'https://' + parsedHostname.host;
}
if (this.options.https) {
var parsedHostname = url.parse(config.hostname);
config.hostname = 'https://' + parsedHostname.host;
}
if(this.options.enableBatching !== undefined) {
config.batching = options.enableBatching;
}
if(this.options.enableBatching !== undefined) {
config.batching = options.enableBatching;
}
if(this.options.batchSize) {
config.batchSize = this.options.batchSize;
}
if(this.options.batchSize) {
config.batchSize = this.options.batchSize;
}
this._context = context || {};
this._persistentParams = persistentParams || {};
this._context = context || {};
this._persistentParams = persistentParams || {};
this.tid = tid || this.options.tid;
this.cid = this._determineCid(cid, this.options.cid, (this.options.strictCidFormat !== false));
if(this.options.uid) {
this.uid = this.options.uid;
}
this.tid = tid || this.options.tid;
this.cid = this._determineCid(cid, this.options.cid, (this.options.strictCidFormat !== false));
if(this.options.uid) {
this.uid = this.options.uid;
}
}

@@ -70,27 +70,27 @@

this.tid = tid;
this.options = options;
this.tid = tid;
this.options = options;
var cookieName = (this.options || {}).cookieName || "_ga";
var cookieName = (this.options || {}).cookieName || "_ga";
return function (req, res, next) {
return function (req, res, next) {
req.visitor = module.exports.createFromSession(req.session);
req.visitor = module.exports.createFromSession(req.session);
if (req.visitor) return next();
if (req.visitor) return next();
var cid;
if (req.cookies && req.cookies[cookieName]) {
var gaSplit = req.cookies[cookieName].split('.');
cid = gaSplit[2] + "." + gaSplit[3];
}
var cid;
if (req.cookies && req.cookies[cookieName]) {
var gaSplit = req.cookies[cookieName].split('.');
cid = gaSplit[2] + "." + gaSplit[3];
}
req.visitor = init(tid, cid, options);
req.visitor = init(tid, cid, options);
if (req.session) {
req.session.cid = req.visitor.cid;
}
if (req.session) {
req.session.cid = req.visitor.cid;
}
next();
}
next();
}
}

@@ -101,5 +101,5 @@

module.exports.createFromSession = function (session) {
if (session && session.cid) {
return init(this.tid, session.cid, this.options);
}
if (session && session.cid) {
return init(this.tid, session.cid, this.options);
}
}

@@ -111,375 +111,420 @@

debug: function (debug) {
this.options.debug = arguments.length === 0 ? true : debug;
this._log("Logging enabled")
return this;
},
debug: function (debug) {
this.options.debug = arguments.length === 0 ? true : debug;
this._log("Logging enabled")
return this;
},
reset: function () {
this._context = null;
return this;
},
reset: function () {
this._context = null;
return this;
},
set: function (key, value) {
this._persistentParams = this._persistentParams || {};
this._persistentParams[key] = value;
},
set: function (key, value) {
this._persistentParams = this._persistentParams || {};
this._persistentParams[key] = value;
},
pageview: function (path, hostname, title, params, fn) {
pageview: function (path, hostname, title, params, fn) {
if (typeof path === 'object' && path != null) {
params = path;
if (typeof hostname === 'function') {
fn = hostname
}
path = hostname = title = null;
} else if (typeof hostname === 'function') {
fn = hostname
hostname = title = null;
} else if (typeof title === 'function') {
fn = title;
title = null;
} else if (typeof params === 'function') {
fn = params;
params = null;
}
if (typeof path === 'object' && path != null) {
params = path;
if (typeof hostname === 'function') {
fn = hostname
}
path = hostname = title = null;
} else if (typeof hostname === 'function') {
fn = hostname
hostname = title = null;
} else if (typeof title === 'function') {
fn = title;
title = null;
} else if (typeof params === 'function') {
fn = params;
params = null;
}
params = this._translateParams(params);
params = this._translateParams(params);
params = _.extend({}, this._persistentParams || {}, params);
params = _.extend({}, this._persistentParams || {}, params);
params.dp = path || params.dp || this._context.dp;
params.dh = hostname || params.dh || this._context.dh;
params.dt = title || params.dt || this._context.dt;
params.dp = path || params.dp || this._context.dp;
params.dh = hostname || params.dh || this._context.dh;
params.dt = title || params.dt || this._context.dt;
this._tidyParameters(params);
this._tidyParameters(params);
if (!params.dp && !params.dl) {
return this._handleError("Please provide either a page path (dp) or a document location (dl)", fn);
}
if (!params.dp && !params.dl) {
return this._handleError("Please provide either a page path (dp) or a document location (dl)", fn);
}
return this._withContext(params)._enqueue("pageview", params, fn);
},
return this._withContext(params)._enqueue("pageview", params, fn);
},
event: function (category, action, label, value, params, fn) {
screenview: function (screenName, appName, appVersion, appId, appInstallerId, params, fn) {
if (typeof category === 'object' && category != null) {
params = category;
if (typeof action === 'function') {
fn = action
}
category = action = label = value = null;
} else if (typeof label === 'function') {
fn = label;
label = value = null;
} else if (typeof value === 'function') {
fn = value;
value = null;
} else if (typeof params === 'function') {
fn = params;
params = null;
}
if (typeof screenName === 'object' && screenName != null) {
params = screenName;
if (typeof appName === 'function') {
fn = appName
}
screenName = appName = appVersion = appId = appInstallerId = null;
} else if (typeof appName === 'function') {
fn = appName
appName = appVersion = appId = appInstallerId = null;
} else if (typeof appVersion === 'function') {
fn = appVersion;
appVersion = appId = appInstallerId = null;
} else if (typeof appId === 'function') {
fn = appId;
appId = appInstallerId = null;
} else if (typeof appInstallerId === 'function') {
fn = appInstallerId;
appInstallerId = null;
} else if (typeof params === 'function') {
fn = params;
params = null;
}
params = this._translateParams(params);
params = this._translateParams(params);
params = _.extend({}, this._persistentParams || {}, params);
params = _.extend({}, this._persistentParams || {}, params);
params.ec = category || params.ec || this._context.ec;
params.ea = action || params.ea || this._context.ea;
params.el = label || params.el || this._context.el;
params.ev = value || params.ev || this._context.ev;
params.p = params.p || params.dp || this._context.p || this._context.dp;
params.cd = screenName || params.cd || this._context.cd;
params.an = appName || params.an || this._context.an;
params.av = appVersion || params.av || this._context.av;
params.aid = appId || params.aid || this._context.aid;
params.aiid = appInstallerId || params.aiid || this._context.aiid;
delete params.dp;
this._tidyParameters(params);
this._tidyParameters(params);
if (!params.ec || !params.ea) {
return this._handleError("Please provide at least an event category (ec) and an event action (ea)", fn);
}
if (!params.cd || !params.an) {
return this._handleError("Please provide at least a screen name (cd) and an app name (an)", fn);
}
return this._withContext(params)._enqueue("event", params, fn);
},
return this._withContext(params)._enqueue("screenview", params, fn);
},
transaction: function (transaction, revenue, shipping, tax, affiliation, params, fn) {
if (typeof transaction === 'object') {
params = transaction;
if (typeof revenue === 'function') {
fn = revenue
}
transaction = revenue = shipping = tax = affiliation = null;
} else if (typeof revenue === 'function') {
fn = revenue;
revenue = shipping = tax = affiliation = null;
} else if (typeof shipping === 'function') {
fn = shipping;
shipping = tax = affiliation = null;
} else if (typeof tax === 'function') {
fn = tax;
tax = affiliation = null;
} else if (typeof affiliation === 'function') {
fn = affiliation;
affiliation = null;
} else if (typeof params === 'function') {
fn = params;
params = null;
}
event: function (category, action, label, value, params, fn) {
params = this._translateParams(params);
if (typeof category === 'object' && category != null) {
params = category;
if (typeof action === 'function') {
fn = action
}
category = action = label = value = null;
} else if (typeof label === 'function') {
fn = label;
label = value = null;
} else if (typeof value === 'function') {
fn = value;
value = null;
} else if (typeof params === 'function') {
fn = params;
params = null;
}
params = _.extend({}, this._persistentParams || {}, params);
params = this._translateParams(params);
params.ti = transaction || params.ti || this._context.ti;
params.tr = revenue || params.tr || this._context.tr;
params.ts = shipping || params.ts || this._context.ts;
params.tt = tax || params.tt || this._context.tt;
params.ta = affiliation || params.ta || this._context.ta;
params.p = params.p || this._context.p || this._context.dp;
params = _.extend({}, this._persistentParams || {}, params);
this._tidyParameters(params);
params.ec = category || params.ec || this._context.ec;
params.ea = action || params.ea || this._context.ea;
params.el = label || params.el || this._context.el;
params.ev = value || params.ev || this._context.ev;
params.p = params.p || params.dp || this._context.p || this._context.dp;
if (!params.ti) {
return this._handleError("Please provide at least a transaction ID (ti)", fn);
}
delete params.dp;
this._tidyParameters(params);
return this._withContext(params)._enqueue("transaction", params, fn);
},
if (!params.ec || !params.ea) {
return this._handleError("Please provide at least an event category (ec) and an event action (ea)", fn);
}
return this._withContext(params)._enqueue("event", params, fn);
},
item: function (price, quantity, sku, name, variation, params, fn) {
if (typeof price === 'object') {
params = price;
if (typeof quantity === 'function') {
fn = quantity
}
price = quantity = sku = name = variation = null;
} else if (typeof quantity === 'function') {
fn = quantity;
quantity = sku = name = variation = null;
} else if (typeof sku === 'function') {
fn = sku;
sku = name = variation = null;
} else if (typeof name === 'function') {
fn = name;
name = variation = null;
} else if (typeof variation === 'function') {
fn = variation;
variation = null;
} else if (typeof params === 'function') {
fn = params;
params = null;
}
params = this._translateParams(params);
transaction: function (transaction, revenue, shipping, tax, affiliation, params, fn) {
if (typeof transaction === 'object') {
params = transaction;
if (typeof revenue === 'function') {
fn = revenue
}
transaction = revenue = shipping = tax = affiliation = null;
} else if (typeof revenue === 'function') {
fn = revenue;
revenue = shipping = tax = affiliation = null;
} else if (typeof shipping === 'function') {
fn = shipping;
shipping = tax = affiliation = null;
} else if (typeof tax === 'function') {
fn = tax;
tax = affiliation = null;
} else if (typeof affiliation === 'function') {
fn = affiliation;
affiliation = null;
} else if (typeof params === 'function') {
fn = params;
params = null;
}
params = _.extend({}, this._persistentParams || {}, params);
params = this._translateParams(params);
params.ip = price || params.ip || this._context.ip;
params.iq = quantity || params.iq || this._context.iq;
params.ic = sku || params.ic || this._context.ic;
params.in = name || params.in || this._context.in;
params.iv = variation || params.iv || this._context.iv;
params.p = params.p || this._context.p || this._context.dp;
params.ti = params.ti || this._context.ti;
params = _.extend({}, this._persistentParams || {}, params);
this._tidyParameters(params);
params.ti = transaction || params.ti || this._context.ti;
params.tr = revenue || params.tr || this._context.tr;
params.ts = shipping || params.ts || this._context.ts;
params.tt = tax || params.tt || this._context.tt;
params.ta = affiliation || params.ta || this._context.ta;
params.p = params.p || this._context.p || this._context.dp;
if (!params.ti) {
return this._handleError("Please provide at least an item transaction ID (ti)", fn);
}
this._tidyParameters(params);
return this._withContext(params)._enqueue("item", params, fn);
if (!params.ti) {
return this._handleError("Please provide at least a transaction ID (ti)", fn);
}
},
return this._withContext(params)._enqueue("transaction", params, fn);
},
exception: function (description, fatal, params, fn) {
if (typeof description === 'object') {
params = description;
if (typeof fatal === 'function') {
fn = fatal;
}
description = fatal = null;
} else if (typeof fatal === 'function') {
fn = fatal;
fatal = 0;
} else if (typeof params === 'function') {
fn = params;
params = null;
}
item: function (price, quantity, sku, name, variation, params, fn) {
if (typeof price === 'object') {
params = price;
if (typeof quantity === 'function') {
fn = quantity
}
price = quantity = sku = name = variation = null;
} else if (typeof quantity === 'function') {
fn = quantity;
quantity = sku = name = variation = null;
} else if (typeof sku === 'function') {
fn = sku;
sku = name = variation = null;
} else if (typeof name === 'function') {
fn = name;
name = variation = null;
} else if (typeof variation === 'function') {
fn = variation;
variation = null;
} else if (typeof params === 'function') {
fn = params;
params = null;
}
params = this._translateParams(params);
params = this._translateParams(params);
params = _.extend({}, this._persistentParams || {}, params);
params = _.extend({}, this._persistentParams || {}, params);
params.exd = description || params.exd || this._context.exd;
params.exf = +!!(fatal || params.exf || this._context.exf);
params.ip = price || params.ip || this._context.ip;
params.iq = quantity || params.iq || this._context.iq;
params.ic = sku || params.ic || this._context.ic;
params.in = name || params.in || this._context.in;
params.iv = variation || params.iv || this._context.iv;
params.p = params.p || this._context.p || this._context.dp;
params.ti = params.ti || this._context.ti;
if (params.exf === 0) {
delete params.exf;
}
this._tidyParameters(params);
this._tidyParameters(params);
if (!params.ti) {
return this._handleError("Please provide at least an item transaction ID (ti)", fn);
}
return this._withContext(params)._enqueue("exception", params, fn);
},
return this._withContext(params)._enqueue("item", params, fn);
timing: function (category, variable, time, label, params, fn) {
},
if (typeof category === 'object') {
params = category;
if (typeof variable === 'function') {
fn = variable;
}
category = variable = time = label = null;
} else if (typeof variable === 'function') {
fn = variable;
variable = time = label = null;
} else if (typeof time === 'function') {
fn = time;
time = label = null;
} else if (typeof label === 'function') {
fn = label;
label = null;
} else if (typeof params === 'function') {
fn = params;
params = null;
}
exception: function (description, fatal, params, fn) {
params = this._translateParams(params);
if (typeof description === 'object') {
params = description;
if (typeof fatal === 'function') {
fn = fatal;
}
description = fatal = null;
} else if (typeof fatal === 'function') {
fn = fatal;
fatal = 0;
} else if (typeof params === 'function') {
fn = params;
params = null;
}
params = _.extend({}, this._persistentParams || {}, params);
params = this._translateParams(params);
params.utc = category || params.utc || this._context.utc;
params.utv = variable || params.utv || this._context.utv;
params.utt = time || params.utt || this._context.utt;
params.utl = label || params.utl || this._context.utl;
params = _.extend({}, this._persistentParams || {}, params);
this._tidyParameters(params);
params.exd = description || params.exd || this._context.exd;
params.exf = +!!(fatal || params.exf || this._context.exf);
return this._withContext(params)._enqueue("timing", params, fn);
},
if (params.exf === 0) {
delete params.exf;
}
this._tidyParameters(params);
send: function (fn) {
var self = this;
var count = 1;
var fn = fn || function () {};
self._log("Sending " + self._queue.length + " tracking call(s)");
return this._withContext(params)._enqueue("exception", params, fn);
},
var test = function () {
return self._queue.length > 0;
}
timing: function (category, variable, time, label, params, fn) {
var getBody = function(params) {
return params.map(function(x) { return querystring.stringify(x); }).join("\n");
}
if (typeof category === 'object') {
params = category;
if (typeof variable === 'function') {
fn = variable;
}
category = variable = time = label = null;
} else if (typeof variable === 'function') {
fn = variable;
variable = time = label = null;
} else if (typeof time === 'function') {
fn = time;
time = label = null;
} else if (typeof label === 'function') {
fn = label;
label = null;
} else if (typeof params === 'function') {
fn = params;
params = null;
}
var iterator = function (fn) {
var params = [];
params = this._translateParams(params);
if(config.batching) {
params = self._queue.splice(0, Math.min(self._queue.length, config.batchSize));
} else {
params.push(self._queue.shift());
}
params = _.extend({}, this._persistentParams || {}, params);
var useBatchPath = params.length > 1;
params.utc = category || params.utc || this._context.utc;
params.utv = variable || params.utv || this._context.utv;
params.utt = time || params.utt || this._context.utt;
params.utl = label || params.utl || this._context.utl;
var path = config.hostname + (useBatchPath ? config.batchPath :config.path);
this._tidyParameters(params);
self._log(count++ + ": " + JSON.stringify(params));
return this._withContext(params)._enqueue("timing", params, fn);
},
var options = _.extend({}, self.options.requestOptions, {
body: getBody(params),
headers: self.options.headers || {}
});
request.post(path, options, fn);
}
send: function (fn) {
var self = this;
var count = 1;
var fn = fn || function () {};
self._log("Sending " + self._queue.length + " tracking call(s)");
async.whilst(test, iterator, function (err) {
self._log("Finished sending tracking calls")
fn.call(self, err || null, count - 1);
});
var test = function () {
return self._queue.length > 0;
}
},
var getBody = function(params) {
return params.map(function(x) { return querystring.stringify(x); }).join("\n");
}
_enqueue: function (type, params, fn) {
var iterator = function (fn) {
var params = [];
if (typeof params === 'function') {
fn = params;
params = {};
}
if(config.batching) {
params = self._queue.splice(0, Math.min(self._queue.length, config.batchSize));
} else {
params.push(self._queue.shift());
}
params = this._translateParams(params) || {};
var useBatchPath = params.length > 1;
_.extend(params, {
v: config.protocolVersion,
tid: this.tid,
cid: this.cid,
t: type
});
if(this.uid) {
params.uid = this.uid;
}
var path = config.hostname + (useBatchPath ? config.batchPath :config.path);
this._queue.push(params);
self._log(count++ + ": " + JSON.stringify(params));
if (this.options.debug) {
this._checkParameters(params);
}
var options = _.extend({}, self.options.requestOptions, {
body: getBody(params),
headers: self.options.headers || {}
});
this._log("Enqueued " + type + " (" + JSON.stringify(params) + ")");
request.post(path, options, fn);
}
if (fn) {
this.send(fn);
}
async.whilst(test, iterator, function (err) {
self._log("Finished sending tracking calls")
fn.call(self, err || null, count - 1);
});
return this;
},
},
_enqueue: function (type, params, fn) {
_handleError: function (message, fn) {
this._log("Error: " + message)
fn && fn.call(this, new Error(message))
return this;
},
if (typeof params === 'function') {
fn = params;
params = {};
}
params = this._translateParams(params) || {};
_.extend(params, {
v: config.protocolVersion,
tid: this.tid,
cid: this.cid,
t: type
});
if(this.uid) {
params.uid = this.uid;
}
_determineCid: function () {
var args = Array.prototype.splice.call(arguments, 0);
var id;
var lastItem = args.length-1;
var strict = args[lastItem];
if (strict) {
for (var i = 0; i < lastItem; i++) {
id = utils.ensureValidCid(args[i]);
if (id !== false) return id;
if (id != null) this._log("Warning! Invalid UUID format '" + args[i] + "'");
}
} else {
for (var i = 0; i < lastItem; i++) {
if (args[i]) return args[i];
}
}
return uuid.v4();
},
this._queue.push(params);
if (this.options.debug) {
this._checkParameters(params);
}
_checkParameters: function (params) {
for (var param in params) {
if (config.acceptedParameters.indexOf(param) !== -1 || config.acceptedParametersRegex.filter(function (r) {
return r.test(param);
}).length) {
continue;
}
this._log("Warning! Unsupported tracking parameter " + param + " (" + params[param] + ")");
}
},
this._log("Enqueued " + type + " (" + JSON.stringify(params) + ")");
_translateParams: function (params) {
if (fn) {
this.send(fn);
}
return this;
},
_handleError: function (message, fn) {
this._log("Error: " + message)
fn && fn.call(this, new Error(message))
return this;
},
_determineCid: function () {
var args = Array.prototype.splice.call(arguments, 0);
var id;
var lastItem = args.length-1;
var strict = args[lastItem];
if (strict) {
for (var i = 0; i < lastItem; i++) {
id = utils.ensureValidCid(args[i]);
if (id !== false) return id;
if (id != null) this._log("Warning! Invalid UUID format '" + args[i] + "'");
}
} else {
for (var i = 0; i < lastItem; i++) {
if (args[i]) return args[i];
}
}
return uuid.v4();
},
_checkParameters: function (params) {
for (var param in params) {
if (config.acceptedParameters.indexOf(param) !== -1 || config.acceptedParametersRegex.filter(function (r) {
return r.test(param);
}).length) {
continue;
}
this._log("Warning! Unsupported tracking parameter " + param + " (" + params[param] + ")");
}
},
_translateParams: function (params) {
var translated = {};

@@ -496,22 +541,22 @@ for (var key in params) {

_tidyParameters: function (params) {
for (var param in params) {
if (params[param] === null || params[param] === undefined) {
delete params[param];
}
}
return params;
},
_tidyParameters: function (params) {
for (var param in params) {
if (params[param] === null || params[param] === undefined) {
delete params[param];
}
}
return params;
},
_log: function (message) {
this.options.debug && console.log("[universal-analytics] " + message);
},
_log: function (message) {
this.options.debug && console.log("[universal-analytics] " + message);
},
_withContext: function (context) {
var visitor = new Visitor(this.tid, this.cid, this.options, context, this._persistentParams);
visitor._queue = this._queue;
return visitor;
}
_withContext: function (context) {
var visitor = new Visitor(this.tid, this.cid, this.options, context, this._persistentParams);
visitor._queue = this._queue;
return visitor;
}

@@ -518,0 +563,0 @@

{
"name": "universal-analytics",
"version": "0.4.12",
"version": "0.4.13",
"description": "A node module for Google's Universal Analytics tracking",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -8,14 +8,27 @@ universal-analytics

`universal-analytics` currently supports the following tracking features:
[![Build Status](https://travis-ci.org/peaksandpies/universal-analytics.png?branch=master)](https://travis-ci.org/peaksandpies/universal-analytics)
* Pageviews
* Events
* E-Commerce with transactions and items
* Exceptions
* User timings
[![Build Status](https://travis-ci.org/peaksandpies/universal-analytics.png?branch=master)](https://travis-ci.org/peaksandpies/universal-analytics)
# Table of Contents
## Getting started
- [Getting started](#getting-started)
- [Tracking](#tracking)
- [Pageviews](#pageview-tracking)
- [Screenviews](#screenview-tracking)
- [Events](#event-tracking)
- [Exceptions](#exception-tracking)
- [User timings](#user-timing-tracking)
- [Transactions](#transaction-tracking)
- [Transaction items](#transaction-item-tracking)
- [Daisy-chaining tracking calls](#daisy-chaining-tracking-calls)
- [Setting persistent parameters](#setting-persistent-parameters)
- [Session-based identification](#session-based-identification)
- [Debug mode](#debug-mode)
- [Request Options](#request-options)
- [Shortcuts](#shortcuts)
- [Tests](#tests)
# Getting started
`universal-analytics` is installed and included like any other node module:

@@ -77,2 +90,6 @@

# Tracking
## Pageview tracking

@@ -123,4 +140,38 @@

See also [a acceptable params](AcceptableParams.md).
See also: [List of acceptable params](AcceptableParams.md).
## Screenview tracking
Instead of pageviews app will want to track screenviews.
```javascript
visitor.screenview("Home Screen", "App Name").send()
```
The following method signatures are available for #screenview:
* `Visitor#screenview(screenName, appName)`
* `Visitor#screenview(screenName, appName, callback)`
* `Visitor#screenview(screenName, appName, appVersion)`
* `Visitor#screenview(screenName, appName, appVersion, callback)`
* `Visitor#screenview(screenName, appName, appVersion, appId)`
* `Visitor#screenview(screenName, appName, appVersion, appId, callback)`
* `Visitor#screenview(screenName, appName, appVersion, appId, appInstallerId)`
* `Visitor#screenview(screenName, appName, appVersion, appId, appInstallerId, callback)`
* `Visitor#screenview(screenName, appName, appVersion, appId, appInstallerId, params)`
* `Visitor#screenview(screenName, appName, appVersion, appId, appInstallerId, params, callback)`
* `Visitor#screenview(params)`
* `Visitor#screenview(params, callback)`
See also: [List of acceptable params](AcceptableParams.md).
## Event tracking

@@ -195,67 +246,10 @@

See also [a acceptable params](AcceptableParams.md).
See also: [List of acceptable params](AcceptableParams.md).
### Daisy-chaining tracking calls
We have seen basic daisy-chaining above when calling `send()` right after `pageview()` and `event()`:
```javascript
visitor.pageview("/").send()
```
Every call of a tracking method returns a visitor instance you can re-use:
```javascript
visitor.pageview("/").pageview("/contact").send()
```
## E-commerce tracking
Granted, the chance of this example actually happening in practice might be rather low.
However, `universal-analytics` is smart when it comes to daisy-chaining certain calls. In many cases, a `pageview()` call is instantly followed by an `event()` call to track some additional information about the current page. `universal-analytics` makes creating the connection between the two easy:
```javascript
visitor.pageview("/landing-page-1").event("Testing", "Button color", "Blue").send()
```
This is the same as two distinct tracking calls.
```javascript
visitor.pageview("/landing-page-1").send()
visitor.event("Testing", "Button color", "Blue", {p: "/landing-page-1"}).send()
```
Daisy-chaining is context-aware and in this case placing the `event()` call right after the `pageview()` call results in the event being associated with the page path tracking in the `pageview()` call. Even though the attributes (`dp` and `p`) are different internally.
It also works when using a callback since the `this` inside the callback will be the `universal-analytics` Visitor instance:
```javascript
visitor.pageview("/landing-page-1", function (err) {
if (!err) {
this.event("Testing", "Button color", "Blue").send()
}
});
```
More generally, the daisy-chaining context keeps all parameters from the previous call around. This means in a situation where similar tracking calls are necessary tracking is simplified:
```javascript
visitor
.event({ec: "Mail Server", ea: "New Team Member Notification sent"})
.event({ea: "Invitation sent"})
.send();
```
In this example the event category ("Mail Server") is not repeated in the second tracking call.
### Setting persistent parameters
Some parameters should be in every tracking call, such as a user ID or custom dimensions that never or hardly change. For such situations a `#set(key, value)` method is available
visitor.set("uid", "123456789")
The uid parameter will be part of every tracking request of that visitor from now on.
### E-commerce tracking
E-commerce tracking in general is a bit more complex. It requires a combination of one call to the `transaction()` method and one or more calls to the `item()` method.

@@ -329,6 +323,11 @@

See also [a acceptable params](AcceptableParams.md).
See also: [List of acceptable params](AcceptableParams.md).
### Exception tracking
## Exception tracking
Exception tracking is a way to keep track of any sort of application errors and bugs with Google Analytics. Using it with this module is a way to capture server-side problems.

@@ -358,6 +357,11 @@

See also [a acceptable params](AcceptableParams.md).
See also: [List of acceptable params](AcceptableParams.md).
### User timing tracking
## User timing tracking
Tracking user timings is a way to capture time-based information similar to the page load speed data tracked automatically by Google Analytics. All arguments to this tracking method are optional, but a category, a variable and a time value should be provided. The time value should be provided in milliseconds.

@@ -382,6 +386,144 @@

See also [a acceptable params](AcceptableParams.md).
See also: [List of acceptable params](AcceptableParams.md).
## Session-based identification
## Transaction tracking
Transactions are the main tracking calls for ecommerce tracking
```javascript
visitor.transaction("123456", "449.99").send()
```
The following method signatures are available for #transaction:
* `Visitor#transaction(transactionId)`
* `Visitor#transaction(transactionId, callback)`
* `Visitor#transaction(transactionId, revenue)`
* `Visitor#transaction(transactionId, revenue, callback)`
* `Visitor#transaction(transactionId, revenue, shippingCost)`
* `Visitor#transaction(transactionId, revenue, shippingCost, callback)`
* `Visitor#transaction(transactionId, revenue, shippingCost, tax)`
* `Visitor#transaction(transactionId, revenue, shippingCost, tax, callback)`
* `Visitor#transaction(transactionId, revenue, shippingCost, tax, affiliation)`
* `Visitor#transaction(transactionId, revenue, shippingCost, tax, affiliation, callback)`
* `Visitor#transaction(transactionId, revenue, shippingCost, tax, affiliation, params)`
* `Visitor#transaction(transactionId, revenue, shippingCost, tax, affiliation, params, callback)`
* `Visitor#transaction(params)`
* `Visitor#transaction(params, callback)`
See also: [List of acceptable params](AcceptableParams.md).
### Transaction item tracking
Transaction consist of one or more items.
```javascript
visitor.item(449.99, 1, "ID54321", "T-Shirt", {ti: "123456"}).send()
```
The following method signatures are available for #transaction:
* `Visitor#transaction(price)`
* `Visitor#transaction(price, callback)`
* `Visitor#transaction(price, quantity)`
* `Visitor#transaction(price, quantity, callback)`
* `Visitor#transaction(price, quantity, sku)`
* `Visitor#transaction(price, quantity, sku, callback)`
* `Visitor#transaction(price, quantity, sku, name)`
* `Visitor#transaction(price, quantity, sku, name, callback)`
* `Visitor#transaction(price, quantity, sku, name, variation)`
* `Visitor#transaction(price, quantity, sku, name, variation, callback)`
* `Visitor#transaction(price, quantity, sku, name, variation, params)`
* `Visitor#transaction(price, quantity, sku, name, variation, params, callback)`
* `Visitor#transaction(params)`
* `Visitor#transaction(params, callback)`
See also: [List of acceptable params](AcceptableParams.md).
# Daisy-chaining tracking calls
We have seen basic daisy-chaining above when calling `send()` right after `pageview()` and `event()`:
```javascript
visitor.pageview("/").send()
```
Every call of a tracking method returns a visitor instance you can re-use:
```javascript
visitor.pageview("/").pageview("/contact").send()
```
Granted, the chance of this example actually happening in practice might be rather low.
However, `universal-analytics` is smart when it comes to daisy-chaining certain calls. In many cases, a `pageview()` call is instantly followed by an `event()` call to track some additional information about the current page. `universal-analytics` makes creating the connection between the two easy:
```javascript
visitor.pageview("/landing-page-1").event("Testing", "Button color", "Blue").send()
```
This is the same as two distinct tracking calls.
```javascript
visitor.pageview("/landing-page-1").send()
visitor.event("Testing", "Button color", "Blue", {p: "/landing-page-1"}).send()
```
Daisy-chaining is context-aware and in this case placing the `event()` call right after the `pageview()` call results in the event being associated with the page path tracking in the `pageview()` call. Even though the attributes (`dp` and `p`) are different internally.
It also works when using a callback since the `this` inside the callback will be the `universal-analytics` Visitor instance:
```javascript
visitor.pageview("/landing-page-1", function (err) {
if (!err) {
this.event("Testing", "Button color", "Blue").send()
}
});
```
More generally, the daisy-chaining context keeps all parameters from the previous call around. This means in a situation where similar tracking calls are necessary tracking is simplified:
```javascript
visitor
.event({ec: "Mail Server", ea: "New Team Member Notification sent"})
.event({ea: "Invitation sent"})
.send();
```
In this example the event category ("Mail Server") is not repeated in the second tracking call.
# Setting persistent parameters
Some parameters should be in every tracking call, such as a user ID or custom dimensions that never or hardly change. For such situations a `#set(key, value)` method is available
```javascript
visitor.set("uid", "123456789")
```
The uid parameter will be part of every tracking request of that visitor from now on.
# Session-based identification
In order to make session-based apps easier to work with, `universal-analytics` also provides a middleware that works in an Expressjs-style fashion. It will try to detect a client ID based on the `_ga` cookie used by the analytics.js client-side tracking. Additionally it will store the detected client ID in the current session to recognize the visitor later.

@@ -406,3 +548,3 @@

## Debug mode
# Debug mode

@@ -417,3 +559,3 @@ `universal-analytics` can be instructed to output information during tracking by enabling the debug mode:

## Request Options
# Request Options

@@ -431,3 +573,3 @@ In order to add additional options to the request a `requestOptions` hash can be provided as part of the constructor options. `unviversal-analytics` uses the [`request`](https://www.npmjs.com/package/request) library. Therefor [any option available for that library](https://www.npmjs.com/package/request#requestoptions-callback) can be provided via the `requestOptions`.

## Shortcuts
# Shortcuts

@@ -453,7 +595,7 @@ The tracking methods have shortcuts:

## License
# License
(The MIT License)
Copyright (c) 2016 Peaks & Pies GmbH &lt;hello@peaksandpies.com&gt;
Copyright (c) 2017 Peaks & Pies GmbH &lt;hello@peaksandpies.com&gt;

@@ -460,0 +602,0 @@ Permission is hereby granted, free of charge, to any person obtaining

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc