Skip to content
This repository was archived by the owner on Jul 22, 2024. It is now read-only.

Commit 349b7a7

Browse files
committed
Improved integraiton with Google Analytics.
By migrating to gtag (which is the preferred client of GA), we can provide seamless integration with GA. This version is stricter in respecting Do-Not-Track.
1 parent 8506a0a commit 349b7a7

File tree

3 files changed

+102
-89
lines changed

3 files changed

+102
-89
lines changed
Lines changed: 98 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,26 @@
1-
/* global localStorage, location, Raven */
1+
/* global Raven */
22
(function (window) {
33
'use strict';
44

5+
/*
6+
* The main requirements when dealing with Do-Not-Track (DNT) are:
7+
*
8+
* 1. Prevent explicit collection, storage and sending data if DNT is enabled.
9+
*
10+
* 2. GA and Telemetry APIs should not throw or error if DNT is enabled,
11+
* although they must ensure requirement #1.
12+
*
13+
* 3. If DNT is enabled in the middle of the gameplay, the API must ensure
14+
* requirements #1 and #2. If DNT is disabled in the middle of the gameplay,
15+
* resuming data collection is not mandatory.
16+
*
17+
* FOR MAINTAINERS: Some collection can happen implicitly when loading 3rd party
18+
* libraries. Try to prevent loading external libraries if DNT is enabled and
19+
* this does not conflict with requirement #2.
20+
*/
21+
22+
var CURRENT_VERSION = '1.0.2';
23+
524
if (!('MozillaResearch' in window)) {
625
window.MozillaResearch = {};
726
}
@@ -13,64 +32,57 @@ if (!('telemetry' in window.MozillaResearch)) {
1332
var navigator = window.navigator;
1433
var telemetry = window.MozillaResearch.telemetry;
1534

16-
telemetry.ga = {
17-
create: function (trackingId, cookieDomain, name, fieldsObject) {
18-
window.ga('create', trackingId, cookieDomain, name, fieldsObject);
19-
return function (command) {
20-
if (navigator.doNotTrack === '1') { return; }
21-
var args = Array.prototype.slice.call(arguments);
22-
if (name && command !== 'provide') {
23-
command = name + '.' + command;
24-
args[0] = command;
25-
}
26-
window.ga.apply(undefined, args);
27-
};
28-
}
29-
};
30-
3135
var NO_OP = function () {};
3236

37+
// Always returns what is in `window[GA_ALIAS]`. According to:
38+
// https://developers.google.com/analytics/devguides/collection/analyticsjs/how-analyticsjs-works
39+
// The `analytics.js` script will redefine the `window[GA_ALIAS]` function after
40+
// loading. Accessing the function indirectly ensures we always get the most
41+
// recent implementation of it.
42+
Object.defineProperty(telemetry, '_gtag', {
43+
get: function () {
44+
return window.gtag || NO_OP;
45+
}
46+
});
47+
3348
telemetry.performance = {
3449
mark: NO_OP,
3550
measure: NO_OP
3651
};
3752

3853
telemetry.start = function (config) {
3954
config = config || {};
40-
if (navigator.doNotTrack === '1') {
41-
return;
42-
}
4355
if (config.errorLogging) {
44-
startErrorLogging();
56+
setupErrorLogging();
4557
}
4658
if (config.analytics) {
4759
var researchAnalytics = startAnalytics();
4860
if (config.performance) {
49-
configurePerformanceAPI(researchAnalytics);
61+
setupPerformanceAPI(researchAnalytics);
5062
}
5163
}
5264
};
5365

5466
setupAnalytics();
5567

5668
function setupAnalytics() {
57-
window.ga = window.ga || function () {
58-
(window.ga.q = (window.ga.q || [])).push(arguments)
59-
};
60-
window.ga.l = +(new Date());
69+
if (doNotTrack()) { return; }
6170

62-
if (navigator.doNotTrack === '1') {
63-
return;
64-
}
65-
injectScript('https://www.google-analytics.com/analytics.js', function (err) {
71+
window.dataLayer = window.dataLayer || [];
72+
window.gtag = window.gtag || function () { dataLayer.push(arguments); };
73+
window.gtag('js', new Date());
74+
75+
injectScript('https://www.googletagmanager.com/gtag/js?id=UA-77033033-6', function (err) {
6676
if (err) {
6777
console.warn('Could not load Analytics.js script:', err);
6878
return;
6979
}
70-
});
80+
});
7181
}
7282

73-
function startErrorLogging() {
83+
function setupErrorLogging() {
84+
if (doNotTrack()) { return; }
85+
7486
injectScript('https://cdn.ravenjs.com/3.22.3/console/raven.min.js', function (err) {
7587
if (err) {
7688
console.warn('Could not load Raven.js script:', err);
@@ -80,43 +92,72 @@ function startErrorLogging() {
8092
console.warn('Could not find `window.Raven` global');
8193
return;
8294
}
83-
configureRaven();
95+
startRaven();
8496
});
8597

86-
function configureRaven () {
87-
console.log('Raven.js script loaded');
98+
function startRaven () {
8899
Raven.config('https://e359be9fb9324addb0dc97b664cf5ee6@sentry.io/294878')
89-
.install();
100+
.install();
90101
}
91102
};
92103

93104
function startAnalytics() {
94-
var CURRENT_VERSION = '1.0.1';
95-
var ga = telemetry.ga.create('UA-77033033-6', 'auto', 'mozillaResearch');
96-
ga('set', 'dimension1', CURRENT_VERSION);
97-
ga('send', 'pageview');
98-
return ga;
105+
var tracker = newTracker('UA-77033033-6', {
106+
'groups': 'MozillaResearch',
107+
'custom_map': {
108+
'dimension1': 'version'
109+
}
110+
});
111+
tracker('event', 'using_webvr_template', { version: CURRENT_VERSION });
112+
return tracker;
99113
}
100114

101-
function configurePerformanceAPI(ga) {
115+
function setupPerformanceAPI(tracker) {
102116
telemetry.performance = {
103117
mark: function (name) {
118+
if (doNotTrack()) { return; }
119+
104120
performance.mark(name);
105121
},
106-
122+
107123
measure: function (name, start, end) {
108-
if (navigator.doNotTrack === '1') {
109-
return;
110-
}
124+
if (doNotTrack()) { return; }
125+
111126
performance.measure(name, start, end);
112127
var performanceEntry = performance.getEntriesByName(name)[0];
113128
var duration = performanceEntry.duration;
114-
ga('send', 'event', 'Performance', name, undefined, duration);
129+
tracker('event', name, {
130+
'event_category': 'Performance',
131+
'value': Math.round(duration)
132+
});
115133
}
116134
};
117135
}
118136

119-
function injectScript (src, callback) {
137+
// Provides a convenient shortcut for named trackers by automatically adding the
138+
// name of the tracker to the command. The function accepts the same parameters
139+
// that follow `create` command. See:
140+
// https://developers.google.com/analytics/devguides/collection/analyticsjs/creating-trackers
141+
function newTracker(trackingId, options) {
142+
if (doNotTrack()) { return NO_OP; }
143+
144+
options = options || {};
145+
var groups = options.groups;
146+
telemetry._gtag('config', trackingId, options);
147+
return trackingFunction;
148+
149+
function trackingFunction(command, label, options) {
150+
if (doNotTrack()) { return; }
151+
152+
options = options || {};
153+
if (groups) {
154+
options.send_to = groups;
155+
}
156+
telemetry._gtag(command, label, options);
157+
};
158+
}
159+
160+
function injectScript(src, callback) {
120161
var script = document.createElement('script');
121162
script.src = src;
122163
script.crossorigin = 'anonymous';
@@ -134,4 +175,13 @@ function injectScript (src, callback) {
134175
return script;
135176
}
136177

137-
})(window);
178+
// IE9/IE10 uses a prefixed version while MS Edge sets the property in
179+
// `window` instead of `navigator`:
180+
// https://developer.mozilla.org/en-US/docs/Web/API/Navigator/doNotTrack#Browser_compatibility
181+
function doNotTrack() {
182+
return navigator.doNotTrack === '1' ||
183+
navigator.msDoNotTrack === '1' ||
184+
window.doNotTrack === '1';
185+
}
186+
187+
})(window);

docs/customization/adding-ga.md

Lines changed: 4 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -18,53 +18,16 @@ When you finish, click on `Get Tracking ID` at the bottom of the page:
1818

1919
![Buttons Get Tracking ID and Cancel at the bottom of the page](./images/filled-2.png)
2020

21-
This will redirect you to the configuration page where you find the HTML code you need to use in the template:
21+
This will redirect you to the configuration page where you find the HTML code you'd use in the template:
2222

2323
![The configuration page includes the instructions for setting up your site](./images/setup-done.png)
2424

25-
**Don't use the snippet above**. Instead, with your favourite code editor, open the file at `Assets/WebGLTemplates/WebVR/index.html` and paste the following code after including the `telemetry.js` library, preferably at the bottom of the `<head>` tag:
26-
27-
```html
28-
<script>
29-
var ga = MozillaResearch.telemetry.ga.create('UA-XXXXXXX-Y');
30-
ga('send', 'pageview');
31-
</script>
32-
```
33-
34-
![The code provided by GA should be added after including the telemetry library](./images/add-to-index.png)
35-
36-
### Template integration of Google Analytics
37-
38-
If you have used Google Analytics before, the previous code should remind you of the familiar Analytics snippet:
39-
40-
```js
41-
ga('create', 'UA-XXXXXX-Y', 'auto');
42-
ga('send', 'pageview');
43-
```
44-
45-
When using Analytics inside the template, use the `create` method of `MozillaReasearch.telemetry.ga` instead of the `create` command. It will return a tracking function which can be used in the same way you would use it in the guide [Sending Data to Google Analytics](https://developers.google.com/analytics/devguides/collection/analyticsjs/creating-trackers).
46-
47-
```js
48-
var ga = MozillaResearch.telemetry.ga.create('UA-XXXXXX-Y', 'auto');
49-
ga('send', 'pageview');
50-
```
51-
52-
If you want to customize the way you create the tracker, read [Creating Trackers](https://developers.google.com/analytics/devguides/collection/analyticsjs/creating-trackers) and remember that:
53-
54-
```js
55-
ga('create', arg1, arg2, ...);
56-
```
57-
58-
Is equivalent to:
59-
60-
```js
61-
var ga = MozillaResearch.telemetry.ga.create(arg1, arg2, ...);
62-
```
25+
Add the snippet just after the `<head>` tag and you'll be ready to go.
6326

6427
## Using Google Analytics
6528

66-
The amount of data in Google Analytics can be overwhelming to navigate and dissect. Fortunately, the folks at Google have developed a series of courses to explain you the main concepts of traffic analysis. We recommend you start at [Google Analytics Academy](https://analytics.google.com/analytics/academy/).
29+
The amount of data in Google Analytics can be overwhelming to navigate and dissect. Fortunately, the folks at Google have developed a series of courses to explain you the main concepts of traffic analysis. We recommend you start at [Google Analytics Academy](https://analytics.google.com/analytics/academy/).
6730

6831
## Open-source alternatives
6932

70-
There are a few [open-source alternatives](https://en.wikipedia.org/wiki/List_of_web_analytics_software#Free_/_Open_source_(FLOSS)) out there. Like Google Analytics, they are free although you need to host them yourself. We recommend [Matomo](https://matomo.org/) and [Open Web Analytics](http://www.openwebanalytics.com) (OWA). Both offer geolocation, click-heat maps, traffic by referrer, event tracking, etc. Which specifically depends on your needs but you can compare both side by side visiting the [demo pages for Matomo](https://demo.matomo.org) and [OWA](http://demo.openwebanalytics.com/owa/).
33+
There are a few [open-source alternatives](https://en.wikipedia.org/wiki/List_of_web_analytics_software#Free_/_Open_source_(FLOSS)) out there. Like Google Analytics, they are free although you need to host them yourself. We recommend [Matomo](https://matomo.org/) and [Open Web Analytics](http://www.openwebanalytics.com) (OWA). Both offer geolocation, click-heat maps, traffic by referrer, event tracking, etc. Which specifically depends on your needs but you can compare both side by side visiting the [demo pages for Matomo](https://demo.matomo.org) and [OWA](http://demo.openwebanalytics.com/owa/).
-189 KB
Binary file not shown.

0 commit comments

Comments
 (0)