diff --git a/.travis.yml b/.travis.yml index 972240c..0b0d5bc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,8 @@ language: node_js node_js: - - "0.8" - - "0.10" - - "0.12" - - "io.js" + - "4" + - "6" + - "8" before_install: - npm install -g npm diff --git a/AcceptableParams.md b/AcceptableParams.md index 1329eaa..7406fb3 100644 --- a/AcceptableParams.md +++ b/AcceptableParams.md @@ -1,5 +1,6 @@ # Acceptable parameters + ## Protocol Version Pass as: `protocolVersion` or `v` @@ -288,7 +289,7 @@ Optional. Specifies the event category. Must not be empty. Pass as: `eventAction` or `ea` -Optional.Specifies the event action.Must not be empty. +Optional. Specifies the event action. Must not be empty. ## Event Label @@ -442,7 +443,7 @@ Optional. Specifies the time it took for a page to load. The value is in millise Pass as: `dnsTime` or `dns` -Optional. Specifies the time it took to do a DNS lookup.The value is in milliseconds. +Optional. Specifies the time it took to do a DNS lookup. The value is in milliseconds. ## Page Download Time diff --git a/HISTORY.md b/HISTORY.md index 37912b2..f292573 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,19 @@ # History +## 0.4.16 + +- Removed async, underscore dependencies + +## 0.4.15 / 2017-08-10 + +- Fixed dependencies + +## 0.4.14 / 2017-08-07 + +- Updated AcceptableParams.md +- Updated .travis.yml to test Node.js up to 8 +- Updated package.json to be more specific about Sinon + ## 0.4.13 / 2017-03-29 - Added `screenview` method diff --git a/README.md b/README.md index 8611b6f..bb38b35 100644 --- a/README.md +++ b/README.md @@ -46,16 +46,16 @@ Initialization expects at least your Google Analytics account ID: var visitor = ua('UA-XXXX-XX'); ``` -This will create a `universal-analytics` Visitor instance that you can use and keep around to track a specific user. Since no user UUID was specified in the constructor's arguments, a random UUID is generated. In case you have a user UUID at hand, you can use that to create the visitor: +This will create a `universal-analytics` Visitor instance that you can use and keep around to track a specific client (Not to be confused with the Google Analytics User ID, see [Setting persistent parameters](#setting-persistent-parameters) for more information on that). Since no client ID was specified in the constructor's arguments, a random UUID is generated. In case you have a client ID at hand, you can use that to create the visitor: ```javascript var visitor = ua('UA-XXXX-XX', '6a14abda-6b12-4578-bf66-43c754eaeda9'); ``` -Starting with Universal Analytics, a UUID v4 is the preferred user ID format. It is therefor necessary to provide a UUID of such type to `universal-analytics`. However you can force custom user ID, passing `strictCidFormat: false` in the options: +Starting with Universal Analytics, a UUID v4 is the preferred client ID format. It is therefor necessary to provide a UUID of such type to `universal-analytics`. However you can force custom client ID, passing `strictCidFormat: false` in the options: ```javascript -var visitor = ua('UA-XXXX-XX', 'CUSTOM_USERID_1', {strictCidFormat: false}); +var visitor = ua('UA-XXXX-XX', 'CUSTOM_CLIENTID_1', {strictCidFormat: false}); ``` If you want to use Google Analytics in https protocol, just include it in the options `https: true`, by default will use http: @@ -540,11 +540,10 @@ var visitor = ua.createFromSession(socket.handshake.session); # Debug mode -`universal-analytics` can be instructed to output information during tracking by enabling the debug mode: +`universal-analytics` is using the [`debug`](https://www.npmjs.com/package/debug) library. It can be instructed to output information during tracking by setting the `DEBUG` environment variable: -```javascript -var visitor = ua("UA-XXXX-XX").debug() -// … and so forth. +``` +DEBUG=universal-analytics ``` diff --git a/lib/index.js b/lib/index.js index 91008de..04d3163 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,6 +1,4 @@ -var async = require("async"); -var _ = require("underscore"); var request = require("request"); var uuid = require("uuid"); var querystring = require("querystring"); @@ -9,6 +7,8 @@ var utils = require("./utils"); var config = require("./config"); var url = require("url"); +var debug = require("debug")("universal-analytics"); + module.exports = init; @@ -104,9 +104,9 @@ module.exports.createFromSession = function (session) { Visitor.prototype = { - debug: function (debug) { - this.options.debug = arguments.length === 0 ? true : debug; - this._log("Logging enabled") + debug: function (d) { + debug.enabled = arguments.length === 0 ? true : d; + debug("visitor.debug() is deprecated: set DEBUG=universal-analytics to enable logging") return this; }, @@ -142,7 +142,7 @@ Visitor.prototype = { params = this._translateParams(params); - params = _.extend({}, this._persistentParams || {}, params); + params = Object.assign({}, this._persistentParams || {}, params); params.dp = path || params.dp || this._context.dp; params.dh = hostname || params.dh || this._context.dh; @@ -185,7 +185,7 @@ Visitor.prototype = { params = this._translateParams(params); - params = _.extend({}, this._persistentParams || {}, params); + params = Object.assign({}, this._persistentParams || {}, params); params.cd = screenName || params.cd || this._context.cd; params.an = appName || params.an || this._context.an; @@ -224,7 +224,7 @@ Visitor.prototype = { params = this._translateParams(params); - params = _.extend({}, this._persistentParams || {}, params); + params = Object.assign({}, this._persistentParams || {}, params); params.ec = category || params.ec || this._context.ec; params.ea = action || params.ea || this._context.ea; @@ -269,7 +269,7 @@ Visitor.prototype = { params = this._translateParams(params); - params = _.extend({}, this._persistentParams || {}, params); + params = Object.assign({}, this._persistentParams || {}, params); params.ti = transaction || params.ti || this._context.ti; params.tr = revenue || params.tr || this._context.tr; @@ -314,7 +314,7 @@ Visitor.prototype = { params = this._translateParams(params); - params = _.extend({}, this._persistentParams || {}, params); + params = Object.assign({}, this._persistentParams || {}, params); params.ip = price || params.ip || this._context.ip; params.iq = quantity || params.iq || this._context.iq; @@ -352,7 +352,7 @@ Visitor.prototype = { params = this._translateParams(params); - params = _.extend({}, this._persistentParams || {}, params); + params = Object.assign({}, this._persistentParams || {}, params); params.exd = description || params.exd || this._context.exd; params.exf = +!!(fatal || params.exf || this._context.exf); @@ -390,7 +390,7 @@ Visitor.prototype = { params = this._translateParams(params); - params = _.extend({}, this._persistentParams || {}, params); + params = Object.assign({}, this._persistentParams || {}, params); params.utc = category || params.utc || this._context.utc; params.utv = variable || params.utv || this._context.utv; @@ -407,17 +407,21 @@ Visitor.prototype = { var self = this; var count = 1; var fn = fn || function () {}; - self._log("Sending " + self._queue.length + " tracking call(s)"); - - var test = function () { - return self._queue.length > 0; - } + debug("Sending %d tracking call(s)", self._queue.length); var getBody = function(params) { return params.map(function(x) { return querystring.stringify(x); }).join("\n"); } - var iterator = function (fn) { + var onFinish = function (err) { + debug("Finished sending tracking calls") + fn.call(self, err || null, count - 1); + } + + var iterator = function () { + if (!self._queue.length) { + return onFinish(null); + } var params = []; if(config.batching) { @@ -430,20 +434,22 @@ Visitor.prototype = { var path = config.hostname + (useBatchPath ? config.batchPath :config.path); - self._log(count++ + ": " + JSON.stringify(params)); + debug("%d: %o", count++, params); - var options = _.extend({}, self.options.requestOptions, { + var options = Object.assign({}, self.options.requestOptions, { body: getBody(params), headers: self.options.headers || {} }); - request.post(path, options, fn); + request.post(path, options, nextIteration); } - async.whilst(test, iterator, function (err) { - self._log("Finished sending tracking calls") - fn.call(self, err || null, count - 1); - }); + function nextIteration(err) { + if (err) return onFinish(err); + iterator(); + } + + iterator(); }, @@ -456,7 +462,7 @@ Visitor.prototype = { params = this._translateParams(params) || {}; - _.extend(params, { + Object.assign(params, { v: config.protocolVersion, tid: this.tid, cid: this.cid, @@ -468,11 +474,11 @@ Visitor.prototype = { this._queue.push(params); - if (this.options.debug) { + if (debug.enabled) { this._checkParameters(params); } - this._log("Enqueued " + type + " (" + JSON.stringify(params) + ")"); + debug("Enqueued %s (%o)", type, params); if (fn) { this.send(fn); @@ -483,7 +489,7 @@ Visitor.prototype = { _handleError: function (message, fn) { - this._log("Error: " + message) + debug("Error: %s", message) fn && fn.call(this, new Error(message)) return this; }, @@ -499,7 +505,7 @@ Visitor.prototype = { 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] + "'"); + if (id != null) debug("Warning! Invalid UUID format '%s'", args[i]); } } else { for (var i = 0; i < lastItem; i++) { @@ -517,7 +523,7 @@ Visitor.prototype = { }).length) { continue; } - this._log("Warning! Unsupported tracking parameter " + param + " (" + params[param] + ")"); + debug("Warning! Unsupported tracking parameter %s (%s)", param, params[param]); } }, @@ -542,12 +548,6 @@ Visitor.prototype = { return params; }, - - _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; diff --git a/package.json b/package.json index 8b814a6..97c8862 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "universal-analytics", - "version": "0.4.13", + "version": "0.4.16", "description": "A node module for Google's Universal Analytics tracking", "main": "index.js", "scripts": { @@ -17,14 +17,13 @@ "tracking" ], "dependencies": { - "async": "1.2.x", + "debug": "^3.0.0", "request": "2.x", - "underscore": "1.x", "uuid": "^3.0.0" }, "devDependencies": { "should": "*", - "sinon": "*", + "sinon": "^1.17.7", "mocha": "*" }, "author": "Jörg Tillmann ", diff --git a/test/_enqueue.js b/test/_enqueue.js index a9a4feb..610feec 100644 --- a/test/_enqueue.js +++ b/test/_enqueue.js @@ -1,5 +1,4 @@ -var _ = require("underscore"); var request = require("request"); var qs = require("querystring"); var uuid = require("uuid"); diff --git a/test/event.js b/test/event.js index 63df9a0..e04f5be 100644 --- a/test/event.js +++ b/test/event.js @@ -1,5 +1,4 @@ -var _ = require("underscore"); var request = require("request"); var qs = require("querystring"); var uuid = require("uuid"); diff --git a/test/exception.js b/test/exception.js index b099c34..8a04fbd 100644 --- a/test/exception.js +++ b/test/exception.js @@ -1,5 +1,4 @@ -var _ = require("underscore"); var request = require("request"); var qs = require("querystring"); var uuid = require("uuid"); diff --git a/test/index.js b/test/index.js index 9b882a8..5bc78cb 100644 --- a/test/index.js +++ b/test/index.js @@ -1,5 +1,4 @@ -var _ = require("underscore"); var request = require("request"); var qs = require("querystring"); var uuid = require("uuid"); @@ -85,11 +84,11 @@ describe("ua", function () { tid: "UA-XXXXX-XX", cid: "custom-format-cid" }; - + var next = sinon.spy(uuid, 'v4') var visitor = ua(options); - + next.calledOnce.should.equal(true, "next() should've been called once") var generatedCid = next.returnValues[0] uuid.v4.restore() @@ -104,11 +103,11 @@ describe("ua", function () { cid: "custom-format-cid", strictCidFormat: false }; - + var next = sinon.spy(uuid, 'v4') var visitor = ua(options); - + next.called.should.equal(false, "next() should't be called") uuid.v4.restore() @@ -117,15 +116,15 @@ describe("ua", function () { describe("params", function () { - + var visitor; - + before(function () { var tid = "UA-XXXXX-XX"; var cid = uuid.v4(); visitor = ua(tid, cid); }); - + it('should not translate params', function(){ var params = { tid: 1, @@ -133,64 +132,20 @@ describe("ua", function () { somefake: 1, v: 'a' }; - - visitor._translateParams(params).should.eql(params); + + visitor._translateParams(params).should.eql(params); }) - - it('should match all parameters and each should be in the list of accepted', function(){ + + it('should match all parameters and each should be in the list of accepted', function(){ var res = visitor._translateParams(config.parametersMap); for (var i in res) { if (res.hasOwnProperty(i)) { res[i].should.equal(i); config.acceptedParameters.should.containEql(i); } - } + } }) - }); - - describe("#debug", function () { - - var log; - - before(function () { - log = sinon.stub(ua.Visitor.prototype, "_log") - }); - - after(function () { - log.restore(); - }); - - it("should enable debugging when invoked without arguments", function () { - var visitor = ua().debug() - - visitor.options.debug.should.equal(true); - - visitor.debug().should.equal(visitor, "should return itself") - - visitor.options.debug.should.equal(true, "A second #debug call should leave debugging enabled"); - }); - - it("should toggle debugging when invoked with a boolean arguments", function () { - var visitor = ua().debug(true) - - visitor.options.debug.should.equal(true); - - visitor.debug(false).should.equal(visitor, "should return itself") - - visitor.options.debug.should.equal(false); - }); - }); }); - - - - - - - - - - diff --git a/test/item.js b/test/item.js index 5348b0c..f855202 100644 --- a/test/item.js +++ b/test/item.js @@ -1,5 +1,4 @@ -var _ = require("underscore"); var request = require("request"); var qs = require("querystring"); var uuid = require("uuid"); diff --git a/test/middleware.js b/test/middleware.js index 09d8ccd..b76e091 100644 --- a/test/middleware.js +++ b/test/middleware.js @@ -1,5 +1,4 @@ -var _ = require("underscore"); var request = require("request"); var qs = require("querystring"); var uuid = require("uuid"); diff --git a/test/pageview.js b/test/pageview.js index 19e5956..b4915a1 100644 --- a/test/pageview.js +++ b/test/pageview.js @@ -1,5 +1,4 @@ -var _ = require("underscore"); var request = require("request"); var qs = require("querystring"); var uuid = require("uuid"); diff --git a/test/send.js b/test/send.js index 10d800f..ad10460 100644 --- a/test/send.js +++ b/test/send.js @@ -1,5 +1,4 @@ -var _ = require("underscore"); var request = require("request"); var qs = require("querystring"); var uuid = require("uuid"); diff --git a/test/set.js b/test/set.js index 268f929..afafd93 100644 --- a/test/set.js +++ b/test/set.js @@ -1,5 +1,4 @@ -var _ = require("underscore"); var request = require("request"); var qs = require("querystring"); var uuid = require("uuid"); diff --git a/test/timing.js b/test/timing.js index d4ec0b8..a29b3d2 100644 --- a/test/timing.js +++ b/test/timing.js @@ -1,5 +1,4 @@ -var _ = require("underscore"); var request = require("request"); var qs = require("querystring"); var uuid = require("uuid"); diff --git a/test/transaction.js b/test/transaction.js index 5554d42..cbf14f9 100644 --- a/test/transaction.js +++ b/test/transaction.js @@ -1,5 +1,4 @@ -var _ = require("underscore"); var request = require("request"); var qs = require("querystring"); var uuid = require("uuid");