@guardian/ophan-tracker-js 2.0.3
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/build/adblock-detection.js +24 -0
- package/build/attention.js +149 -0
- package/build/campaign.js +30 -0
- package/build/click-path-capture.js +81 -0
- package/build/components.js +167 -0
- package/build/contribution.js +25 -0
- package/build/core.js +234 -0
- package/build/embed.js +11 -0
- package/build/fb-instant.js +10 -0
- package/build/heatmap.js +32 -0
- package/build/holidays.js +11 -0
- package/build/http-status.js +20 -0
- package/build/iframe-tracking.js +68 -0
- package/build/interactive.js +25 -0
- package/build/jobs-courses.js +11 -0
- package/build/jobs.js +11 -0
- package/build/manage-my-account.js +47 -0
- package/build/membership.js +25 -0
- package/build/ng.js +33 -0
- package/build/perf.js +39 -0
- package/build/privatebrowsing.js +71 -0
- package/build/r2.js +24 -0
- package/build/smart-news.js +19 -0
- package/build/support.js +41 -0
- package/build/transmit.js +107 -0
- package/build/vendor/adBlockDetectionLib.js +367 -0
- package/build/visibility.js +7 -0
- package/build/witness.js +11 -0
- package/package.json +26 -0
- package/readme.md +95 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Generated by CoffeeScript 2.7.0
|
|
2
|
+
import abd from "./vendor/adBlockDetectionLib.js";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
run: function() {
|
|
6
|
+
return new Promise(function(resolve, reject) {
|
|
7
|
+
var e;
|
|
8
|
+
if (abd.init) {
|
|
9
|
+
try {
|
|
10
|
+
return abd.init({
|
|
11
|
+
complete: function(v) {
|
|
12
|
+
return resolve(v);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
} catch (error) {
|
|
16
|
+
e = error;
|
|
17
|
+
return reject(e);
|
|
18
|
+
}
|
|
19
|
+
} else {
|
|
20
|
+
return reject(new Error("Failed to initialise adblock detection"));
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
};
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// Generated by CoffeeScript 2.7.0
|
|
2
|
+
var ATTENTIONDECAY, EVENTS, REPORTINGINTERVAL, cancelDecayTimer, decayTimerId, incrementTotalAttentionTimeByUnrecordedAmount, initAttention, initComponent, makeActive, makeInactive, reportedTotalAttentionMs, reporter, setEventEmitter, totalAttentionMs, unrecordedAttentionStarted, videoPlaying;
|
|
3
|
+
|
|
4
|
+
import transmit from "./transmit.js";
|
|
5
|
+
|
|
6
|
+
import components from "./components.js";
|
|
7
|
+
|
|
8
|
+
// The upworthy definition of attention minutes, from
|
|
9
|
+
// http://upworthy.github.io/2014/06/implementing-attention-minutes-part-1/ :
|
|
10
|
+
|
|
11
|
+
// "We consider the page to have the user’s attention if
|
|
12
|
+
// 1. some activity is happening on the page. For our purposes this means:
|
|
13
|
+
// 1. the page currently has focus
|
|
14
|
+
// 2. and the user has interacted with the page within a certain timeout
|
|
15
|
+
// 2. or a video is playing on the page
|
|
16
|
+
// Attention Minutes, then, are the total number of minutes that a user has spent on
|
|
17
|
+
// a page where the above conditions have held true."
|
|
18
|
+
|
|
19
|
+
// our definition of "within a certain timeout" above:
|
|
20
|
+
ATTENTIONDECAY = 5000;
|
|
21
|
+
|
|
22
|
+
// our definition of "the user has interacted with the page"
|
|
23
|
+
EVENTS = ['focus', 'click', 'scroll', 'mousemove', 'touchstart', 'touchend', 'touchcancel', 'touchleave', 'touchmove', 'keyup', 'keydown'];
|
|
24
|
+
|
|
25
|
+
REPORTINGINTERVAL = 10000;
|
|
26
|
+
|
|
27
|
+
// total attention time so far on this page
|
|
28
|
+
totalAttentionMs = 0;
|
|
29
|
+
|
|
30
|
+
// the time elapsed since the time origin (https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp#the_time_origin)
|
|
31
|
+
// when the most recent period of attention (that is, attention
|
|
32
|
+
// which we haven't yet added to totalAttentionMs) began.
|
|
33
|
+
// null if we don't have attention.
|
|
34
|
+
unrecordedAttentionStarted = null;
|
|
35
|
+
|
|
36
|
+
// the attention time we last reported to ophan
|
|
37
|
+
reportedTotalAttentionMs = null; // setting null here forces a first report of attention time, even if it's only 0ms
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
// the decay timer if we've set one
|
|
41
|
+
decayTimerId = null;
|
|
42
|
+
|
|
43
|
+
// is video currently playing?
|
|
44
|
+
videoPlaying = false;
|
|
45
|
+
|
|
46
|
+
cancelDecayTimer = function() {
|
|
47
|
+
if (decayTimerId != null) {
|
|
48
|
+
window.clearTimeout(decayTimerId);
|
|
49
|
+
}
|
|
50
|
+
return decayTimerId = null;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
makeActive = function() {
|
|
54
|
+
// mark when the latest period of attention began,
|
|
55
|
+
// if we're not already in an attention period
|
|
56
|
+
if (unrecordedAttentionStarted == null) {
|
|
57
|
+
unrecordedAttentionStarted = performance.now();
|
|
58
|
+
}
|
|
59
|
+
components.startMonitoring();
|
|
60
|
+
// start decay timer
|
|
61
|
+
cancelDecayTimer();
|
|
62
|
+
return decayTimerId = window.setTimeout((function() {
|
|
63
|
+
if (!videoPlaying) {
|
|
64
|
+
return makeInactive();
|
|
65
|
+
}
|
|
66
|
+
}), ATTENTIONDECAY);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
incrementTotalAttentionTimeByUnrecordedAmount = function() {
|
|
70
|
+
var now, unrecordedMs;
|
|
71
|
+
if (unrecordedAttentionStarted != null) {
|
|
72
|
+
now = performance.now();
|
|
73
|
+
// the Math.min here is to deal with occasions where we don't get an event indicating that the user
|
|
74
|
+
// has become inactive - this can happen e.g. due to users suspending their phone. Never send
|
|
75
|
+
// crazy big values!
|
|
76
|
+
unrecordedMs = Math.min(now - unrecordedAttentionStarted, REPORTINGINTERVAL);
|
|
77
|
+
totalAttentionMs += unrecordedMs;
|
|
78
|
+
return unrecordedAttentionStarted = now;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
makeInactive = function() {
|
|
83
|
+
cancelDecayTimer();
|
|
84
|
+
components.stopMonitoring();
|
|
85
|
+
incrementTotalAttentionTimeByUnrecordedAmount();
|
|
86
|
+
return unrecordedAttentionStarted = null;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
reporter = function() {
|
|
90
|
+
var componentAttentionTimes, report;
|
|
91
|
+
incrementTotalAttentionTimeByUnrecordedAmount();
|
|
92
|
+
if (totalAttentionMs !== reportedTotalAttentionMs) {
|
|
93
|
+
report = {
|
|
94
|
+
attentionMs: Math.round(totalAttentionMs)
|
|
95
|
+
};
|
|
96
|
+
componentAttentionTimes = components.getAttentionTimes();
|
|
97
|
+
if (Object.keys(componentAttentionTimes).length) {
|
|
98
|
+
report.componentAttentionMs = componentAttentionTimes;
|
|
99
|
+
}
|
|
100
|
+
transmit.sendMore(report);
|
|
101
|
+
return reportedTotalAttentionMs = totalAttentionMs;
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
initComponent = function(name, el, visibilityThreshold = 0.5) {
|
|
106
|
+
return components.registerComponent(name, el, visibilityThreshold, REPORTINGINTERVAL);
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
initAttention = function(visibility) {
|
|
110
|
+
var event, i, len;
|
|
111
|
+
for (i = 0, len = EVENTS.length; i < len; i++) {
|
|
112
|
+
event = EVENTS[i];
|
|
113
|
+
// user interaction tracking
|
|
114
|
+
window.addEventListener(event, makeActive);
|
|
115
|
+
}
|
|
116
|
+
// focus tracking
|
|
117
|
+
document.addEventListener(visibility.changeEvent, (function() {
|
|
118
|
+
if (visibility.state() === "visible") {
|
|
119
|
+
return makeActive();
|
|
120
|
+
} else {
|
|
121
|
+
return makeInactive();
|
|
122
|
+
}
|
|
123
|
+
}), false);
|
|
124
|
+
// video tracking
|
|
125
|
+
document.addEventListener('videoPlaying', function() {
|
|
126
|
+
videoPlaying = true;
|
|
127
|
+
return makeActive();
|
|
128
|
+
});
|
|
129
|
+
document.addEventListener('videoEnded', function() {
|
|
130
|
+
videoPlaying = false;
|
|
131
|
+
return makeInactive();
|
|
132
|
+
});
|
|
133
|
+
document.addEventListener('videoPause', function() {
|
|
134
|
+
videoPlaying = false;
|
|
135
|
+
return makeInactive();
|
|
136
|
+
});
|
|
137
|
+
window.setTimeout(reporter, 100);
|
|
138
|
+
return window.setInterval(reporter, REPORTINGINTERVAL);
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
setEventEmitter = function(emitter) {
|
|
142
|
+
return components.setEventEmitter(emitter);
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
export default {
|
|
146
|
+
init: initAttention,
|
|
147
|
+
initComponent: initComponent,
|
|
148
|
+
setEventEmitter: setEventEmitter
|
|
149
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Generated by CoffeeScript 2.7.0
|
|
2
|
+
var ref, ref1, start;
|
|
3
|
+
|
|
4
|
+
import transmit from "./transmit.js";
|
|
5
|
+
|
|
6
|
+
import perf from "./perf.js";
|
|
7
|
+
|
|
8
|
+
start = (ref = perf != null ? (ref1 = perf.timing) != null ? ref1.domComplete : void 0 : void 0) != null ? ref : performance.now();
|
|
9
|
+
|
|
10
|
+
// DFP ads
|
|
11
|
+
if (typeof googletag !== "undefined" && googletag !== null) {
|
|
12
|
+
googletag.cmd.push(function() {
|
|
13
|
+
return googletag.pubads().addEventListener('slotRenderEnded', function(event) {
|
|
14
|
+
var slotId;
|
|
15
|
+
slotId = event.slot.getSlotId().getDomId();
|
|
16
|
+
return transmit.sendMore({
|
|
17
|
+
"ads": [
|
|
18
|
+
{
|
|
19
|
+
slot: slotId,
|
|
20
|
+
campaignId: event.isEmpty ? "__empty__" : event.lineItemId,
|
|
21
|
+
creativeId: event.creativeId,
|
|
22
|
+
// overall time to render an ad
|
|
23
|
+
timeToRenderEnded: Math.round(performance.now() - start),
|
|
24
|
+
adServer: "DFP"
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// Generated by CoffeeScript 2.7.0
|
|
2
|
+
var getContainingComponent, getDataLinkNames, validAncestorAnchorElement;
|
|
3
|
+
|
|
4
|
+
import ophan from "./core.js";
|
|
5
|
+
|
|
6
|
+
import transmit from "./transmit.js";
|
|
7
|
+
|
|
8
|
+
validAncestorAnchorElement = function(el) {
|
|
9
|
+
var elementType, ref;
|
|
10
|
+
elementType = el != null ? (ref = el.nodeName) != null ? ref.toLowerCase() : void 0 : void 0;
|
|
11
|
+
if (elementType === "a") {
|
|
12
|
+
return el;
|
|
13
|
+
} else if ((elementType == null) || elementType === "body") {
|
|
14
|
+
return null;
|
|
15
|
+
} else {
|
|
16
|
+
return validAncestorAnchorElement(el.parentNode);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
getContainingComponent = function(el) {
|
|
21
|
+
var elementType, ref;
|
|
22
|
+
elementType = el != null ? (ref = el.nodeName) != null ? ref.toLowerCase() : void 0 : void 0;
|
|
23
|
+
if ((elementType == null) || elementType === "body") {
|
|
24
|
+
return null;
|
|
25
|
+
} else {
|
|
26
|
+
return (typeof el.getAttribute === "function" ? el.getAttribute("data-component") : void 0) || getContainingComponent(el.parentNode);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
getDataLinkNames = function(el, dataLinkNames = []) {
|
|
31
|
+
var isBody, isDocument, walkTree;
|
|
32
|
+
isBody = function(elem) {
|
|
33
|
+
var ref;
|
|
34
|
+
return (elem != null ? (ref = elem.nodeName) != null ? ref.toLowerCase() : void 0 : void 0) === document.body.nodeName.toLowerCase();
|
|
35
|
+
};
|
|
36
|
+
isDocument = function(elem) {
|
|
37
|
+
return elem === document;
|
|
38
|
+
};
|
|
39
|
+
walkTree = function(elem, dataLinkNames) {
|
|
40
|
+
var dataLinkName;
|
|
41
|
+
if ((elem != null) && !isBody(elem) && !isDocument(elem)) {
|
|
42
|
+
dataLinkName = elem.getAttribute("data-link-name");
|
|
43
|
+
if (dataLinkName != null) {
|
|
44
|
+
dataLinkNames.push(dataLinkName);
|
|
45
|
+
}
|
|
46
|
+
return walkTree(elem.parentNode, dataLinkNames);
|
|
47
|
+
} else {
|
|
48
|
+
return dataLinkNames;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
return walkTree(el, dataLinkNames.slice());
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
if (typeof document.addEventListener === "function") {
|
|
55
|
+
document.addEventListener("click", function(e) {
|
|
56
|
+
var anchorTarget, info;
|
|
57
|
+
anchorTarget = validAncestorAnchorElement(e.target);
|
|
58
|
+
info = {
|
|
59
|
+
from: [location.protocol, "//", location.host, location.pathname].join(""),
|
|
60
|
+
to: anchorTarget ? anchorTarget.href : void 0,
|
|
61
|
+
referringComponent: getContainingComponent(e.target),
|
|
62
|
+
referringDataLinkNames: getDataLinkNames(e.target),
|
|
63
|
+
refPlatform: ophan.servingPlatform(),
|
|
64
|
+
refViewId: ophan.viewId
|
|
65
|
+
};
|
|
66
|
+
if (info.referringDataLinkNames != null) {
|
|
67
|
+
transmit.sendMore({
|
|
68
|
+
clickComponent: info.referringComponent,
|
|
69
|
+
clickLinkNames: info.referringDataLinkNames
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
if (anchorTarget != null) {
|
|
73
|
+
// then we may be about to navigate away from this page, so store to send on next request
|
|
74
|
+
return ophan.storeDataToSendOnNextEvent(info);
|
|
75
|
+
}
|
|
76
|
+
}, false);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export default {
|
|
80
|
+
getDataLinkNames: getDataLinkNames
|
|
81
|
+
};
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
// Generated by CoffeeScript 2.7.0
|
|
2
|
+
var Component, components, eventEmitter;
|
|
3
|
+
|
|
4
|
+
components = [];
|
|
5
|
+
|
|
6
|
+
// theguardian.com uses a custom scroll event for performance reasons.
|
|
7
|
+
// We pass in the event emitter so that we can listen to this custom scroll event.
|
|
8
|
+
// If not on theguardian.com, we default to the native scroll event
|
|
9
|
+
eventEmitter = null;
|
|
10
|
+
|
|
11
|
+
// Tracks attention time of elements on the page with data-component attributes.
|
|
12
|
+
// This should always be less than or equal to the page attention time.
|
|
13
|
+
// If the page does not have attention, no component has attention.
|
|
14
|
+
// If the page does have attention, a given component *may* also have
|
|
15
|
+
// attention, if it is within the viewport and not hidden.
|
|
16
|
+
Component = class Component {
|
|
17
|
+
constructor(name1, element, visibilityThreshold1, reportingInterval1) {
|
|
18
|
+
this.name = name1;
|
|
19
|
+
this.element = element;
|
|
20
|
+
this.visibilityThreshold = visibilityThreshold1;
|
|
21
|
+
this.reportingInterval = reportingInterval1;
|
|
22
|
+
this.visible = false;
|
|
23
|
+
// total attention time so far for this element
|
|
24
|
+
this.totalAttentionMs = 0;
|
|
25
|
+
// the time elapsed since the time origin (https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp#the_time_origin)
|
|
26
|
+
// when the most recent period of attention (that is, attention
|
|
27
|
+
// which we haven't yet added to totalAttentionMs) began.
|
|
28
|
+
// null if we don't have attention.
|
|
29
|
+
this.unrecordedAttentionStarted = null;
|
|
30
|
+
// the attention time when getAttentionTime() was last called
|
|
31
|
+
this.reportedTotalAttentionMs = 0;
|
|
32
|
+
this.usingEmitter = false;
|
|
33
|
+
this.visCheck = this.checkVisibility.bind(this);
|
|
34
|
+
if (eventEmitter != null) {
|
|
35
|
+
this.usingEmitter = true;
|
|
36
|
+
eventEmitter.on('window:throttledScroll', this.visCheck);
|
|
37
|
+
} else {
|
|
38
|
+
window.addEventListener('scroll', this.visCheck);
|
|
39
|
+
}
|
|
40
|
+
window.addEventListener('resize', this.visCheck);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
isVisible(threshold = 1) {
|
|
44
|
+
var box, height, width, windowHeight, windowWidth;
|
|
45
|
+
if (!this.element.offsetParent) {
|
|
46
|
+
// exclude hidden elements
|
|
47
|
+
// will also exclude position: fixed elements but we don't care about these
|
|
48
|
+
// (because their attention time would always be the same as the whole page)
|
|
49
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetParent
|
|
50
|
+
return false;
|
|
51
|
+
} else {
|
|
52
|
+
box = this.element.getBoundingClientRect();
|
|
53
|
+
width = box.right - box.left;
|
|
54
|
+
height = box.bottom - box.top;
|
|
55
|
+
windowHeight = window.innerHeight || document.documentElement.clientHeight;
|
|
56
|
+
windowWidth = window.innerWidth || document.documentElement.clientWidth;
|
|
57
|
+
return box.left >= -(width * (1 - threshold)) && box.top >= -(height * (1 - threshold)) && box.right <= windowWidth + (width * (1 - threshold)) && box.bottom <= windowHeight + (height * (1 - threshold));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
visibilityHasChanged() {
|
|
62
|
+
var wasVisible;
|
|
63
|
+
wasVisible = this.visible;
|
|
64
|
+
this.visible = this.isVisible(this.visibilityThreshold);
|
|
65
|
+
return wasVisible !== this.visible;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
rebindToEventEmitter() {
|
|
69
|
+
if (!this.usingEmitter && (eventEmitter != null)) {
|
|
70
|
+
window.removeEventListener('scroll', this.visCheck);
|
|
71
|
+
this.usingEmitter = true;
|
|
72
|
+
return eventEmitter.on('window:throttledScroll', this.visCheck);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
checkVisibility() {
|
|
77
|
+
this.rebindToEventEmitter();
|
|
78
|
+
if (this.visibilityHasChanged()) {
|
|
79
|
+
if (this.visible) {
|
|
80
|
+
return this.makeActive();
|
|
81
|
+
} else {
|
|
82
|
+
return this.makeInactive();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
makeActive() {
|
|
88
|
+
// mark when the latest period of attention began,
|
|
89
|
+
// if we're not already in an attention period
|
|
90
|
+
return this.unrecordedAttentionStarted != null ? this.unrecordedAttentionStarted : this.unrecordedAttentionStarted = performance.now();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
makeInactive() {
|
|
94
|
+
this.incrementTotalAttentionTimeByUnrecordedAmount();
|
|
95
|
+
return this.unrecordedAttentionStarted = null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
hadAttentionSinceLastGet() {
|
|
99
|
+
this.incrementTotalAttentionTimeByUnrecordedAmount();
|
|
100
|
+
return this.totalAttentionMs !== this.reportedTotalAttentionMs;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
getAttentionTime() {
|
|
104
|
+
this.incrementTotalAttentionTimeByUnrecordedAmount();
|
|
105
|
+
this.reportedTotalAttentionMs = this.totalAttentionMs;
|
|
106
|
+
return this.totalAttentionMs;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
incrementTotalAttentionTimeByUnrecordedAmount() {
|
|
110
|
+
var now, unrecordedMs;
|
|
111
|
+
if (this.unrecordedAttentionStarted != null) {
|
|
112
|
+
now = performance.now();
|
|
113
|
+
// the Math.min here is to deal with occasions where we don't get an event indicating that the user
|
|
114
|
+
// has become inactive - this can happen e.g. due to users suspending their phone. Never send
|
|
115
|
+
// crazy big values!
|
|
116
|
+
unrecordedMs = Math.min(now - this.unrecordedAttentionStarted, this.reportingInterval);
|
|
117
|
+
this.totalAttentionMs += unrecordedMs;
|
|
118
|
+
return this.unrecordedAttentionStarted = now;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export default {
|
|
125
|
+
setEventEmitter: function(emitter) {
|
|
126
|
+
return eventEmitter = emitter;
|
|
127
|
+
},
|
|
128
|
+
startMonitoring: function() {
|
|
129
|
+
var component, i, len, results;
|
|
130
|
+
results = [];
|
|
131
|
+
for (i = 0, len = components.length; i < len; i++) {
|
|
132
|
+
component = components[i];
|
|
133
|
+
if (component.isVisible()) {
|
|
134
|
+
results.push(component.makeActive());
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return results;
|
|
138
|
+
},
|
|
139
|
+
stopMonitoring: function() {
|
|
140
|
+
var component, i, len, results;
|
|
141
|
+
results = [];
|
|
142
|
+
for (i = 0, len = components.length; i < len; i++) {
|
|
143
|
+
component = components[i];
|
|
144
|
+
results.push(component.makeInactive());
|
|
145
|
+
}
|
|
146
|
+
return results;
|
|
147
|
+
},
|
|
148
|
+
getAttentionTimes: function() {
|
|
149
|
+
var component, i, len, obj;
|
|
150
|
+
obj = {};
|
|
151
|
+
for (i = 0, len = components.length; i < len; i++) {
|
|
152
|
+
component = components[i];
|
|
153
|
+
if (component.hadAttentionSinceLastGet()) {
|
|
154
|
+
// if there are duplicate component names, only the last one survives
|
|
155
|
+
obj[component.name] = Math.round(component.getAttentionTime());
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return obj;
|
|
159
|
+
},
|
|
160
|
+
// visibilityThreshold represents the fraction of each component that must
|
|
161
|
+
// be in the viewport before it is considered visible.
|
|
162
|
+
// e.g. 0.5 means that half the height or width must be in the viewport
|
|
163
|
+
// 1 means that the entire element must be in the viewport
|
|
164
|
+
registerComponent: function(name, el, visibilityThreshold, reportingInterval) {
|
|
165
|
+
return components.push(new Component(name, el, visibilityThreshold, reportingInterval));
|
|
166
|
+
}
|
|
167
|
+
};
|
|
@@ -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("contribution");
|
|
17
|
+
|
|
18
|
+
if (window.addEventListener != null) {
|
|
19
|
+
attention.init(visibility);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default {
|
|
23
|
+
record: transmit.sendMore,
|
|
24
|
+
viewId: transmit.viewId
|
|
25
|
+
};
|