@newrelic/video-core 3.1.1 → 3.2.0-beta-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/CHANGELOG.md +7 -2
- package/README.md +15 -2
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/index.js.LICENSE.txt +1 -1
- package/dist/cjs/index.js.map +1 -0
- package/dist/esm/index.js +3 -1
- package/dist/esm/index.js.LICENSE.txt +1 -1
- package/dist/esm/index.js.map +1 -0
- package/dist/umd/nrvideo.min.js +3 -1
- package/dist/umd/nrvideo.min.js.LICENSE.txt +1 -1
- package/dist/umd/nrvideo.min.js.map +1 -0
- package/package.json +5 -5
- package/src/agent.js +6 -0
- package/src/authConfiguration.js +138 -0
- package/src/chrono.js +78 -0
- package/src/constants.js +43 -0
- package/src/core.js +100 -0
- package/src/emitter.js +81 -0
- package/src/eventAggregator.js +66 -0
- package/src/harvester.js +171 -0
- package/src/index.js +22 -0
- package/src/log.js +323 -0
- package/src/recordEvent.js +68 -0
- package/src/tracker.js +281 -0
- package/src/utils.js +101 -0
- package/src/videotracker.js +1060 -0
- package/src/videotrackerstate.js +574 -0
package/src/log.js
ADDED
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static Log class
|
|
3
|
+
*
|
|
4
|
+
* @class
|
|
5
|
+
* @static
|
|
6
|
+
*/
|
|
7
|
+
class Log {
|
|
8
|
+
/**
|
|
9
|
+
* Sends an error console log.
|
|
10
|
+
* @param {...any} [msg] Message to show
|
|
11
|
+
* @static
|
|
12
|
+
*/
|
|
13
|
+
static error(...msg) {
|
|
14
|
+
_report(msg, Log.Levels.ERROR, "darkred");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Sends a warning console log.
|
|
19
|
+
* @method Log.warn
|
|
20
|
+
* @static
|
|
21
|
+
* @param {...any} msg Message to show
|
|
22
|
+
*/
|
|
23
|
+
static warn(...msg) {
|
|
24
|
+
_report(msg, Log.Levels.WARNING, "darkorange");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Sends a notice console log.
|
|
29
|
+
* @method Log.notice
|
|
30
|
+
* @static
|
|
31
|
+
* @param {...any} msg Message to show
|
|
32
|
+
*/
|
|
33
|
+
static notice(...msg) {
|
|
34
|
+
_report([].slice.call(arguments), Log.Levels.NOTICE, "darkcyan");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Sends a debug message to console.
|
|
39
|
+
* @method Log.debug
|
|
40
|
+
* @static
|
|
41
|
+
* @param {...any} msg Message to show
|
|
42
|
+
*/
|
|
43
|
+
static debug(...msg) {
|
|
44
|
+
_report(msg, Log.Levels.DEBUG, "indigo");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* This utility method will add most of the HTML5 common event listeners to the player sent.
|
|
49
|
+
* Events will be reported as DEBUG level messages.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* // Already included events:
|
|
53
|
+
* ['canplay', 'buffering', 'waiting', 'ended', 'play', 'playing', 'pause', 'resume', 'error',
|
|
54
|
+
* 'abort', 'seek', 'seeking', 'seeked', 'stalled', 'dispose', 'loadeddata', 'loadstart',
|
|
55
|
+
* 'loadedmetadata']
|
|
56
|
+
*
|
|
57
|
+
* @method Log.debugCommonVideoEvents
|
|
58
|
+
* @static
|
|
59
|
+
* @param {object|function} o Object to attach the events.
|
|
60
|
+
* @param {array} [extraEvents]
|
|
61
|
+
* An array of extra events to watch. ie: ['timeupdate', 'progress'].
|
|
62
|
+
* If the first item is null, no common events will be added.
|
|
63
|
+
* @param {function} [report] Callback function called to report events.
|
|
64
|
+
* Default calls Log.debug()
|
|
65
|
+
*/
|
|
66
|
+
static debugCommonVideoEvents(o, extraEvents, report) {
|
|
67
|
+
try {
|
|
68
|
+
if (Log.level <= Log.Levels.DEBUG) {
|
|
69
|
+
report =
|
|
70
|
+
report ||
|
|
71
|
+
function (e) {
|
|
72
|
+
Log.debug("Event: " + e.type);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
var playerEvents = [
|
|
76
|
+
"canplay",
|
|
77
|
+
"buffering",
|
|
78
|
+
"waiting",
|
|
79
|
+
"ended",
|
|
80
|
+
"play",
|
|
81
|
+
"playing",
|
|
82
|
+
"pause",
|
|
83
|
+
"resume",
|
|
84
|
+
"error",
|
|
85
|
+
"abort",
|
|
86
|
+
"seek",
|
|
87
|
+
"seeking",
|
|
88
|
+
"seeked",
|
|
89
|
+
"stalled",
|
|
90
|
+
"dispose",
|
|
91
|
+
"loadeddata",
|
|
92
|
+
"loadstart",
|
|
93
|
+
"loadedmetadata",
|
|
94
|
+
];
|
|
95
|
+
if (extraEvents) {
|
|
96
|
+
if (extraEvents[0] === null) {
|
|
97
|
+
extraEvents.shift();
|
|
98
|
+
playerEvents = extraEvents;
|
|
99
|
+
} else {
|
|
100
|
+
playerEvents = playerEvents.concat(extraEvents);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
for (var i = 0; i < playerEvents.length; i++) {
|
|
105
|
+
if (typeof o === "function") {
|
|
106
|
+
o.call(window, playerEvents[i], report);
|
|
107
|
+
} else if (o.on) {
|
|
108
|
+
o.on(playerEvents[i], report);
|
|
109
|
+
} else if (o.addEventListener) {
|
|
110
|
+
o.addEventListener(playerEvents[i], report);
|
|
111
|
+
} else if (o.addEventHandler) {
|
|
112
|
+
o.addEventHandler(playerEvents[i], report);
|
|
113
|
+
} else {
|
|
114
|
+
Log.warn(
|
|
115
|
+
"debugCommonVideoEvents: No common listener function found for ",
|
|
116
|
+
o
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
} catch (err) {
|
|
122
|
+
Log.warn(err);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Enum for log levels
|
|
129
|
+
* @enum {integer}
|
|
130
|
+
* @static
|
|
131
|
+
* @var
|
|
132
|
+
*/
|
|
133
|
+
Log.Levels = {
|
|
134
|
+
/** No console outputs */
|
|
135
|
+
SILENT: 5,
|
|
136
|
+
/** Console will show errors */
|
|
137
|
+
ERROR: 4,
|
|
138
|
+
/** Console will show warnings */
|
|
139
|
+
WARNING: 3,
|
|
140
|
+
/** Console will show notices (ie: life-cyrcle logs) */
|
|
141
|
+
NOTICE: 2,
|
|
142
|
+
/** Console will show debug messages. */
|
|
143
|
+
DEBUG: 1,
|
|
144
|
+
/** Show all messages. */
|
|
145
|
+
ALL: 0,
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Only logs of this imporance or higher will be shown.
|
|
150
|
+
* @example Log.level = Log.Levels.ALL
|
|
151
|
+
* @default Log.Levels.ERROR
|
|
152
|
+
* @static
|
|
153
|
+
*/
|
|
154
|
+
Log.level = Log.Levels.ERROR;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* If true, logs will be outputed with colors.
|
|
158
|
+
* @default true
|
|
159
|
+
* @static
|
|
160
|
+
*/
|
|
161
|
+
Log.colorful = true;
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* If true, logs will include the time mark.
|
|
165
|
+
* @default true
|
|
166
|
+
* @static
|
|
167
|
+
*/
|
|
168
|
+
Log.includeTime = true;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Prefix included at the start of every log.
|
|
172
|
+
* @default '[New Relic]'
|
|
173
|
+
* @static
|
|
174
|
+
*/
|
|
175
|
+
Log.prefix = "[nrvideo]";
|
|
176
|
+
|
|
177
|
+
// PRIVATE MEMBERS
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Returns a console message
|
|
181
|
+
*
|
|
182
|
+
* @private
|
|
183
|
+
* @param {array} msg Message array, error object or array of messages.
|
|
184
|
+
* @param {Log.Level} [level=Log.Levels.NOTICE] Defines the level of the error sent.
|
|
185
|
+
* Only errors with higher or equal level than Log.logLevel will be displayed.
|
|
186
|
+
* @param {string} [color='darkgreen'] Color of the header
|
|
187
|
+
* @see {@link Log.level}
|
|
188
|
+
*/
|
|
189
|
+
function _report(msg, level, color) {
|
|
190
|
+
level = level || Log.Levels.NOTICE;
|
|
191
|
+
color = color || "darkcyan";
|
|
192
|
+
|
|
193
|
+
var prefix = Log.prefix;
|
|
194
|
+
if (Log.includeTime) prefix += _getCurrentTime() + " ";
|
|
195
|
+
prefix += _level2letter(level) + ":";
|
|
196
|
+
|
|
197
|
+
// Show messages in actual console if level is enought
|
|
198
|
+
if (Log.level <= level && level !== Log.Levels.SILENT) {
|
|
199
|
+
if (
|
|
200
|
+
!Log.colorful ||
|
|
201
|
+
(typeof document !== "undefined" && document.documentMode)
|
|
202
|
+
) {
|
|
203
|
+
// document.documentMode exits only in IE
|
|
204
|
+
_plainReport(msg, prefix);
|
|
205
|
+
} else {
|
|
206
|
+
// choose log method
|
|
207
|
+
var logMethod;
|
|
208
|
+
if (level === Log.Levels.ERROR && console.error) {
|
|
209
|
+
logMethod = console.error;
|
|
210
|
+
} else if (level === Log.Levels.WARNING && console.warn) {
|
|
211
|
+
logMethod = console.warn;
|
|
212
|
+
} else if (level === Log.Levels.DEBUG && console.debug) {
|
|
213
|
+
// NOTE: for some reason console.debug doesn't work on CAF Receivers.
|
|
214
|
+
if (window.cast == undefined) {
|
|
215
|
+
logMethod = console.debug;
|
|
216
|
+
} else {
|
|
217
|
+
logMethod = console.log;
|
|
218
|
+
}
|
|
219
|
+
} else {
|
|
220
|
+
logMethod = console.log;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// print message
|
|
224
|
+
prefix = "%c" + prefix;
|
|
225
|
+
msg.splice(0, 0, prefix, "color: " + color);
|
|
226
|
+
logMethod.apply(console, msg);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Returns the current time in format hh:mm:ss.mmm (with trailing 0s)
|
|
233
|
+
* @private
|
|
234
|
+
* @return {string} Current time.
|
|
235
|
+
*/
|
|
236
|
+
function _getCurrentTime() {
|
|
237
|
+
var d = new Date();
|
|
238
|
+
var hh = ("0" + d.getDate()).slice(-2);
|
|
239
|
+
var mm = ("0" + d.getMinutes()).slice(-2);
|
|
240
|
+
var ss = ("0" + d.getSeconds()).slice(-2);
|
|
241
|
+
var mmm = ("00" + d.getMilliseconds()).slice(-3);
|
|
242
|
+
return "[" + hh + ":" + mm + ":" + ss + "." + mmm + "]";
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Returns a console message without style
|
|
247
|
+
*
|
|
248
|
+
* @private
|
|
249
|
+
* @param {(string|object|array)} msg Message string, object or array of messages.
|
|
250
|
+
* @param {string} prefix Prefix of the message.
|
|
251
|
+
*/
|
|
252
|
+
function _plainReport(msg, prefix) {
|
|
253
|
+
if (msg instanceof Array) {
|
|
254
|
+
for (var m in msg) {
|
|
255
|
+
_plainReport(msg[m], prefix);
|
|
256
|
+
}
|
|
257
|
+
} else {
|
|
258
|
+
if (typeof msg === "string") {
|
|
259
|
+
console.log(prefix + " " + msg);
|
|
260
|
+
} else {
|
|
261
|
+
console.log(prefix + "↵");
|
|
262
|
+
console.log(msg);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const _letters = {
|
|
268
|
+
4: "e", // Error
|
|
269
|
+
3: "w", // Warning
|
|
270
|
+
2: "n", // Notice
|
|
271
|
+
1: "d", // Debug
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Transforms a level to a letter to identify every message.
|
|
276
|
+
*
|
|
277
|
+
* @private
|
|
278
|
+
* @param {sLog.Level} level Level of the message
|
|
279
|
+
*/
|
|
280
|
+
function _level2letter(level) {
|
|
281
|
+
return _letters[level];
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* This function is automatically executed at load.
|
|
286
|
+
* Will search inside window.location.search for attribute 'nrvideo-debug=X'.
|
|
287
|
+
* X can have one of these values, that will modify Log.Levels.
|
|
288
|
+
* 5: SILENT,
|
|
289
|
+
* 4: ERROR,
|
|
290
|
+
* 3: WARNING,
|
|
291
|
+
* 2: NOTICE,
|
|
292
|
+
* 1: DEBUG,
|
|
293
|
+
*
|
|
294
|
+
* If nrvideo-colors=false is present, Log.colorful will be set to false.
|
|
295
|
+
*
|
|
296
|
+
* @private
|
|
297
|
+
*/
|
|
298
|
+
function _loadLevelFromUrl() {
|
|
299
|
+
if (
|
|
300
|
+
typeof window !== "undefined" &&
|
|
301
|
+
window.location &&
|
|
302
|
+
window.location.search
|
|
303
|
+
) {
|
|
304
|
+
var m = /\?.*&*nrvideo-debug=(.+)/i.exec(window.location.search);
|
|
305
|
+
if (m !== null) {
|
|
306
|
+
if (m[1] === "true") {
|
|
307
|
+
Log.level = Log.Levels.ALL;
|
|
308
|
+
} else {
|
|
309
|
+
Log.level = m[1];
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
var m2 = /\?.*&*nrvideo-colors=false/i.exec(window.location.search);
|
|
314
|
+
if (m2 !== null) {
|
|
315
|
+
Log.colorful = false;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// Execute load level
|
|
321
|
+
_loadLevelFromUrl();
|
|
322
|
+
|
|
323
|
+
export default Log;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { customEventAggregator } from "./agent.js";
|
|
2
|
+
import { getPayloadSize } from "./utils.js";
|
|
3
|
+
import Constants from "./constants";
|
|
4
|
+
|
|
5
|
+
const { VALID_EVENT_TYPES, MAX_EVENT_SIZE } = Constants;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Records a video event with the specified type and attributes
|
|
9
|
+
* @param {string} eventType - The type of event to record
|
|
10
|
+
* @param {Object} attributes - Additional attributes to include with the event
|
|
11
|
+
* @returns {boolean} - True if event was recorded successfully, false otherwise
|
|
12
|
+
*/
|
|
13
|
+
export function recordEvent(eventType, attributes = {}) {
|
|
14
|
+
// Input validation
|
|
15
|
+
if (
|
|
16
|
+
typeof eventType !== "string" ||
|
|
17
|
+
eventType.length === 0 ||
|
|
18
|
+
!VALID_EVENT_TYPES.includes(eventType)
|
|
19
|
+
) {
|
|
20
|
+
console.warn("recordEvent: Invalid eventType provided:", eventType);
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Validate attributes parameter
|
|
25
|
+
if (
|
|
26
|
+
attributes !== null &&
|
|
27
|
+
(typeof attributes !== "object" || Array.isArray(attributes))
|
|
28
|
+
) {
|
|
29
|
+
console.warn("recordEvent: attributes must be a plain object");
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Ensure attributes is an object (handle null case)
|
|
34
|
+
attributes = attributes || {};
|
|
35
|
+
|
|
36
|
+
// Check if NRVIDEO is properly initialized
|
|
37
|
+
if (!window.NRVIDEO || !window.NRVIDEO.info) {
|
|
38
|
+
console.error("recordEvent: NRVIDEO not properly initialized");
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const { appName } = window.NRVIDEO.info;
|
|
44
|
+
|
|
45
|
+
const eventObject = {
|
|
46
|
+
...attributes,
|
|
47
|
+
eventType,
|
|
48
|
+
appName,
|
|
49
|
+
timestamp: Date.now(),
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// Check event size to prevent oversized payloads
|
|
53
|
+
const eventSize = getPayloadSize(eventObject);
|
|
54
|
+
|
|
55
|
+
if (eventSize > MAX_EVENT_SIZE) {
|
|
56
|
+
console.warn(
|
|
57
|
+
`recordEvent: Event size (${eventSize} bytes) exceeds maximum (${MAX_EVENT_SIZE} bytes)`
|
|
58
|
+
);
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
customEventAggregator.add(eventObject);
|
|
63
|
+
return true;
|
|
64
|
+
} catch (error) {
|
|
65
|
+
console.error("recordEvent: Error recording event:", error);
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
package/src/tracker.js
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import pkg from "../package.json";
|
|
2
|
+
import Emitter from "./emitter";
|
|
3
|
+
import Chrono from "./chrono";
|
|
4
|
+
import Constants from "./constants";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Tracker class provides the basic logic to extend Newrelic's Browser Agent capabilities.
|
|
8
|
+
* Trackers are designed to listen third party elements (like video tags, banners, etc.) and send
|
|
9
|
+
* information over to Browser Agent. Extend this class to create your own tracker, override
|
|
10
|
+
* registerListeners and unregisterListeners for full coverage!
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* Tracker instances should be added to Core library to start sending data:
|
|
14
|
+
* nrvideo.Core.addTracker(new Tracker())
|
|
15
|
+
*
|
|
16
|
+
* @extends Emitter
|
|
17
|
+
*/
|
|
18
|
+
class Tracker extends Emitter {
|
|
19
|
+
/**
|
|
20
|
+
* Constructor, receives options. You should call {@see registerListeners} after this.
|
|
21
|
+
*
|
|
22
|
+
* @param {Object} [options] Options for the tracker. See {@link setOptions}.
|
|
23
|
+
*/
|
|
24
|
+
constructor(options) {
|
|
25
|
+
super();
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* If you add something to this custom dictionary it will be added to every action. If you set
|
|
29
|
+
* any value, it will always override the values returned by the getters.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* If you define tracker.customData.contentTitle = 'a' and tracker.getTitle() returns 'b'.
|
|
33
|
+
* 'a' will prevail.
|
|
34
|
+
*/
|
|
35
|
+
this.customData = {};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Set time between hearbeats, in ms.
|
|
39
|
+
*/
|
|
40
|
+
this.heartbeat = null;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Another Tracker instance. Useful to relate ad Trackers to their parent content Trackers.
|
|
44
|
+
* @type Tracker
|
|
45
|
+
*/
|
|
46
|
+
this.parentTracker = null;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Chrono that counts time since this class was instantiated.
|
|
50
|
+
* @private
|
|
51
|
+
*/
|
|
52
|
+
this._trackerReadyChrono = new Chrono();
|
|
53
|
+
this._trackerReadyChrono.start();
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Store the initial table of actions with time 0 ms
|
|
57
|
+
*/
|
|
58
|
+
this._actionTable = Constants.ACTION_TABLE;
|
|
59
|
+
this._actionAdTable = Constants.ACTION_AD_TABLE;
|
|
60
|
+
|
|
61
|
+
options = options || {};
|
|
62
|
+
this.setOptions(options);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Set options for the Tracker.
|
|
67
|
+
*
|
|
68
|
+
* @param {Object} [options] Options for the tracker.
|
|
69
|
+
* @param {number} [options.heartbeat] Set time between heartbeats. See {@link heartbeat}.
|
|
70
|
+
* @param {Object} [options.customData] Set custom data. See {@link customData}.
|
|
71
|
+
* @param {Tracker} [options.parentTracker] Set parent tracker. See {@link parentTracker}.
|
|
72
|
+
*/
|
|
73
|
+
setOptions(options) {
|
|
74
|
+
if (options) {
|
|
75
|
+
if (options.parentTracker) this.parentTracker = options.parentTracker;
|
|
76
|
+
if (options.customData) this.customData = options.customData;
|
|
77
|
+
if (options.heartbeat) this.heartbeat = options.heartbeat;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Prepares tracker to dispose. Calls {@see unregisterListeners} and drops references.
|
|
83
|
+
*/
|
|
84
|
+
dispose() {
|
|
85
|
+
this.unregisterListeners();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Override this method to register listeners to third party elements.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* class SpecificTracker extends Tracker {
|
|
93
|
+
* registerListeners() {
|
|
94
|
+
* this.player.on('play', () => this.playHandler)
|
|
95
|
+
* }
|
|
96
|
+
*
|
|
97
|
+
* playHandler() {
|
|
98
|
+
* this.emit(Tracker.Events.REQUESTED)
|
|
99
|
+
* }
|
|
100
|
+
* }
|
|
101
|
+
*/
|
|
102
|
+
registerListeners() {}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Override this method to unregister listeners to third party elements created with
|
|
106
|
+
* {@see registerListeners}.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* class SpecificTracker extends Tracker {
|
|
110
|
+
* registerListeners() {
|
|
111
|
+
* this.player.on('play', () => this.playHandler)
|
|
112
|
+
* }
|
|
113
|
+
*
|
|
114
|
+
* unregisterListeners() {
|
|
115
|
+
* this.player.off('play', () => this.playHandler)
|
|
116
|
+
* }
|
|
117
|
+
*
|
|
118
|
+
* playHandler() {
|
|
119
|
+
* this.emit(Tracker.Events.REQUESTED)
|
|
120
|
+
* }
|
|
121
|
+
* }
|
|
122
|
+
*/
|
|
123
|
+
unregisterListeners() {}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Returns heartbeat time interval. 30000 (30s) if not set. See {@link setOptions}.
|
|
127
|
+
* @return {number} Heartbeat interval in ms.
|
|
128
|
+
* @final
|
|
129
|
+
*/
|
|
130
|
+
getHeartbeat() {
|
|
131
|
+
if (this.state._isAd) {
|
|
132
|
+
// modifying heartbeat for Ad Tracker
|
|
133
|
+
return 2000;
|
|
134
|
+
} else {
|
|
135
|
+
if (this.heartbeat) {
|
|
136
|
+
return this.heartbeat;
|
|
137
|
+
} else if (this.parentTracker && this.parentTracker.heartbeat) {
|
|
138
|
+
return this.parentTracker.heartbeat;
|
|
139
|
+
} else {
|
|
140
|
+
return 30000;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Starts heartbeating. Interval period set by options.heartbeat. Min 2000 ms.
|
|
147
|
+
* This method is automaticaly called by the tracker once sendRequest is called.
|
|
148
|
+
*/
|
|
149
|
+
startHeartbeat() {
|
|
150
|
+
this._heartbeatInterval = setInterval(
|
|
151
|
+
this.sendHeartbeat.bind(this),
|
|
152
|
+
Math.max(this.getHeartbeat(), 2000)
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Stops heartbeating. This method is automaticaly called by the tracker.
|
|
158
|
+
*/
|
|
159
|
+
stopHeartbeat() {
|
|
160
|
+
if (this._heartbeatInterval) {
|
|
161
|
+
clearInterval(this._heartbeatInterval);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Heartbeating allows you to call this function each X milliseconds, defined by
|
|
167
|
+
* {@link getHeartbeat}. This is useful to send regular events to track changes.
|
|
168
|
+
*
|
|
169
|
+
* By default it will send {@link Tracker.Events.HEARTBEAT}.
|
|
170
|
+
* To start heartbeating use {@link startHeartbeat} and to stop them use {@link stopHeartbeat}.
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* Override this method to define your own Heartbeat reporting.
|
|
174
|
+
*
|
|
175
|
+
* class TrackerChild extends Tracker {
|
|
176
|
+
* sendHeartbeat (att) {
|
|
177
|
+
* this.send('MY_HEARBEAT_EVENT')
|
|
178
|
+
* }
|
|
179
|
+
* }
|
|
180
|
+
*
|
|
181
|
+
* @param {Object} [att] Collection of key:value attributes to send with the request.
|
|
182
|
+
*/
|
|
183
|
+
sendHeartbeat(att) {
|
|
184
|
+
this.sendVideoAction(Tracker.Events.HEARTBEAT, att);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Override this method to return attributes for actions.
|
|
189
|
+
*
|
|
190
|
+
* @example
|
|
191
|
+
* class SpecificTracker extends Tracker {
|
|
192
|
+
* getAttributes(att) {
|
|
193
|
+
* att = att || {}
|
|
194
|
+
* att.information = 'something'
|
|
195
|
+
* return att
|
|
196
|
+
* }
|
|
197
|
+
* }
|
|
198
|
+
*
|
|
199
|
+
* @param {object} [att] Collection of key value attributes
|
|
200
|
+
* @return {object} Filled attributes
|
|
201
|
+
* @final
|
|
202
|
+
*/
|
|
203
|
+
getAttributes(att, eventType) {
|
|
204
|
+
att = att || {};
|
|
205
|
+
att.trackerName = this.getTrackerName();
|
|
206
|
+
att.trackerVersion = this.getTrackerVersion();
|
|
207
|
+
att.coreVersion = pkg.version;
|
|
208
|
+
att.timeSinceTrackerReady = this._trackerReadyChrono.getDeltaTime();
|
|
209
|
+
|
|
210
|
+
for (let key in this.customData) {
|
|
211
|
+
att[key] = this.customData[key];
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (document.hidden != undefined) {
|
|
215
|
+
att.isBackgroundEvent = document.hidden;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return att;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** Override to change of the Version of tracker. ie: '1.0.1' */
|
|
222
|
+
getTrackerVersion() {
|
|
223
|
+
return pkg.version;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** Override to change of the Name of the tracker. ie: 'custom-html5' */
|
|
227
|
+
getTrackerName() {
|
|
228
|
+
return "base-tracker";
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Send given event. Will automatically call {@see getAttributes} to fill information.
|
|
233
|
+
* Internally, this will call {@see Emitter#emit}, so you could listen any event fired.
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* tracker.send('BANNER_CLICK', { url: 'http....' })
|
|
237
|
+
*
|
|
238
|
+
* @param {string} event Event name
|
|
239
|
+
* @param {object} [att] Key:value dictionary filled with attributes.
|
|
240
|
+
*/
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* getElapsedTime: Calculate the time elapsed between two same actions
|
|
244
|
+
*
|
|
245
|
+
*/
|
|
246
|
+
|
|
247
|
+
sendVideoAction(event, att) {
|
|
248
|
+
this.emit("VideoAction", event, this.getAttributes(att));
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
sendVideoAdAction(event, att) {
|
|
252
|
+
this.emit("VideoAdAction", event, this.getAttributes(att));
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
sendVideoErrorAction(event, att) {
|
|
256
|
+
let ev = this.isAd() ? "adError" : "videoError";
|
|
257
|
+
this.emit("VideoErrorAction", event, this.getAttributes(att, ev));
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
sendVideoCustomAction(event, att) {
|
|
261
|
+
this.emit(
|
|
262
|
+
"VideoCustomAction",
|
|
263
|
+
event,
|
|
264
|
+
this.getAttributes(att, "customAction")
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Enumeration of events fired by this class.
|
|
271
|
+
*
|
|
272
|
+
* @static
|
|
273
|
+
* @memberof Tracker
|
|
274
|
+
* @enum {string}
|
|
275
|
+
*/
|
|
276
|
+
Tracker.Events = {
|
|
277
|
+
/** The heartbeat event is sent once every 30 seconds while the video is playing. */
|
|
278
|
+
HEARTBEAT: "HEARTBEAT",
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
export default Tracker;
|