UNPKG

23.5 kBMarkdownView Raw
1universal-analytics
2=======
3
4A node module for Google's [Universal Analytics](http://support.google.com/analytics/bin/answer.py?hl=en&hlrm=de&answer=2790010) tracking via the [Measurement Protocol](https://developers.google.com/analytics/devguides/collection/protocol/v1/).
5
6This module allows tracking data (or rather, users) from within a Node.js application. Tracking is initiated on the server side and, if required, does not require any more tracking in the browser.
7
8[![npm version](https://badge.fury.io/js/universal-analytics.svg)](https://www.npmjs.com/package/universal-analytics) [![Build Status](https://travis-ci.org/peaksandpies/universal-analytics.png?branch=master)](https://travis-ci.org/peaksandpies/universal-analytics)
9
10
11# Table of Contents
12
13- [Getting started](#getting-started)
14- [Tracking](#tracking)
15 - [Pageviews](#pageview-tracking)
16 - [Screenviews](#screenview-tracking)
17 - [Events](#event-tracking)
18 - [Exceptions](#exception-tracking)
19 - [User timings](#user-timing-tracking)
20 - [Transactions](#transaction-tracking)
21 - [Transaction items](#transaction-item-tracking)
22- [Daisy-chaining tracking calls](#daisy-chaining-tracking-calls)
23- [Setting persistent parameters](#setting-persistent-parameters)
24- [Filter application tracking data](#filter-application-tracking-data)
25- [Session-based identification](#session-based-identification)
26- [Debug mode](#debug-mode)
27- [Request Options](#request-options)
28- [Shortcuts](#shortcuts)
29- [Tests](#tests)
30
31
32# Getting started
33
34`universal-analytics` is installed and included like any other node module:
35
36```
37$ npm install universal-analytics
38```
39
40```javascript
41var ua = require('universal-analytics');
42
43// Or with ES6 import
44import ua from 'universal-analytics'
45```
46
47Initialization expects at least your Google Analytics account ID:
48
49```javascript
50var visitor = ua('UA-XXXX-XX');
51```
52
53This 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:
54
55```javascript
56var visitor = ua('UA-XXXX-XX', '6a14abda-6b12-4578-bf66-43c754eaeda9');
57```
58
59Starting 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:
60
61```javascript
62var visitor = ua('UA-XXXX-XX', 'CUSTOM_CLIENTID_1', {strictCidFormat: false});
63```
64
65If you want to use Google Analytics in http protocol, just include it in the options `http: true`, by default will use https:
66```javascript
67var visitor = ua('UA-XXXX-XX', {http: true});
68```
69
70If you want to set User Id you can add it into options:
71```javascript
72var visitor = ua('UA-XXXX-XX', {uid: 'as8eknlll'});
73```
74[see about User Id](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#uid)
75
76
77Tracking a pageview without much else is now very simple:
78
79```javascript
80visitor.pageview("/").send()
81```
82
83The first argument for the pageview method is the path of the page to be tracked. Simply calling `pageview()` will not initiate a tracking request. In order to send off tracking to the Google Analytics servers you have two options:
84
851. You can append a `send()` call after `pageview()`. The tracking request is sent asynchronously. This means you will not receive any confirmation when and if it was successful.
862. You can provide a callback function to `pageview()` as an additional, last argument. This callback will be invoked once the tracking request has finished. Any error that occured during the request will be provided to said callback. In that case `send()` is no longer necessary.
87
88An example of the callback approach:
89
90```javascript
91var visitor = ua('UA-XXXX-XX');
92visitor.pageview("/", function (err) {
93 // Handle the error if necessary.
94 // In case no error is provided you can be sure
95 // the request was successfully sent off to Google.
96});
97```
98
99
100
101# Tracking
102
103
104## Pageview tracking
105
106The first argument for the pageview tracking call is the page path. Furthermore, pageview tracking can be improved with the additional parameters to provide the page's hostname and title to Google Analytics. The parameters are provided as arguments after the page path.
107
108```javascript
109visitor.pageview("/", "http://peaksandpies.com", "Welcome").send();
110```
111
112The following snippet is the exact same tracking using a callback. It is always the last argument.
113
114```javascript
115visitor.pageview("/", "http://peaksandpies.com", "Welcome", function (err) {
116 // …
117});
118```
119
120Depending on how you integrate tracking into your app, you might be more comfortable with providing all the tracking data via a params object to the `pageview()` method:
121
122```javascript
123visitor.pageview({dp: "/", dt: "Welcome", dh: "http://peaksandpies.com"}).send();
124```
125
126This code has the exact same effect as the one above. `dp`, `dt`, and `dh` (as in 'document path', 'document title' and 'document hostname') are the attribute names used by the Measurement Protocol.
127
128It's mandatory to specify either the page path (`dp`) or document location (`dl`). Google Analytics can not track a pageview without a path. To avoid such erroneous requests, `universal-analytics` will deny `pageview()` tracking if the required parameters are omitted.
129
130```javascript
131var pagePath = null;
132
133visitor.pageview(pagePath, function (err) {
134 // This callback will receive an error
135});
136```
137
138The following method signatures are available for the `pageview()` method of the Visitor instance:
139
140* `Visitor#pageview(path)`
141* `Visitor#pageview(path, callback)`
142* `Visitor#pageview(params)`
143* `Visitor#pageview(params, callback)`
144* `Visitor#pageview(path, hostname)`
145* `Visitor#pageview(path, hostname, callback)`
146* `Visitor#pageview(path, hostname, title)`
147* `Visitor#pageview(path, hostname, title, callback)`
148
149See also: [List of acceptable params](AcceptableParams.md).
150
151
152
153
154
155## Screenview tracking
156
157Instead of pageviews app will want to track screenviews.
158
159```javascript
160visitor.screenview("Home Screen", "App Name").send()
161```
162
163The following method signatures are available for #screenview:
164
165* `Visitor#screenview(screenName, appName)`
166* `Visitor#screenview(screenName, appName, callback)`
167* `Visitor#screenview(screenName, appName, appVersion)`
168* `Visitor#screenview(screenName, appName, appVersion, callback)`
169* `Visitor#screenview(screenName, appName, appVersion, appId)`
170* `Visitor#screenview(screenName, appName, appVersion, appId, callback)`
171* `Visitor#screenview(screenName, appName, appVersion, appId, appInstallerId)`
172* `Visitor#screenview(screenName, appName, appVersion, appId, appInstallerId, callback)`
173* `Visitor#screenview(screenName, appName, appVersion, appId, appInstallerId, params)`
174* `Visitor#screenview(screenName, appName, appVersion, appId, appInstallerId, params, callback)`
175* `Visitor#screenview(params)`
176* `Visitor#screenview(params, callback)`
177
178See also: [List of acceptable params](AcceptableParams.md).
179
180
181
182
183
184
185## Event tracking
186
187
188Tracking events with `universal-analytics` works like pageview tracking, only you have to provide different arguments:
189
190```javascript
191visitor.event("Event Category", "Event Action").send()
192```
193
194This is the most straightforward way to track an event. The event attributes *label* and *value* are optional and can be provided if necessary:
195
196```javascript
197visitor.event("Event Category", "Event Action", "…and a label", 42).send()
198```
199
200Just like pageview tracking, event tracking supports a callback as the last argument:
201
202```javascript
203visitor.event("Event Category", "Event Action", "…and a label", 42, function (err) {
204 // …
205})
206```
207
208An additional attribute for events is the path of the page they should be associated with in Google Analytics. You can provide this path via an additional params object:
209
210```javascript
211visitor.event("Event Category", "Event Action", "…and a label", 42, {p: "/contact"}, function (err) {
212 // …
213})
214```
215
216*Notice:* The page path attribute for the event is called `p` which differs from the `dp` attribute used in the pageview tracking example. `universal-analytics` is smart enough to use the `dp` attribute should you provide it instead of `p`.
217
218In case this argument list is getting a little long, `event()` also accepts a params object like `pageview()`:
219
220```javascript
221var params = {
222 ec: "Event Category",
223 ea: "Event Action",
224 el: "…and a label",
225 ev: 42,
226 dp: "/contact"
227}
228
229visitor.event(params).send();
230```
231
232The category (`ec`) and the action (`ea`) are mandatory. Google Analytics will not track an event without them. To avoid such erroneous requests, universal-analytics will deny `event()` tracking if either attribute is omitted.
233
234```javascript
235var action = null;
236
237visitor.event("Navigation clicks", action, function (err) {
238 // This callback will receive an error
239});
240```
241
242The following method signatures are available for #event:
243
244* `Visitor#event(category, action)`
245* `Visitor#event(category, action, callback)`
246* `Visitor#event(category, action, label)`
247* `Visitor#event(category, action, label, callback)`
248* `Visitor#event(category, action, label, value)`
249* `Visitor#event(category, action, label, value, callback)`
250* `Visitor#event(category, action, label, value, params, callback)`
251* `Visitor#event(params)`
252* `Visitor#event(params, callback)`
253
254See also: [List of acceptable params](AcceptableParams.md).
255
256
257
258
259
260## E-commerce tracking
261
262E-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.
263
264```javascript
265visitor
266 .transaction("trans-12345", 500) // Create transaction trans-12345 worth 500 total.
267 .item(300, 1, "item-54321") // Add 1 unit the item item-54321 worth 300.
268 .item(200, 2, "item-41325") // Add 2 units the item item-41325 worth 200.
269 .send()
270```
271
272Once again, daisy-chaining simplifies associating the items with the transaction. Officially, nothing but the transaction ID is a requirement for both the transaction and the items. However, providing a minimum set of information (revenue for the transaction, price, quantity and ID for the items) is recommended.
273
274It is also possible to provide the params as an object to both methods:
275
276```javascript
277visitor
278 .transaction({ti: "trans-12345", tr: 500, ts: 50, tt: 100, ta: "Partner 13"})
279 .item({ip: 300, iq: 1, ic: "item-54321", in: "Item 54321", iv: "Blue"})
280 .item({ip: 200, iq: 2, ic: "item-41325", in: "Item 41325", iv: "XXL"})
281 .send()
282```
283
284In case an additional item has to be added later on or daisy-chaining is not available for another reason, each item can be given an associated transaction ID via the params object as well:
285
286visitor.item({ip: 100, iq: 1, ic: "item-41325", in: "Item 41325", iv: "XL", ti: "trans-12345"}).send()
287
288The transaction ID (`ti`) is mandatory for both the transaction and the item. Google Analytics will not track e-commerce data without it. To avoid such erroneous requests, universal-analytics will deny `transaction()` and `item()` tracking if it is omitted.
289
290```javascript
291var ti = null;
292
293visitor.transaction(ti, function (err) {
294 // This callback will receive an error
295});
296```
297
298The following method signatures are available for #transaction:
299
300* `Visitor#transaction(id)`
301* `Visitor#transaction(id, callback)`
302* `Visitor#transaction(id, revenue)`
303* `Visitor#transaction(id, revenue, callback)`
304* `Visitor#transaction(id, revenue, shipping)`
305* `Visitor#transaction(id, revenue, shipping, callback)`
306* `Visitor#transaction(id, revenue, shipping, tax)`
307* `Visitor#transaction(id, revenue, shipping, tax, callback)`
308* `Visitor#transaction(id, revenue, shipping, tax, affiliation)`
309* `Visitor#transaction(id, revenue, shipping, tax, affiliation, callback)`
310* `Visitor#transaction(params)`
311* `Visitor#transaction(params, callback)`
312
313The following method signatures are available for #item:
314
315* `Visitor#item(price)`
316* `Visitor#item(price, callback)`
317* `Visitor#item(price, quantity)`
318* `Visitor#item(price, quantity, callback)`
319* `Visitor#item(price, quantity, sku)`
320* `Visitor#item(price, quantity, sku, callback)`
321* `Visitor#item(price, quantity, sku, name)`
322* `Visitor#item(price, quantity, sku, name, callback)`
323* `Visitor#item(price, quantity, sku, name, variation)`
324* `Visitor#item(price, quantity, sku, name, variation, callback)`
325* `Visitor#item(price, quantity, sku, name, variation, params)`
326* `Visitor#item(price, quantity, sku, name, variation, params, callback)`
327* `Visitor#item(params)`
328* `Visitor#item(params, callback)`
329
330See also: [List of acceptable params](AcceptableParams.md).
331
332
333
334
335
336
337## Exception tracking
338
339Exception 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.
340
341```javascript
342visitor.exception("StackOverflow Error").send()
343```
344
345As an additional information, the exception can be flagged as fatal if the error was exceptionally bad.
346
347```javascript
348var fatal = true;
349visitor.exception("StackOverflow Error", fatal, function () {
350 // Finish handling this error
351});
352```
353
354The following method signatures are available for #exception:
355
356* `Visitor#exception(description)`
357* `Visitor#exception(description, callback)`
358* `Visitor#exception(description, fatal)`
359* `Visitor#exception(description, fatal, callback)`
360* `Visitor#exception(params)`
361* `Visitor#exception(params, callback)`
362
363See also: [List of acceptable params](AcceptableParams.md).
364
365
366
367
368
369
370## User timing tracking
371
372Tracking 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.
373
374```javascript
375visitor.timing("User interaction", "Time to open login overlay", 12547).send()
376```
377
378The following method signatures are available for #timing:
379
380* `Visitor#timing(category)`
381* `Visitor#timing(category, callback)`
382* `Visitor#timing(category, variable)`
383* `Visitor#timing(category, variable, callback)`
384* `Visitor#timing(category, variable, time)`
385* `Visitor#timing(category, variable, time, callback)`
386* `Visitor#timing(category, variable, time, label)`
387* `Visitor#timing(category, variable, time, label, callback)`
388* `Visitor#timing(params)`
389* `Visitor#timing(params, callback)`
390
391See also: [List of acceptable params](AcceptableParams.md).
392
393
394
395
396
397## Transaction tracking
398
399Transactions are the main tracking calls for ecommerce tracking
400
401```javascript
402visitor.transaction("123456", "449.99").send()
403```
404
405The following method signatures are available for #transaction:
406
407* `Visitor#transaction(transactionId)`
408* `Visitor#transaction(transactionId, callback)`
409* `Visitor#transaction(transactionId, revenue)`
410* `Visitor#transaction(transactionId, revenue, callback)`
411* `Visitor#transaction(transactionId, revenue, shippingCost)`
412* `Visitor#transaction(transactionId, revenue, shippingCost, callback)`
413* `Visitor#transaction(transactionId, revenue, shippingCost, tax)`
414* `Visitor#transaction(transactionId, revenue, shippingCost, tax, callback)`
415* `Visitor#transaction(transactionId, revenue, shippingCost, tax, affiliation)`
416* `Visitor#transaction(transactionId, revenue, shippingCost, tax, affiliation, callback)`
417* `Visitor#transaction(transactionId, revenue, shippingCost, tax, affiliation, params)`
418* `Visitor#transaction(transactionId, revenue, shippingCost, tax, affiliation, params, callback)`
419* `Visitor#transaction(params)`
420* `Visitor#transaction(params, callback)`
421
422See also: [List of acceptable params](AcceptableParams.md).
423
424
425
426
427
428### Transaction item tracking
429
430Transaction consist of one or more items.
431
432```javascript
433visitor.item(449.99, 1, "ID54321", "T-Shirt", {ti: "123456"}).send()
434```
435
436The following method signatures are available for #item:
437
438* `Visitor#item(price)`
439* `Visitor#item(price, callback)`
440* `Visitor#item(price, quantity)`
441* `Visitor#item(price, quantity, callback)`
442* `Visitor#item(price, quantity, sku)`
443* `Visitor#item(price, quantity, sku, callback)`
444* `Visitor#item(price, quantity, sku, name)`
445* `Visitor#item(price, quantity, sku, name, callback)`
446* `Visitor#item(price, quantity, sku, name, variation)`
447* `Visitor#item(price, quantity, sku, name, variation, callback)`
448* `Visitor#item(price, quantity, sku, name, variation, params)`
449* `Visitor#item(price, quantity, sku, name, variation, params, callback)`
450* `Visitor#item(params)`
451* `Visitor#item(params, callback)`
452
453See also: [List of acceptable params](AcceptableParams.md).
454
455
456
457
458
459
460# Daisy-chaining tracking calls
461
462We have seen basic daisy-chaining above when calling `send()` right after `pageview()` and `event()`:
463
464```javascript
465visitor.pageview("/").send()
466```
467
468Every call of a tracking method returns a visitor instance you can re-use:
469
470```javascript
471visitor.pageview("/").pageview("/contact").send()
472```
473
474Granted, the chance of this example actually happening in practice might be rather low.
475
476However, `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:
477
478```javascript
479visitor.pageview("/landing-page-1").event("Testing", "Button color", "Blue").send()
480```
481This is the same as two distinct tracking calls.
482
483```javascript
484visitor.pageview("/landing-page-1").send()
485visitor.event("Testing", "Button color", "Blue", {p: "/landing-page-1"}).send()
486```
487
488Daisy-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.
489
490It also works when using a callback since the `this` inside the callback will be the `universal-analytics` Visitor instance:
491
492```javascript
493visitor.pageview("/landing-page-1", function (err) {
494 if (!err) {
495 this.event("Testing", "Button color", "Blue").send()
496 }
497});
498```
499
500More 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:
501
502```javascript
503visitor
504 .event({ec: "Mail Server", ea: "New Team Member Notification sent"})
505 .event({ea: "Invitation sent"})
506 .send();
507```
508
509In this example the event category ("Mail Server") is not repeated in the second tracking call.
510
511
512
513
514# Setting persistent parameters
515
516Some 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
517
518```javascript
519 visitor.set("uid", "123456789");
520```
521
522The uid parameter will be part of every tracking request of that visitor from now on.
523
524For custom dimensions, you will not pass `dimension#` rather `cd#`:
525
526```javascript
527 visitor.set("cd[1-20]", "123456789"); // [1-20] will be the dimension number
528```
529
530# Filter application tracking data
531
532Set a persistent parameter for [`Data Source`](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#ds) to `app` in order to mark tracking data as `Application`.
533
534```javascript
535 visitor.set("ds", "app"); // Allows filtering by the 'Application?' field in GA
536```
537
538Then create a new view in Google Analytics of type 'Application'. You will then need to filter the data for that view by creating a new filter that either includes or excludes `Application? Yes` (depending on if you want to show(includes) or hide(excludes) application analytics in a given view).
539
540![Google Analytics Setup](https://i.imgur.com/ZDZ3ZPO.png)
541
542# Session-based identification
543
544In 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.
545
546```javascript
547var ua = require("universal-analytics");
548var express = require("express");
549
550var app = express()
551
552express.use(ua.middleware("UA-XXXX-Y", {cookieName: '_ga'}));
553```
554
555The middleware will attach the `universal analytics` visitor instance to every request (`req.visitor`).
556
557Additionally, the module also exposes a `createFromSession` method to create a visitor instance simply based on a session, which is helpful when working with Socket.io, etc. where the middleware is not used.
558
559```javascript
560var visitor = ua.createFromSession(socket.handshake.session);
561```
562
563# Debug mode
564
565`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:
566
567```
568DEBUG=universal-analytics
569```
570
571
572# Request Options
573
574In 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`.
575
576```javascript
577var visitor = ua('UA-XXXX-XX', {
578 requestOptions: {
579 proxy: "…"
580 }
581});
582```
583
584
585# Shortcuts
586
587The tracking methods have shortcuts:
588
589* `Visitor#pv` as an alias for `Visitor#pageview`
590* `Visitor#e` as an alias for `Visitor#event`
591* `Visitor#t` as an alias for `Visitor#transaction`
592* `Visitor#i` as an alias for `Visitor#item`
593
594
595# Tests
596
597The tests are written with [mocha](https://github.com/visionmedia/mocha) using [should](https://github.com/visionmedia/should.js) and [Sinon.JS](https://github.com/cjohansen/Sinon.JS).
598
599Run them by executing the following commands in the `universal-analytics` directory:
600
601```
602$ npm install
603$ make test
604```
605
606# License
607
608(The MIT License)
609
610Copyright (c) 2017 Peaks & Pies GmbH <hello@peaksandpies.com>
611
612Permission is hereby granted, free of charge, to any person obtaining
613a copy of this software and associated documentation files (the
614'Software'), to deal in the Software without restriction, including
615without limitation the rights to use, copy, modify, merge, publish,
616distribute, sublicense, and/or sell copies of the Software, and to
617permit persons to whom the Software is furnished to do so, subject to
618the following conditions:
619
620The above copyright notice and this permission notice shall be
621included in all copies or substantial portions of the Software.
622
623THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
624EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
625MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
626IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
627CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
628TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
629SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652