@guardian/ophan-tracker-js 2.0.4 → 2.1.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/adblock-detection.js +24 -0
- package/assets/attention.js +187 -0
- package/assets/campaign.js +40 -0
- package/assets/click-path-capture.js +107 -0
- package/assets/components.js +209 -0
- package/assets/contribution.js +25 -0
- package/assets/core.js +282 -0
- package/assets/embed.js +11 -0
- package/assets/fb-instant.js +10 -0
- package/assets/heatmap.js +47 -0
- package/assets/holidays.js +11 -0
- package/assets/http-status.js +20 -0
- package/assets/iframe-tracking.js +82 -0
- package/assets/interactive.js +25 -0
- package/assets/jobs-courses.js +11 -0
- package/assets/jobs.js +11 -0
- package/assets/manage-my-account.js +50 -0
- package/assets/membership.js +25 -0
- package/assets/ng.js +41 -0
- package/assets/perf.js +43 -0
- package/assets/privatebrowsing.js +79 -0
- package/{build → assets}/r2.js +3 -3
- package/{build → assets}/smart-news.js +4 -4
- package/assets/support.js +44 -0
- package/assets/transmit.js +150 -0
- package/assets/vendor/adBlockDetectionLib.js +366 -0
- package/assets/visibility.js +20 -0
- package/{build → assets}/witness.js +3 -3
- package/package.json +28 -24
- package/build/adblock-detection.js +0 -24
- package/build/attention.js +0 -149
- package/build/campaign.js +0 -30
- package/build/click-path-capture.js +0 -81
- package/build/components.js +0 -167
- package/build/contribution.js +0 -25
- package/build/core.js +0 -234
- package/build/embed.js +0 -11
- package/build/fb-instant.js +0 -10
- package/build/heatmap.js +0 -32
- package/build/holidays.js +0 -11
- package/build/http-status.js +0 -20
- package/build/iframe-tracking.js +0 -68
- package/build/interactive.js +0 -25
- package/build/jobs-courses.js +0 -11
- package/build/jobs.js +0 -11
- package/build/manage-my-account.js +0 -47
- package/build/membership.js +0 -25
- package/build/ng.js +0 -33
- package/build/perf.js +0 -39
- package/build/privatebrowsing.js +0 -71
- package/build/support.js +0 -41
- package/build/transmit.js +0 -107
- package/build/vendor/adBlockDetectionLib.js +0 -367
- package/build/visibility.js +0 -7
package/assets/core.js
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
let init,
|
|
2
|
+
sendInitialEvent,
|
|
3
|
+
storeDataToSendOnNextEvent,
|
|
4
|
+
hasProp = {}.hasOwnProperty;
|
|
5
|
+
|
|
6
|
+
import transmit from './transmit.js';
|
|
7
|
+
|
|
8
|
+
import visibility from './visibility.js';
|
|
9
|
+
|
|
10
|
+
import adblockDetection from './adblock-detection.js';
|
|
11
|
+
|
|
12
|
+
const VERSION = 17;
|
|
13
|
+
|
|
14
|
+
let doc = window.document;
|
|
15
|
+
|
|
16
|
+
const canStoreEventsInLocalStorage =
|
|
17
|
+
window.localStorage != null && typeof JSON !== 'undefined' && JSON !== null;
|
|
18
|
+
|
|
19
|
+
let platform = null;
|
|
20
|
+
|
|
21
|
+
const MaximumComponentNameLength = 50;
|
|
22
|
+
|
|
23
|
+
init = function (servingPlatform, httpStatus) {
|
|
24
|
+
platform = servingPlatform;
|
|
25
|
+
if (visibility.state() !== 'prerender') {
|
|
26
|
+
return sendInitialEvent(httpStatus);
|
|
27
|
+
} else {
|
|
28
|
+
if (visibility.changeEvent) {
|
|
29
|
+
return doc.addEventListener(
|
|
30
|
+
visibility.changeEvent,
|
|
31
|
+
function () {
|
|
32
|
+
if (visibility.state() === 'visible') {
|
|
33
|
+
return sendInitialEvent(httpStatus);
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
false,
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Retrieves the value of a specified query parameter from the current page's URL.
|
|
44
|
+
* Using an old-fashioned way of finding a query param rather than using searchParams
|
|
45
|
+
* as we don't control which environments the CDN distribution is being used in and so don't know if it's supported.
|
|
46
|
+
* @param {string} paramName - The name of the query parameter to retrieve.
|
|
47
|
+
* @returns {string | undefined} The value of the query parameter, or undefined if not found.
|
|
48
|
+
*/
|
|
49
|
+
const getQueryParameterValue = (paramName) => {
|
|
50
|
+
const queryString = window.location.search.substring(1);
|
|
51
|
+
const queryParams = queryString.split('&');
|
|
52
|
+
|
|
53
|
+
for (const param of queryParams) {
|
|
54
|
+
const [key, value] = param.split('=');
|
|
55
|
+
if (key === paramName) {
|
|
56
|
+
return decodeURIComponent(value);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Retrieves the referrer URL from the given referrer or a fallback query parameter.
|
|
63
|
+
* If an authentication flow takes place on page load, the referrer is lost.
|
|
64
|
+
* So, if no referrer, fall back to query param holding the value of the referrer before the auth flow began.
|
|
65
|
+
* See https://github.com/guardian/support-frontend/blob/main/support-frontend/app/controllers/AuthCodeFlowController.scala#L105
|
|
66
|
+
* for an example use. * @param {string} referrer - The document referrer.
|
|
67
|
+
* @param {string} referrer - The document referrer.
|
|
68
|
+
* @returns {string} The referrer URL or the fallback query parameter value.
|
|
69
|
+
*/
|
|
70
|
+
const getReferrer = (referrer) => {
|
|
71
|
+
return referrer || getQueryParameterValue('pre-auth-ref') || '';
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Retrieves the type of navigation that occurred to arrive at the current page, using the Performance API.
|
|
76
|
+
* Returns null if the navigation type is not available.
|
|
77
|
+
* @returns {string | null} The navigation type (e.g., 'navigate', 'reload', 'back_forward'), or null if not available.
|
|
78
|
+
*/
|
|
79
|
+
const getNavigationType = () => {
|
|
80
|
+
if (window.performance?.getEntriesByType) {
|
|
81
|
+
const entries = window.performance.getEntriesByType('navigation');
|
|
82
|
+
if (entries.length > 0) {
|
|
83
|
+
return entries[0].type;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
sendInitialEvent = function (
|
|
90
|
+
httpStatus,
|
|
91
|
+
url = location.href,
|
|
92
|
+
referrer = window.document.referrer,
|
|
93
|
+
) {
|
|
94
|
+
const navigationType = getNavigationType();
|
|
95
|
+
// send initial event
|
|
96
|
+
const event = {
|
|
97
|
+
v: VERSION,
|
|
98
|
+
platform: platform,
|
|
99
|
+
url: url,
|
|
100
|
+
ref: getReferrer(referrer),
|
|
101
|
+
visibilityState: visibility.state(),
|
|
102
|
+
isModernBrowser:
|
|
103
|
+
typeof guardian !== 'undefined' && guardian !== null
|
|
104
|
+
? guardian.isModernBrowser
|
|
105
|
+
: void 0,
|
|
106
|
+
httpStatus: httpStatus,
|
|
107
|
+
tz: new Date().getTimezoneOffset(),
|
|
108
|
+
};
|
|
109
|
+
if (navigationType != null) {
|
|
110
|
+
// Add navigation type as metadata to the event if it's not null
|
|
111
|
+
event.navigationType = navigationType;
|
|
112
|
+
}
|
|
113
|
+
appendContentType(event);
|
|
114
|
+
appendDataFromLocalStorageToEvent(event);
|
|
115
|
+
transmit.sendInitial(event);
|
|
116
|
+
return adblockDetection.run().then(function (adBlockerEnabled) {
|
|
117
|
+
// `adUnitWasHidden` is the query param used
|
|
118
|
+
// by the previous adblock detection, hence reusing it here.
|
|
119
|
+
return transmit.sendMore({
|
|
120
|
+
adUnitWasHidden: adBlockerEnabled,
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const onLoadCaptures = [];
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Registers a data capture function to be called when the document is fully loaded.
|
|
129
|
+
* The result of this function is then sent to the tracker backend service.
|
|
130
|
+
* If the document is already loaded, this is done immediately.
|
|
131
|
+
*
|
|
132
|
+
* @param {() => Record<string, unknown>} dataCapture - A function that returns an object containing performance metrics such as page load time, network latency, etc.
|
|
133
|
+
* Refer to the `perf.js` file where this function is used for more info.
|
|
134
|
+
*/
|
|
135
|
+
const onLoadCapture = (dataCapture) => {
|
|
136
|
+
if (document.readyState === 'complete') {
|
|
137
|
+
const msg = { ...dataCapture() };
|
|
138
|
+
transmit.sendMore(msg);
|
|
139
|
+
} else {
|
|
140
|
+
onLoadCaptures.push(dataCapture);
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Processes all registered data capture functions, merges their outputs and sends it to the tracker backend service.
|
|
146
|
+
* If on a 'next-gen' platform, additional component data is appended to the event via the `appendComponentDataToEvent` function.
|
|
147
|
+
*/
|
|
148
|
+
const processCaptures = () => {
|
|
149
|
+
const msg = {};
|
|
150
|
+
|
|
151
|
+
for (const capture of onLoadCaptures) {
|
|
152
|
+
const captureData = capture();
|
|
153
|
+
|
|
154
|
+
for (const key in captureData) {
|
|
155
|
+
if (captureData.hasOwnProperty(key)) {
|
|
156
|
+
msg[key] = captureData[key];
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (platform === 'next-gen') {
|
|
162
|
+
appendComponentDataToEvent(msg);
|
|
163
|
+
}
|
|
164
|
+
transmit.sendMore(msg);
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
window.addEventListener?.('load', processCaptures, false);
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Appends data from local storage to a given event object.
|
|
171
|
+
* Specifically targets data stored under the 'ophan_follow' key in localStorage.
|
|
172
|
+
* After appending the data to the event, it removes the data from localStorage.
|
|
173
|
+
* @param {Record<string, unknown>} event - The event object to which the local storage data will be appended.
|
|
174
|
+
*/
|
|
175
|
+
const appendDataFromLocalStorageToEvent = (event) => {
|
|
176
|
+
if (canStoreEventsInLocalStorage) {
|
|
177
|
+
const localStorageItems = JSON.parse(
|
|
178
|
+
window.localStorage.getItem('ophan_follow'),
|
|
179
|
+
);
|
|
180
|
+
if (localStorageItems != null) {
|
|
181
|
+
for (const key in localStorageItems) {
|
|
182
|
+
if (localStorageItems.hasOwnProperty(key)) {
|
|
183
|
+
event[key] = localStorageItems[key];
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
window.localStorage.removeItem('ophan_follow');
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Trims component names to a maximum length to ensure they are URL safe.
|
|
193
|
+
* If a component name exceeds the maximum length, it is truncated and appended with an ellipsis.
|
|
194
|
+
* @param {string[]} componentNames - An array of component names.
|
|
195
|
+
* @returns {string[]} An array of trimmed component names.
|
|
196
|
+
*/
|
|
197
|
+
const trimComponentNamesToUrlSafeLength = (componentNames) => {
|
|
198
|
+
return componentNames.map((componentName) =>
|
|
199
|
+
componentName.length > MaximumComponentNameLength
|
|
200
|
+
? componentName.substring(0, MaximumComponentNameLength).concat('…')
|
|
201
|
+
: componentName,
|
|
202
|
+
);
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Appends data about rendered components to an event object.
|
|
207
|
+
* Extracts component names from elements with a 'data-component' attribute, trims them for URL safety, ensures uniqueness, and adds them to the event.
|
|
208
|
+
* @param {Object} event - The event object to which component data will be appended.
|
|
209
|
+
*/
|
|
210
|
+
const appendComponentDataToEvent = (event) => {
|
|
211
|
+
const componentElements = document.querySelectorAll('[data-component]');
|
|
212
|
+
const componentNames = Array.prototype.slice.call(componentElements).map((el) =>
|
|
213
|
+
el.getAttribute('data-component')
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
if (componentNames.length > 0) {
|
|
217
|
+
const trimmedComponentNames =
|
|
218
|
+
trimComponentNamesToUrlSafeLength(componentNames);
|
|
219
|
+
// uniquify
|
|
220
|
+
const uniqueComponents = new Set(trimmedComponentNames);
|
|
221
|
+
event.renderedComponents = [...uniqueComponents];
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
storeDataToSendOnNextEvent = function (newData) {
|
|
227
|
+
let existingData, key, value;
|
|
228
|
+
if (canStoreEventsInLocalStorage) {
|
|
229
|
+
existingData =
|
|
230
|
+
JSON.parse(window.localStorage.getItem('ophan_follow')) || {};
|
|
231
|
+
for (key in newData) {
|
|
232
|
+
if (!hasProp.call(newData, key)) continue;
|
|
233
|
+
value = newData[key];
|
|
234
|
+
existingData[key] = value;
|
|
235
|
+
}
|
|
236
|
+
return window.localStorage.setItem(
|
|
237
|
+
'ophan_follow',
|
|
238
|
+
JSON.stringify(existingData),
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Determines the 'content type' based on the platform and guardian object.
|
|
245
|
+
* @param {Record<string, unknown>} event - The event object that will be updated with contentType.
|
|
246
|
+
* @param {string} platform - The current platform ('next-gen', 'embed' or other).
|
|
247
|
+
* @param {Record<string, unknown>} guardian - The guardian object.
|
|
248
|
+
*/
|
|
249
|
+
const appendContentType = (event, platform, guardian) => {
|
|
250
|
+
const contentType =
|
|
251
|
+
platform === 'next-gen' || platform === 'embed'
|
|
252
|
+
? guardian?.config?.page?.contentType
|
|
253
|
+
: guardian?.page?.contentTypes;
|
|
254
|
+
|
|
255
|
+
if (contentType) {
|
|
256
|
+
event.contentType = contentType.toLowerCase();
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
export default {
|
|
261
|
+
init: init,
|
|
262
|
+
storeDataToSendOnNextEvent: storeDataToSendOnNextEvent,
|
|
263
|
+
onLoadCapture: onLoadCapture,
|
|
264
|
+
servingPlatform: function () {
|
|
265
|
+
return platform;
|
|
266
|
+
},
|
|
267
|
+
viewId: transmit.viewId,
|
|
268
|
+
sendInitialEvent: sendInitialEvent,
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Exports for testing purposes.
|
|
273
|
+
*/
|
|
274
|
+
export const _testExports = {
|
|
275
|
+
appendComponentDataToEvent,
|
|
276
|
+
trimComponentNamesToUrlSafeLength,
|
|
277
|
+
getQueryParameterValue,
|
|
278
|
+
onLoadCaptures,
|
|
279
|
+
onLoadCapture,
|
|
280
|
+
processCaptures,
|
|
281
|
+
appendContentType,
|
|
282
|
+
};
|
package/assets/embed.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Generated by CoffeeScript 2.7.0
|
|
2
|
+
var heatmapFired, init;
|
|
3
|
+
|
|
4
|
+
heatmapFired = false;
|
|
5
|
+
|
|
6
|
+
init = function () {
|
|
7
|
+
var addHeatmap;
|
|
8
|
+
addHeatmap = function () {
|
|
9
|
+
var heatmapParam;
|
|
10
|
+
if (
|
|
11
|
+
typeof localStorage !== 'undefined' &&
|
|
12
|
+
localStorage !== null &&
|
|
13
|
+
!heatmapFired
|
|
14
|
+
) {
|
|
15
|
+
heatmapFired = true;
|
|
16
|
+
heatmapParam = window.location.search.replace(
|
|
17
|
+
/^(?:.*[&\?]heatmap(?:\=([^&]*))?)?.*$/,
|
|
18
|
+
'$1',
|
|
19
|
+
);
|
|
20
|
+
if (heatmapParam === 'true' || heatmapParam === 'false') {
|
|
21
|
+
localStorage['ophan_heatmap'] = heatmapParam;
|
|
22
|
+
}
|
|
23
|
+
if (localStorage['ophan_heatmap'] === 'true' || heatmapParam === 'show') {
|
|
24
|
+
return (document.body.appendChild(
|
|
25
|
+
document.createElement('script'),
|
|
26
|
+
).src = '//dashboard.ophan.co.uk/assets/js/heatmap-bookmarklet.js');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
if (document.readyState === 'complete') {
|
|
31
|
+
return addHeatmap();
|
|
32
|
+
} else {
|
|
33
|
+
return typeof window.addEventListener === 'function'
|
|
34
|
+
? window.addEventListener(
|
|
35
|
+
'load',
|
|
36
|
+
function () {
|
|
37
|
+
return addHeatmap();
|
|
38
|
+
},
|
|
39
|
+
false,
|
|
40
|
+
)
|
|
41
|
+
: void 0;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export default {
|
|
46
|
+
init: init,
|
|
47
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Generated by CoffeeScript 2.7.0
|
|
2
|
+
var reportStatus;
|
|
3
|
+
|
|
4
|
+
import core from './core.js';
|
|
5
|
+
|
|
6
|
+
import './transmit.js';
|
|
7
|
+
|
|
8
|
+
import './click-path-capture.js';
|
|
9
|
+
|
|
10
|
+
import './perf.js';
|
|
11
|
+
|
|
12
|
+
import './campaign.js';
|
|
13
|
+
|
|
14
|
+
reportStatus = function (platform, status) {
|
|
15
|
+
return core.init(platform, status);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default {
|
|
19
|
+
reportStatus: reportStatus,
|
|
20
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Generated by CoffeeScript 2.7.0
|
|
2
|
+
var componentEventIsValid,
|
|
3
|
+
handleIframeMessage,
|
|
4
|
+
recordIframeClickEvent,
|
|
5
|
+
recordIframeComponentEvent,
|
|
6
|
+
retrieveOriginDomain,
|
|
7
|
+
validIframeDomains;
|
|
8
|
+
|
|
9
|
+
import clickCapture from './click-path-capture.js';
|
|
10
|
+
|
|
11
|
+
validIframeDomains = [
|
|
12
|
+
'.theguardian.com',
|
|
13
|
+
'.dev-theguardian.com',
|
|
14
|
+
'.thegulocal.com', // NB - leading dot is essential here to avoid matching on non-Guardian-owned domains
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
handleIframeMessage = function (messageEvent) {
|
|
18
|
+
var eventObject, iFrame, originDomain;
|
|
19
|
+
originDomain = retrieveOriginDomain(messageEvent.origin);
|
|
20
|
+
if (
|
|
21
|
+
originDomain &&
|
|
22
|
+
validIframeDomains.some((domain) => {
|
|
23
|
+
return originDomain.endsWith(domain);
|
|
24
|
+
})
|
|
25
|
+
) {
|
|
26
|
+
if (messageEvent.data.type === 'ophan-iframe-click-event') {
|
|
27
|
+
eventObject = messageEvent.data.value;
|
|
28
|
+
iFrame = document.getElementById(messageEvent.data.iframeId);
|
|
29
|
+
recordIframeClickEvent(iFrame, eventObject);
|
|
30
|
+
} else if (messageEvent.data.type === 'ophan-iframe-component-event') {
|
|
31
|
+
eventObject = messageEvent.data.value;
|
|
32
|
+
recordIframeComponentEvent(eventObject);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
retrieveOriginDomain = function (eventOrigin) {
|
|
38
|
+
var e, originURL;
|
|
39
|
+
try {
|
|
40
|
+
originURL = new URL(eventOrigin);
|
|
41
|
+
return originURL.host;
|
|
42
|
+
} catch (error) {
|
|
43
|
+
e = error;
|
|
44
|
+
if (e instanceof TypeError) {
|
|
45
|
+
// We failed to parse origin as an URL, we should ignore the event
|
|
46
|
+
return null;
|
|
47
|
+
} else {
|
|
48
|
+
throw e;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
recordIframeClickEvent = function (iFrame, clickEvent) {
|
|
54
|
+
if (iFrame) {
|
|
55
|
+
clickEvent.clickLinkNames =
|
|
56
|
+
clickCapture.getDataLinkNames(iFrame, clickEvent.clickLinkNames) ||
|
|
57
|
+
clickEvent.clickLinkNames;
|
|
58
|
+
}
|
|
59
|
+
window.guardian.ophan.record(clickEvent);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
componentEventIsValid = function (eventObject) {
|
|
63
|
+
if (!eventObject || typeof eventObject !== 'object') {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
if (
|
|
67
|
+
!eventObject.componentEvent ||
|
|
68
|
+
typeof eventObject.componentEvent !== 'object'
|
|
69
|
+
) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
return true;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
recordIframeComponentEvent = function (eventObject) {
|
|
76
|
+
if (!componentEventIsValid(eventObject)) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
window.guardian.ophan.record(eventObject);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
window.addEventListener('message', handleIframeMessage, false);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Generated by CoffeeScript 2.7.0
|
|
2
|
+
var ref;
|
|
3
|
+
|
|
4
|
+
import core from './core.js';
|
|
5
|
+
|
|
6
|
+
import transmit from './transmit.js';
|
|
7
|
+
|
|
8
|
+
import attention from './attention.js';
|
|
9
|
+
|
|
10
|
+
import './click-path-capture.js';
|
|
11
|
+
|
|
12
|
+
if (((ref = window.guardian) != null ? ref.ophan : void 0) != null) {
|
|
13
|
+
window.guardian.ophan;
|
|
14
|
+
} else {
|
|
15
|
+
core.init('embed');
|
|
16
|
+
if (window.guardian == null) {
|
|
17
|
+
window.guardian = {};
|
|
18
|
+
}
|
|
19
|
+
window.guardian.ophan = {
|
|
20
|
+
setEventEmitter: attention.setEventEmitter,
|
|
21
|
+
trackComponentAttention: attention.initComponent,
|
|
22
|
+
record: transmit.sendMore,
|
|
23
|
+
viewId: transmit.viewId,
|
|
24
|
+
};
|
|
25
|
+
}
|
package/assets/jobs.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Generated by CoffeeScript 2.7.0
|
|
2
|
+
var exports, sendInitialEvent;
|
|
3
|
+
|
|
4
|
+
import core from './core.js';
|
|
5
|
+
|
|
6
|
+
import transmit from './transmit.js';
|
|
7
|
+
|
|
8
|
+
import attention from './attention.js';
|
|
9
|
+
|
|
10
|
+
import visibility from './visibility.js';
|
|
11
|
+
|
|
12
|
+
import './click-path-capture.js';
|
|
13
|
+
|
|
14
|
+
import './perf.js';
|
|
15
|
+
|
|
16
|
+
import './campaign.js';
|
|
17
|
+
|
|
18
|
+
core.init('manage-my-account');
|
|
19
|
+
|
|
20
|
+
if (window.addEventListener != null) {
|
|
21
|
+
attention.init(visibility);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
sendInitialEvent = function (
|
|
25
|
+
url = location.href,
|
|
26
|
+
referrer = window.document.referrer,
|
|
27
|
+
) {
|
|
28
|
+
var e;
|
|
29
|
+
try {
|
|
30
|
+
transmit.bumpViewId();
|
|
31
|
+
return core.sendInitialEvent(null, url, referrer);
|
|
32
|
+
} catch (error) {
|
|
33
|
+
e = error;
|
|
34
|
+
return console.log(e);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
exports = {
|
|
39
|
+
sendInitialEvent: sendInitialEvent,
|
|
40
|
+
record: transmit.sendMore,
|
|
41
|
+
viewId: transmit.viewId,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
if (window.guardian == null) {
|
|
45
|
+
window.guardian = {};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
window.guardian.ophan = exports;
|
|
49
|
+
|
|
50
|
+
export default exports;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Generated by CoffeeScript 2.7.0
|
|
2
|
+
import core from './core.js';
|
|
3
|
+
|
|
4
|
+
import transmit from './transmit.js';
|
|
5
|
+
|
|
6
|
+
import attention from './attention.js';
|
|
7
|
+
|
|
8
|
+
import visibility from './visibility.js';
|
|
9
|
+
|
|
10
|
+
import './click-path-capture.js';
|
|
11
|
+
|
|
12
|
+
import './perf.js';
|
|
13
|
+
|
|
14
|
+
import './campaign.js';
|
|
15
|
+
|
|
16
|
+
core.init('membership');
|
|
17
|
+
|
|
18
|
+
if (window.addEventListener != null) {
|
|
19
|
+
attention.init(visibility);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default {
|
|
23
|
+
record: transmit.sendMore,
|
|
24
|
+
viewId: transmit.viewId,
|
|
25
|
+
};
|
package/assets/ng.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Generated by CoffeeScript 2.7.0
|
|
2
|
+
var ng, ref;
|
|
3
|
+
|
|
4
|
+
import core from './core.js';
|
|
5
|
+
|
|
6
|
+
import transmit from './transmit.js';
|
|
7
|
+
|
|
8
|
+
import attention from './attention.js';
|
|
9
|
+
|
|
10
|
+
import visibility from './visibility.js';
|
|
11
|
+
|
|
12
|
+
import privatebrowsing from './privatebrowsing.js';
|
|
13
|
+
|
|
14
|
+
import heatmap from './heatmap.js';
|
|
15
|
+
|
|
16
|
+
import './click-path-capture.js';
|
|
17
|
+
|
|
18
|
+
import './perf.js';
|
|
19
|
+
|
|
20
|
+
import './iframe-tracking.js';
|
|
21
|
+
|
|
22
|
+
// TODO:
|
|
23
|
+
// pageViewId is used for Google Analytics on frontend, membership and some of the jobs sites.
|
|
24
|
+
// If we can migrate these to use viewId instead then pageViewId can safely be removed
|
|
25
|
+
ng =
|
|
26
|
+
((ref = window.guardian) != null ? ref.ophan : void 0) != null
|
|
27
|
+
? window.guardian.ophan
|
|
28
|
+
: (core.init('next-gen'),
|
|
29
|
+
privatebrowsing.init(),
|
|
30
|
+
heatmap.init(),
|
|
31
|
+
window.addEventListener != null ? attention.init(visibility) : void 0,
|
|
32
|
+
window.guardian != null ? window.guardian : (window.guardian = {}),
|
|
33
|
+
(window.guardian.ophan = {
|
|
34
|
+
setEventEmitter: attention.setEventEmitter,
|
|
35
|
+
trackComponentAttention: attention.initComponent,
|
|
36
|
+
record: transmit.sendMore,
|
|
37
|
+
viewId: transmit.viewId,
|
|
38
|
+
pageViewId: transmit.viewId,
|
|
39
|
+
}));
|
|
40
|
+
|
|
41
|
+
export default ng;
|
package/assets/perf.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Generated by CoffeeScript 2.7.0
|
|
2
|
+
var perf, sendTimingData;
|
|
3
|
+
|
|
4
|
+
import core from './core.js';
|
|
5
|
+
|
|
6
|
+
perf =
|
|
7
|
+
window.performance ||
|
|
8
|
+
window.msPerformance ||
|
|
9
|
+
window.webkitPerformance ||
|
|
10
|
+
window.mozPerformance;
|
|
11
|
+
|
|
12
|
+
sendTimingData = function () {
|
|
13
|
+
var t;
|
|
14
|
+
t = perf != null ? perf.timing : void 0;
|
|
15
|
+
if (t != null) {
|
|
16
|
+
return {
|
|
17
|
+
performance: {
|
|
18
|
+
// Time required for domain lookup.
|
|
19
|
+
dns: t.domainLookupEnd - t.domainLookupStart,
|
|
20
|
+
// Time to establish a connection to server.
|
|
21
|
+
connection: t.connectEnd - t.connectStart,
|
|
22
|
+
// From connection established to first byte of data.
|
|
23
|
+
firstByte: t.responseStart - t.connectEnd,
|
|
24
|
+
// First byte to last byte, or closed, including if from cache.
|
|
25
|
+
lastByte: t.responseEnd - t.responseStart,
|
|
26
|
+
// From last byte of doc to start of domContentLoaded
|
|
27
|
+
domContentLoadedEvent: t.domContentLoadedEventStart - t.responseEnd,
|
|
28
|
+
// domcontentLoaded to start of load event.
|
|
29
|
+
loadEvent: t.loadEventStart - t.domContentLoadedEventStart,
|
|
30
|
+
// click, back/forward, etc...
|
|
31
|
+
navType: perf.navigation.type,
|
|
32
|
+
// No. of redirects on current domain.
|
|
33
|
+
redirectCount: perf.navigation.redirectCount,
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
} else {
|
|
37
|
+
return {};
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
core.onLoadCapture(sendTimingData);
|
|
42
|
+
|
|
43
|
+
export default perf;
|