@snowplow/signals-browser-plugin 0.0.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/LICENSE +29 -0
- package/README.md +131 -0
- package/dist/index.module.d.ts +187 -0
- package/dist/index.module.js +649 -0
- package/dist/index.module.js.map +1 -0
- package/dist/index.umd.js +951 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/index.umd.min.js +13 -0
- package/dist/index.umd.min.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,951 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Snowplow Signals Interventions SDK v0.0.1 (https://github.com/snowplow-incubator/signals-browser-plugin)
|
|
3
|
+
* Copyright 2025 Snowplow Analytics Ltd
|
|
4
|
+
* Licensed under BSD-3-Clause
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
(function (global, factory) {
|
|
8
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
9
|
+
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
|
10
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.snowplowSignals = {}));
|
|
11
|
+
})(this, (function (exports) { 'use strict';
|
|
12
|
+
|
|
13
|
+
/******************************************************************************
|
|
14
|
+
Copyright (c) Microsoft Corporation.
|
|
15
|
+
|
|
16
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
17
|
+
purpose with or without fee is hereby granted.
|
|
18
|
+
|
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
20
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
21
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
22
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
23
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
24
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
25
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
26
|
+
***************************************************************************** */
|
|
27
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
function __spreadArray(to, from, pack) {
|
|
31
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
32
|
+
if (ar || !(i in from)) {
|
|
33
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
34
|
+
ar[i] = from[i];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
41
|
+
var e = new Error(message);
|
|
42
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/*!
|
|
46
|
+
* Core functionality for Snowplow JavaScript trackers v4.6.5 (http://bit.ly/sp-js)
|
|
47
|
+
* Copyright 2022 Snowplow Analytics Ltd, 2010 Anthon Pang
|
|
48
|
+
* Licensed under BSD-3-Clause
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
/*
|
|
53
|
+
* Copyright (c) 2022 Snowplow Analytics Ltd, 2010 Anthon Pang
|
|
54
|
+
* All rights reserved.
|
|
55
|
+
*
|
|
56
|
+
* Redistribution and use in source and binary forms, with or without
|
|
57
|
+
* modification, are permitted provided that the following conditions are met:
|
|
58
|
+
*
|
|
59
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
60
|
+
* list of conditions and the following disclaimer.
|
|
61
|
+
*
|
|
62
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
63
|
+
* this list of conditions and the following disclaimer in the documentation
|
|
64
|
+
* and/or other materials provided with the distribution.
|
|
65
|
+
*
|
|
66
|
+
* 3. Neither the name of the copyright holder nor the names of its
|
|
67
|
+
* contributors may be used to endorse or promote products derived from
|
|
68
|
+
* this software without specific prior written permission.
|
|
69
|
+
*
|
|
70
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
71
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
72
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
73
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
74
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
75
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
76
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
77
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
78
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
79
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
80
|
+
*/
|
|
81
|
+
function payloadBuilder() {
|
|
82
|
+
var dict = {}, allJson = [], jsonForProcessing = [], contextEntitiesForProcessing = [];
|
|
83
|
+
var processor;
|
|
84
|
+
var add = function (key, value) {
|
|
85
|
+
if (value != null && value !== '') {
|
|
86
|
+
// null also checks undefined
|
|
87
|
+
dict[key] = value;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
var addDict = function (dict) {
|
|
91
|
+
for (var key in dict) {
|
|
92
|
+
if (Object.prototype.hasOwnProperty.call(dict, key)) {
|
|
93
|
+
add(key, dict[key]);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
var addJson = function (keyIfEncoded, keyIfNotEncoded, json) {
|
|
98
|
+
if (json && isNonEmptyJson(json)) {
|
|
99
|
+
var jsonWithKeys = { keyIfEncoded: keyIfEncoded, keyIfNotEncoded: keyIfNotEncoded, json: json };
|
|
100
|
+
jsonForProcessing.push(jsonWithKeys);
|
|
101
|
+
allJson.push(jsonWithKeys);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
var addContextEntity = function (entity) {
|
|
105
|
+
contextEntitiesForProcessing.push(entity);
|
|
106
|
+
};
|
|
107
|
+
return {
|
|
108
|
+
add: add,
|
|
109
|
+
addDict: addDict,
|
|
110
|
+
addJson: addJson,
|
|
111
|
+
addContextEntity: addContextEntity,
|
|
112
|
+
getPayload: function () { return dict; },
|
|
113
|
+
getJson: function () { return allJson; },
|
|
114
|
+
withJsonProcessor: function (jsonProcessor) {
|
|
115
|
+
processor = jsonProcessor;
|
|
116
|
+
},
|
|
117
|
+
build: function () {
|
|
118
|
+
processor === null || processor === void 0 ? void 0 : processor(this, jsonForProcessing, contextEntitiesForProcessing);
|
|
119
|
+
return dict;
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Is property a non-empty JSON?
|
|
125
|
+
* @param property - Checks if object is non-empty json
|
|
126
|
+
*/
|
|
127
|
+
function isNonEmptyJson(property) {
|
|
128
|
+
if (!isJson(property)) {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
for (var key in property) {
|
|
132
|
+
if (Object.prototype.hasOwnProperty.call(property, key)) {
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Is property a JSON?
|
|
140
|
+
* @param property - Checks if object is json
|
|
141
|
+
*/
|
|
142
|
+
function isJson(property) {
|
|
143
|
+
return (typeof property !== 'undefined' &&
|
|
144
|
+
property !== null &&
|
|
145
|
+
(property.constructor === {}.constructor || property.constructor === [].constructor));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/*
|
|
149
|
+
* Copyright (c) 2022 Snowplow Analytics Ltd, 2010 Anthon Pang
|
|
150
|
+
* All rights reserved.
|
|
151
|
+
*
|
|
152
|
+
* Redistribution and use in source and binary forms, with or without
|
|
153
|
+
* modification, are permitted provided that the following conditions are met:
|
|
154
|
+
*
|
|
155
|
+
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
156
|
+
* list of conditions and the following disclaimer.
|
|
157
|
+
*
|
|
158
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
159
|
+
* this list of conditions and the following disclaimer in the documentation
|
|
160
|
+
* and/or other materials provided with the distribution.
|
|
161
|
+
*
|
|
162
|
+
* 3. Neither the name of the copyright holder nor the names of its
|
|
163
|
+
* contributors may be used to endorse or promote products derived from
|
|
164
|
+
* this software without specific prior written permission.
|
|
165
|
+
*
|
|
166
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
167
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
168
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
169
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
170
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
171
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
172
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
173
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
174
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
175
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
176
|
+
*/
|
|
177
|
+
var label = 'Snowplow: ';
|
|
178
|
+
var LOG_LEVEL;
|
|
179
|
+
(function (LOG_LEVEL) {
|
|
180
|
+
LOG_LEVEL[LOG_LEVEL["none"] = 0] = "none";
|
|
181
|
+
LOG_LEVEL[LOG_LEVEL["error"] = 1] = "error";
|
|
182
|
+
LOG_LEVEL[LOG_LEVEL["warn"] = 2] = "warn";
|
|
183
|
+
LOG_LEVEL[LOG_LEVEL["debug"] = 3] = "debug";
|
|
184
|
+
LOG_LEVEL[LOG_LEVEL["info"] = 4] = "info";
|
|
185
|
+
})(LOG_LEVEL || (LOG_LEVEL = {}));
|
|
186
|
+
logger$1();
|
|
187
|
+
function logger$1(logLevel) {
|
|
188
|
+
if (logLevel === void 0) { logLevel = LOG_LEVEL.warn; }
|
|
189
|
+
function setLogLevel(level) {
|
|
190
|
+
if (LOG_LEVEL[level]) {
|
|
191
|
+
logLevel = level;
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
logLevel = LOG_LEVEL.warn;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Log errors, with or without error object
|
|
199
|
+
*/
|
|
200
|
+
function error(message, error) {
|
|
201
|
+
var extraParams = [];
|
|
202
|
+
for (var _i = 2; _i < arguments.length; _i++) {
|
|
203
|
+
extraParams[_i - 2] = arguments[_i];
|
|
204
|
+
}
|
|
205
|
+
if (logLevel >= LOG_LEVEL.error && typeof console !== 'undefined') {
|
|
206
|
+
var logMsg = label + message + '\n';
|
|
207
|
+
if (error) {
|
|
208
|
+
console.error.apply(console, __spreadArray([logMsg + '\n', error], extraParams, false));
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
console.error.apply(console, __spreadArray([logMsg], extraParams, false));
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Log warnings, with or without error object
|
|
217
|
+
*/
|
|
218
|
+
function warn(message, error) {
|
|
219
|
+
var extraParams = [];
|
|
220
|
+
for (var _i = 2; _i < arguments.length; _i++) {
|
|
221
|
+
extraParams[_i - 2] = arguments[_i];
|
|
222
|
+
}
|
|
223
|
+
if (logLevel >= LOG_LEVEL.warn && typeof console !== 'undefined') {
|
|
224
|
+
var logMsg = label + message;
|
|
225
|
+
if (error) {
|
|
226
|
+
console.warn.apply(console, __spreadArray([logMsg + '\n', error], extraParams, false));
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
console.warn.apply(console, __spreadArray([logMsg], extraParams, false));
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Log debug messages
|
|
235
|
+
*/
|
|
236
|
+
function debug(message) {
|
|
237
|
+
var extraParams = [];
|
|
238
|
+
for (var _i = 1; _i < arguments.length; _i++) {
|
|
239
|
+
extraParams[_i - 1] = arguments[_i];
|
|
240
|
+
}
|
|
241
|
+
if (logLevel >= LOG_LEVEL.debug && typeof console !== 'undefined') {
|
|
242
|
+
console.debug.apply(console, __spreadArray([label + message], extraParams, false));
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Log info messages
|
|
247
|
+
*/
|
|
248
|
+
function info(message) {
|
|
249
|
+
var extraParams = [];
|
|
250
|
+
for (var _i = 1; _i < arguments.length; _i++) {
|
|
251
|
+
extraParams[_i - 1] = arguments[_i];
|
|
252
|
+
}
|
|
253
|
+
if (logLevel >= LOG_LEVEL.info && typeof console !== 'undefined') {
|
|
254
|
+
console.info.apply(console, __spreadArray([label + message], extraParams, false));
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return { setLogLevel: setLogLevel, warn: warn, error: error, debug: debug, info: info };
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Find dynamic context generating functions and return their results to be merged into the static contexts
|
|
261
|
+
* Combine an array of unchanging contexts with the result of a context-creating function
|
|
262
|
+
*
|
|
263
|
+
* @param dynamicOrStaticContexts - Array of custom context Objects or custom context generating functions
|
|
264
|
+
* @param Parameters - to pass to dynamic context callbacks
|
|
265
|
+
* @returns An array of Self Describing JSON context
|
|
266
|
+
*/
|
|
267
|
+
function resolveDynamicContext(dynamicOrStaticContexts) {
|
|
268
|
+
var _a;
|
|
269
|
+
var extraParams = [];
|
|
270
|
+
for (var _i = 1; _i < arguments.length; _i++) {
|
|
271
|
+
extraParams[_i - 1] = arguments[_i];
|
|
272
|
+
}
|
|
273
|
+
return ((_a = dynamicOrStaticContexts === null || dynamicOrStaticContexts === void 0 ? void 0 : dynamicOrStaticContexts.map(function (context) {
|
|
274
|
+
if (typeof context === 'function') {
|
|
275
|
+
try {
|
|
276
|
+
return context.apply(void 0, extraParams);
|
|
277
|
+
}
|
|
278
|
+
catch (e) {
|
|
279
|
+
//TODO: provide warning
|
|
280
|
+
return undefined;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
return context;
|
|
285
|
+
}
|
|
286
|
+
}).filter(Boolean)) !== null && _a !== void 0 ? _a : []);
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Build a self-describing event
|
|
290
|
+
* A custom event type, allowing for an event to be tracked using your own custom schema
|
|
291
|
+
* and a data object which conforms to the supplied schema
|
|
292
|
+
*
|
|
293
|
+
* @param event - Contains the properties and schema location for the event
|
|
294
|
+
* @returns PayloadBuilder to be sent to {@link @snowplow/tracker-core#TrackerCore.track}
|
|
295
|
+
*/
|
|
296
|
+
function buildSelfDescribingEvent(event) {
|
|
297
|
+
var _a = event.event, schema = _a.schema, data = _a.data, pb = payloadBuilder();
|
|
298
|
+
var ueJson = {
|
|
299
|
+
schema: 'iglu:com.snowplowanalytics.snowplow/unstruct_event/jsonschema/1-0-0',
|
|
300
|
+
data: { schema: schema, data: data },
|
|
301
|
+
};
|
|
302
|
+
pb.add('e', 'ue');
|
|
303
|
+
pb.addJson('ue_px', 'ue_pr', ueJson);
|
|
304
|
+
return pb;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
var LogLevel;
|
|
308
|
+
(function (LogLevel) {
|
|
309
|
+
LogLevel["DEBUG"] = "debug";
|
|
310
|
+
LogLevel["ERROR"] = "error";
|
|
311
|
+
LogLevel["INFO"] = "info";
|
|
312
|
+
LogLevel["WARN"] = "warn";
|
|
313
|
+
})(LogLevel || (LogLevel = {}));
|
|
314
|
+
var name;
|
|
315
|
+
var LOG;
|
|
316
|
+
/**
|
|
317
|
+
* Wrap the passed logger so that it's clear which plugin/tracker instance log messages refer to
|
|
318
|
+
* @param level Log level for the logged message
|
|
319
|
+
* @param trackerId Tracker ID logging the event
|
|
320
|
+
* @param args Log message and other arguments
|
|
321
|
+
*/
|
|
322
|
+
var logger = function (level, trackerId) {
|
|
323
|
+
var args = [];
|
|
324
|
+
for (var _i = 2; _i < arguments.length; _i++) {
|
|
325
|
+
args[_i - 2] = arguments[_i];
|
|
326
|
+
}
|
|
327
|
+
if (!name || !LOG) {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
var prefix = "[".concat(name, ":").concat(trackerId, "] ");
|
|
331
|
+
if (typeof args[0] === 'string') {
|
|
332
|
+
var msg = prefix + args.shift();
|
|
333
|
+
LOG[level].apply(LOG, __spreadArray([msg], args, false));
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
LOG[level].apply(LOG, __spreadArray([prefix], args, false));
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
var setLogger = function (plugin, log) {
|
|
340
|
+
name = plugin;
|
|
341
|
+
LOG = log;
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
var ENTITY_ALIASES = ['co', 'cx', 'context', 'entity', 'entities'];
|
|
345
|
+
var EVENT_ALIASES = ['ue', 'ue_pr', 'ue_px', 'unstruct', 'unstruct_event', 'self_describing', 'sde'];
|
|
346
|
+
var EVENT_SCHEMAS = {
|
|
347
|
+
se: 'iglu:com.google.analytics/event/jsonschema/1-0-0',
|
|
348
|
+
ev: 'iglu:com.google.analytics/event/jsonschema/1-0-0',
|
|
349
|
+
ad: 'iglu:com.snowplowanalytics.snowplow/ad_impression/jsonschema/1-0-0',
|
|
350
|
+
tr: 'iglu:com.snowplowanalytics.snowplow/transaction/jsonschema/1-0-0',
|
|
351
|
+
ti: 'iglu:com.snowplowanalytics.snowplow/transaction_item/1-0-0',
|
|
352
|
+
pv: 'iglu:com.snowplowanalytics.snowplow/page_view/jsonschema/1-0-0',
|
|
353
|
+
pp: 'iglu:com.snowplowanalytics.snowplow/page_ping/jsonschema/1-0-0',
|
|
354
|
+
ue: '', // here to pass an `in` check below; needs to be extracted from SDJ payload
|
|
355
|
+
};
|
|
356
|
+
var objWithKey = function (obj, key) {
|
|
357
|
+
return typeof obj === 'object' && obj != null && key in obj;
|
|
358
|
+
};
|
|
359
|
+
var extractUrlFrom = function (part, field) {
|
|
360
|
+
return function (event) {
|
|
361
|
+
try {
|
|
362
|
+
return new URL(event[field])[part].toString() || undefined;
|
|
363
|
+
}
|
|
364
|
+
catch (_) {
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
};
|
|
369
|
+
var extractUrlParamFrom = function (param, field) {
|
|
370
|
+
return function (event) {
|
|
371
|
+
var _a;
|
|
372
|
+
try {
|
|
373
|
+
return (_a = new URL(event[field]).searchParams.get(param)) !== null && _a !== void 0 ? _a : undefined;
|
|
374
|
+
}
|
|
375
|
+
catch (_) {
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
};
|
|
380
|
+
var extractParamPartFrom = function (param, field, index, sep) {
|
|
381
|
+
if (sep === void 0) { sep = '.'; }
|
|
382
|
+
return function (event) {
|
|
383
|
+
var _a;
|
|
384
|
+
try {
|
|
385
|
+
var full = (_a = new URL(event[field]).searchParams.get(param)) !== null && _a !== void 0 ? _a : undefined;
|
|
386
|
+
return full ? full.split(sep)[index] : undefined;
|
|
387
|
+
}
|
|
388
|
+
catch (_) {
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
};
|
|
393
|
+
var extractDimensionValueFrom = function (dim, field) {
|
|
394
|
+
return function (event) {
|
|
395
|
+
try {
|
|
396
|
+
return event[field].split('x')[dim];
|
|
397
|
+
}
|
|
398
|
+
catch (_) {
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
};
|
|
403
|
+
/**
|
|
404
|
+
* `Payload` instances access data via their tracker protocol field names, rather than the more human-friendly ones users are familiar with from enriched data.
|
|
405
|
+
* This maps the enriched fields back to their TP equivalents; allowing for field extraction where necessary.
|
|
406
|
+
*/
|
|
407
|
+
var selectorMap = {
|
|
408
|
+
app_id: 'aid',
|
|
409
|
+
platform: 'p',
|
|
410
|
+
dvce_created_tstamp: 'dtm',
|
|
411
|
+
event: function (_a) {
|
|
412
|
+
var _b;
|
|
413
|
+
var e = _a.e;
|
|
414
|
+
return ((_b = {
|
|
415
|
+
se: 'struct',
|
|
416
|
+
ev: 'struct',
|
|
417
|
+
ue: 'unstruct',
|
|
418
|
+
ad: 'ad_impression',
|
|
419
|
+
tr: 'transaction',
|
|
420
|
+
ti: 'transaction_item',
|
|
421
|
+
pv: 'page_view',
|
|
422
|
+
pp: 'page_ping',
|
|
423
|
+
}[e]) !== null && _b !== void 0 ? _b : e);
|
|
424
|
+
},
|
|
425
|
+
event_id: 'eid',
|
|
426
|
+
txn_id: 'tid',
|
|
427
|
+
name_tracker: 'tna',
|
|
428
|
+
v_tracker: 'tv',
|
|
429
|
+
user_id: 'uid',
|
|
430
|
+
user_ipaddress: 'ip',
|
|
431
|
+
user_fingerprint: 'fp',
|
|
432
|
+
domain_userid: 'duid',
|
|
433
|
+
domain_sessionidx: 'vid',
|
|
434
|
+
network_userid: 'nuid',
|
|
435
|
+
page_url: 'url',
|
|
436
|
+
page_title: 'page',
|
|
437
|
+
page_referrer: 'refr',
|
|
438
|
+
page_urlscheme: extractUrlFrom('protocol', 'url'),
|
|
439
|
+
page_urlhost: extractUrlFrom('hostname', 'url'),
|
|
440
|
+
page_urlport: extractUrlFrom('port', 'url'),
|
|
441
|
+
page_urlpath: extractUrlFrom('pathname', 'url'),
|
|
442
|
+
page_urlquery: extractUrlFrom('search', 'url'),
|
|
443
|
+
page_urlfragment: extractUrlFrom('hash', 'url'),
|
|
444
|
+
refr_urlscheme: extractUrlFrom('protocol', 'refr'),
|
|
445
|
+
refr_urlhost: extractUrlFrom('hostname', 'refr'),
|
|
446
|
+
refr_urlport: extractUrlFrom('port', 'refr'),
|
|
447
|
+
refr_urlpath: extractUrlFrom('pathname', 'refr'),
|
|
448
|
+
refr_urlquery: extractUrlFrom('search', 'refr'),
|
|
449
|
+
refr_urlfragment: extractUrlFrom('hash', 'refr'),
|
|
450
|
+
mkt_medium: extractUrlParamFrom('utm_medium', 'url'),
|
|
451
|
+
mkt_source: extractUrlParamFrom('utm_source', 'url'),
|
|
452
|
+
mkt_term: extractUrlParamFrom('utm_term', 'url'),
|
|
453
|
+
mkt_content: extractUrlParamFrom('utm_content', 'url'),
|
|
454
|
+
mkt_campaign: extractUrlParamFrom('utm_campaign', 'url'),
|
|
455
|
+
se_category: 'se_ca',
|
|
456
|
+
se_action: 'se_ac',
|
|
457
|
+
se_label: 'se_la',
|
|
458
|
+
se_property: 'se_pr',
|
|
459
|
+
se_value: 'se_va',
|
|
460
|
+
tr_orderid: 'tr_id',
|
|
461
|
+
tr_affiliation: 'tr_af',
|
|
462
|
+
tr_total: 'tr_tt',
|
|
463
|
+
tr_tax: 'tr_tx',
|
|
464
|
+
tr_shipping: 'tr_sh',
|
|
465
|
+
tr_city: 'tr_ci',
|
|
466
|
+
tr_state: 'tr_st',
|
|
467
|
+
tr_country: 'tr_co',
|
|
468
|
+
ti_orderid: 'ti_id',
|
|
469
|
+
ti_sku: 'ti_sk',
|
|
470
|
+
ti_name: 'ti_na',
|
|
471
|
+
ti_category: 'ti_ca',
|
|
472
|
+
ti_price: 'ti_pr',
|
|
473
|
+
ti_quantity: 'ti_qu',
|
|
474
|
+
pp_xoffset_min: 'pp_mix',
|
|
475
|
+
pp_xoffset_max: 'pp_max',
|
|
476
|
+
pp_yoffset_min: 'pp_miy',
|
|
477
|
+
pp_yoffset_max: 'pp_may',
|
|
478
|
+
useragent: function (_a) {
|
|
479
|
+
var ua = _a.ua;
|
|
480
|
+
return ua !== null && ua !== void 0 ? ua : navigator.userAgent;
|
|
481
|
+
}, // often elided and extracted from HTTP header
|
|
482
|
+
br_lang: 'lang',
|
|
483
|
+
br_features_pdf: 'f_pdf',
|
|
484
|
+
br_features_flash: 'f_fla',
|
|
485
|
+
br_features_java: 'f_java',
|
|
486
|
+
br_features_director: 'f_dir',
|
|
487
|
+
br_features_quicktime: 'f_qt',
|
|
488
|
+
br_features_realplayer: 'f_realp',
|
|
489
|
+
br_features_windowsmedia: 'f_wma',
|
|
490
|
+
br_features_gears: 'f_gears',
|
|
491
|
+
br_features_silverlight: 'f_ag',
|
|
492
|
+
br_cookies: 'cookie',
|
|
493
|
+
br_colordepth: 'cd',
|
|
494
|
+
br_viewwidth: extractDimensionValueFrom(0, 'vp'),
|
|
495
|
+
br_viewheight: extractDimensionValueFrom(1, 'vp'),
|
|
496
|
+
os_timezone: 'tz',
|
|
497
|
+
dvce_screenwidth: extractDimensionValueFrom(0, 'res'),
|
|
498
|
+
dvce_screenheight: extractDimensionValueFrom(1, 'res'),
|
|
499
|
+
doc_charset: 'cs',
|
|
500
|
+
doc_width: extractDimensionValueFrom(0, 'ds'),
|
|
501
|
+
doc_height: extractDimensionValueFrom(1, 'ds'),
|
|
502
|
+
tr_currency: 'tr_cu',
|
|
503
|
+
ti_currency: 'ti_cu',
|
|
504
|
+
mkt_clickid: extractUrlParamFrom('gclid', 'url'),
|
|
505
|
+
dvce_sent_tstamp: 'stm',
|
|
506
|
+
refr_domain_userid: extractParamPartFrom('_sp', 'url', 0),
|
|
507
|
+
refr_device_tstamp: extractParamPartFrom('_sp', 'url', 1),
|
|
508
|
+
domain_sessionid: 'sid',
|
|
509
|
+
event_vendor: function (evt) { var _a; return (_a = getEventSelf(evt)) === null || _a === void 0 ? void 0 : _a.vendor; },
|
|
510
|
+
event_name: function (evt) { var _a; return (_a = getEventSelf(evt)) === null || _a === void 0 ? void 0 : _a.name; },
|
|
511
|
+
event_format: function (evt) { var _a; return (_a = getEventSelf(evt)) === null || _a === void 0 ? void 0 : _a.format; },
|
|
512
|
+
event_version: function (evt) { var _a; return (_a = getEventSelf(evt)) === null || _a === void 0 ? void 0 : _a.version; },
|
|
513
|
+
true_tstamp: 'ttm',
|
|
514
|
+
};
|
|
515
|
+
var parseJsonPointer = function (pointer) {
|
|
516
|
+
if (!pointer) {
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
if (pointer[0] !== '/') {
|
|
520
|
+
pointer = "/".concat(pointer); // for atomic-level fields, this will allow regular names since JSON Pointer isn't super intuitive
|
|
521
|
+
}
|
|
522
|
+
return pointer
|
|
523
|
+
.split('/')
|
|
524
|
+
.map(function (segment) { return segment.replace(/~1/g, '/').replace(/~0/g, '~'); })
|
|
525
|
+
.slice(1);
|
|
526
|
+
};
|
|
527
|
+
var parseEncodedFields = function (evt, fields) {
|
|
528
|
+
return fields.map(function (field) {
|
|
529
|
+
if (objWithKey(evt, field)) {
|
|
530
|
+
var val = evt[field];
|
|
531
|
+
if (typeof val === 'string') {
|
|
532
|
+
try {
|
|
533
|
+
return JSON.parse(val);
|
|
534
|
+
}
|
|
535
|
+
catch (_) {
|
|
536
|
+
try {
|
|
537
|
+
return JSON.parse(atob(val.replace(/[_-]/g, function (m) { return (m == '-' ? '+' : '/'); })));
|
|
538
|
+
}
|
|
539
|
+
catch (_) { }
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
});
|
|
544
|
+
};
|
|
545
|
+
/**
|
|
546
|
+
* Build a lookup map of `vendor: name[]` for entities to lookup more easily
|
|
547
|
+
*/
|
|
548
|
+
var summarizeEntities = function (evt) {
|
|
549
|
+
var fields = parseEncodedFields(evt, ['co', 'cx']);
|
|
550
|
+
return fields.reduce(function (acc, ctx) {
|
|
551
|
+
if (objWithKey(ctx, 'data') && Array.isArray(ctx.data)) {
|
|
552
|
+
ctx.data.forEach(function (entity) {
|
|
553
|
+
var _a, _b;
|
|
554
|
+
if (objWithKey(entity, 'schema') && objWithKey(entity, 'data')) {
|
|
555
|
+
if (typeof entity.schema === 'string' && entity.schema.indexOf('iglu:') === 0) {
|
|
556
|
+
var parts = entity.schema.slice(5).split('/');
|
|
557
|
+
if (parts.length !== 4) {
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
var vendor = (acc[parts[0]] = (_a = acc[parts[0]]) !== null && _a !== void 0 ? _a : {});
|
|
561
|
+
vendor[parts[1]] = (_b = vendor[parts[1]]) !== null && _b !== void 0 ? _b : [];
|
|
562
|
+
vendor[parts[1]].push(entity.data);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
return acc;
|
|
568
|
+
}, {});
|
|
569
|
+
};
|
|
570
|
+
/**
|
|
571
|
+
* Build a lookup map of `vendor: name` for SDE payloads to lookup more easily
|
|
572
|
+
*/
|
|
573
|
+
var summarizeEvent = function (evt) {
|
|
574
|
+
var fields = parseEncodedFields(evt, ['ue_pr', 'ue_px']);
|
|
575
|
+
return fields.reduce(function (acc, ctx) {
|
|
576
|
+
var _a;
|
|
577
|
+
if (objWithKey(ctx, 'data')) {
|
|
578
|
+
if (objWithKey(ctx.data, 'schema') && objWithKey(ctx.data, 'data')) {
|
|
579
|
+
var event_1 = ctx.data;
|
|
580
|
+
if (typeof event_1.schema === 'string' && event_1.schema.indexOf('iglu:') === 0) {
|
|
581
|
+
var parts = event_1.schema.slice(5).split('/');
|
|
582
|
+
if (parts.length !== 4) {
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
var vendor = (acc[parts[0]] = (_a = acc[parts[0]]) !== null && _a !== void 0 ? _a : {});
|
|
586
|
+
vendor[parts[1]] = event_1.data;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
return acc;
|
|
591
|
+
}, {});
|
|
592
|
+
};
|
|
593
|
+
var getEventSelf = function (evt) {
|
|
594
|
+
var _a;
|
|
595
|
+
var schema = undefined;
|
|
596
|
+
if (!objWithKey(evt, 'e') || typeof evt.e !== 'string' || !(evt.e in EVENT_SCHEMAS)) {
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
if (evt.e === 'ue') {
|
|
600
|
+
var fields = parseEncodedFields(evt, ['ue_pr', 'ue_px']);
|
|
601
|
+
var ue = (_a = fields[0]) !== null && _a !== void 0 ? _a : fields[1];
|
|
602
|
+
if (objWithKey(ue, 'data') && objWithKey(ue.data, 'schema') && typeof ue.data.schema === 'string') {
|
|
603
|
+
schema = ue.data.schema;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
else {
|
|
607
|
+
schema = EVENT_SCHEMAS[evt.e];
|
|
608
|
+
}
|
|
609
|
+
if (typeof schema === 'string' && schema.indexOf('iglu:') === 0) {
|
|
610
|
+
var _b = schema.slice(5).split('/'), vendor = _b[0], name_1 = _b[1], format = _b[2], version = _b[3];
|
|
611
|
+
return { vendor: vendor, name: name_1, format: format, version: version };
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
var derefJsonPointer = function (pointerString, obj) {
|
|
615
|
+
var _a, _b;
|
|
616
|
+
var pointer = parseJsonPointer(pointerString);
|
|
617
|
+
if (pointer == null) {
|
|
618
|
+
return obj; // return whole document
|
|
619
|
+
}
|
|
620
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
621
|
+
return; // no segments will work
|
|
622
|
+
}
|
|
623
|
+
// map enriched fieldname <> TP field
|
|
624
|
+
if (pointer[0] in selectorMap) {
|
|
625
|
+
var mappedSelector = selectorMap[pointer[0]];
|
|
626
|
+
if (typeof mappedSelector === 'string' && objWithKey(obj, mappedSelector)) {
|
|
627
|
+
return obj[mappedSelector];
|
|
628
|
+
}
|
|
629
|
+
else if (typeof mappedSelector === 'function') {
|
|
630
|
+
return mappedSelector(obj);
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
// descend into nested SDJ payloads
|
|
634
|
+
var cursor = obj;
|
|
635
|
+
if (ENTITY_ALIASES.indexOf(pointer[0]) !== -1) {
|
|
636
|
+
cursor = (_a = {}, _a[pointer[0]] = summarizeEntities(cursor), _a);
|
|
637
|
+
}
|
|
638
|
+
if (EVENT_ALIASES.indexOf(pointer[0]) !== -1) {
|
|
639
|
+
cursor = (_b = {}, _b[pointer[0]] = summarizeEvent(cursor), _b);
|
|
640
|
+
}
|
|
641
|
+
for (var _i = 0, pointer_1 = pointer; _i < pointer_1.length; _i++) {
|
|
642
|
+
var segment = pointer_1[_i];
|
|
643
|
+
if (objWithKey(cursor, segment)) {
|
|
644
|
+
cursor = cursor[segment];
|
|
645
|
+
}
|
|
646
|
+
else if (Array.isArray(cursor) && cursor.length === 1 && objWithKey(cursor[0], segment)) {
|
|
647
|
+
cursor = cursor[0][segment];
|
|
648
|
+
}
|
|
649
|
+
else
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
return cursor;
|
|
653
|
+
};
|
|
654
|
+
/**
|
|
655
|
+
* Given a list of rules to extract entity IDs and a Snowplow event payload, return any extracted ID results.
|
|
656
|
+
* @param targets Map of entity names to rule definitions for how to find ID values
|
|
657
|
+
* @param pb Snowplow event
|
|
658
|
+
* @returns Resulting IDs extracted from the event
|
|
659
|
+
*/
|
|
660
|
+
function extractEntityValues(targets, pb) {
|
|
661
|
+
var extracted = {};
|
|
662
|
+
Object.entries(targets).forEach(function (_a) {
|
|
663
|
+
var entityName = _a[0], pointers = _a[1];
|
|
664
|
+
pointers = Array.isArray(pointers) ? pointers : [pointers];
|
|
665
|
+
for (var _i = 0, pointers_1 = pointers; _i < pointers_1.length; _i++) {
|
|
666
|
+
var pointer = pointers_1[_i];
|
|
667
|
+
if (pointer === '') {
|
|
668
|
+
continue;
|
|
669
|
+
}
|
|
670
|
+
var candidateId = derefJsonPointer(pointer, pb);
|
|
671
|
+
if (candidateId != null) {
|
|
672
|
+
extracted[entityName] = String(candidateId);
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
});
|
|
677
|
+
return extracted;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
var DEFAULT_PULL_API_PATH = '/api/v1/interventions';
|
|
681
|
+
var DEFAULT_ENTITY_TARGETS = {
|
|
682
|
+
domain_userid: '/domain_userid',
|
|
683
|
+
domain_sessionid: '/domain_sessionid',
|
|
684
|
+
//pageview_id: '/co/com.snowplowanalytics.snowplow/web_page/id', // not a default entity seed
|
|
685
|
+
//tab_id: '/co/com.snowplowanalytics.snowplow/browser_context/tabId', // not a default entity seed
|
|
686
|
+
};
|
|
687
|
+
var DEFAULT_CONNECTION_TIMEOUT_MS = 2500;
|
|
688
|
+
/**
|
|
689
|
+
* Default `Fetcher` implementation; uses SSEs, auto updates based on observed entity IDs defined with JSON Pointers
|
|
690
|
+
*/
|
|
691
|
+
var InterventionFetcher = /** @class */ (function () {
|
|
692
|
+
function InterventionFetcher(tracker, dispatch) {
|
|
693
|
+
this.tracker = tracker;
|
|
694
|
+
this.dispatch = dispatch;
|
|
695
|
+
this.entityValues = {};
|
|
696
|
+
this.aborter = new AbortController();
|
|
697
|
+
this.timeoutMs = DEFAULT_CONNECTION_TIMEOUT_MS;
|
|
698
|
+
this.newEndpoint = false;
|
|
699
|
+
this.currentParams = '';
|
|
700
|
+
this.entitySelectors = DEFAULT_ENTITY_TARGETS;
|
|
701
|
+
// reasonable defaults even without any events observed
|
|
702
|
+
var info = tracker.getDomainUserInfo();
|
|
703
|
+
this.update({
|
|
704
|
+
duid: info[1] || undefined,
|
|
705
|
+
sid: info[6] || undefined,
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
InterventionFetcher.prototype.configure = function (_a) {
|
|
709
|
+
var endpoint = _a.endpoint, _b = _a.apiPath, apiPath = _b === void 0 ? DEFAULT_PULL_API_PATH : _b, _c = _a.entityTargets, entityTargets = _c === void 0 ? DEFAULT_ENTITY_TARGETS : _c, _d = _a.entityIds, entityIds = _d === void 0 ? {} : _d, _e = _a.connectionTimeoutMs, connectionTimeoutMs = _e === void 0 ? DEFAULT_CONNECTION_TIMEOUT_MS : _e;
|
|
710
|
+
this.entitySelectors = Object.assign({}, this.entitySelectors, entityTargets);
|
|
711
|
+
this.timeoutMs = connectionTimeoutMs;
|
|
712
|
+
var prevEndpoint = this.endpoint;
|
|
713
|
+
this.endpoint = "".concat(/\/\//.test(endpoint) ? endpoint : 'https://' + endpoint).concat(apiPath);
|
|
714
|
+
this.newEndpoint = prevEndpoint != this.endpoint;
|
|
715
|
+
this.update(undefined, entityIds);
|
|
716
|
+
};
|
|
717
|
+
InterventionFetcher.prototype.update = function (payload, explicitEntities) {
|
|
718
|
+
if (explicitEntities === void 0) { explicitEntities = {}; }
|
|
719
|
+
if (payload) {
|
|
720
|
+
Object.assign(this.entityValues, extractEntityValues(this.entitySelectors, payload));
|
|
721
|
+
}
|
|
722
|
+
Object.assign(this.entityValues, explicitEntities);
|
|
723
|
+
var newParams = new URLSearchParams(this.entityValues).toString();
|
|
724
|
+
if (this.endpoint && (newParams != this.currentParams || this.newEndpoint)) {
|
|
725
|
+
logger(LogLevel.DEBUG, this.tracker.id, 'Entity IDs updated', this.entityValues);
|
|
726
|
+
this.currentParams = newParams;
|
|
727
|
+
this.requestInterventions();
|
|
728
|
+
}
|
|
729
|
+
};
|
|
730
|
+
/**
|
|
731
|
+
* Set up a new SSE connection and start dispatching any received events
|
|
732
|
+
*/
|
|
733
|
+
InterventionFetcher.prototype.requestInterventions = function () {
|
|
734
|
+
var _this = this;
|
|
735
|
+
this.aborter.abort(); // abort any previous connection
|
|
736
|
+
var aborter = (this.aborter = new AbortController()); // new controller to reset aborted state
|
|
737
|
+
if (!this.endpoint) {
|
|
738
|
+
logger(LogLevel.ERROR, this.tracker.id, 'Requested interventions from undefined endpoint');
|
|
739
|
+
return;
|
|
740
|
+
}
|
|
741
|
+
var url = "".concat(this.endpoint, "?").concat(this.currentParams);
|
|
742
|
+
var stream = new EventSource(url);
|
|
743
|
+
aborter.signal.addEventListener('abort', stream.close.bind(stream), {
|
|
744
|
+
once: true,
|
|
745
|
+
});
|
|
746
|
+
var timeout = setTimeout(aborter.abort.bind(aborter), this.timeoutMs);
|
|
747
|
+
stream.addEventListener('open', function () { return clearTimeout(timeout); }, {
|
|
748
|
+
once: true,
|
|
749
|
+
});
|
|
750
|
+
stream.addEventListener('error', function (ev) {
|
|
751
|
+
return logger(LogLevel.ERROR, _this.tracker.id, 'Error fetching interventions:', ev);
|
|
752
|
+
});
|
|
753
|
+
stream.addEventListener('message', function (ev) {
|
|
754
|
+
_this.dispatch(JSON.parse(ev.data), _this.tracker);
|
|
755
|
+
});
|
|
756
|
+
};
|
|
757
|
+
/**
|
|
758
|
+
* Factory to match signature of public interface and create the default fetcher instance
|
|
759
|
+
* @param tracker Tracker activating the plugin
|
|
760
|
+
* @param dispatch Callback to pass interventions to
|
|
761
|
+
* @returns `InterventionFetcher` instance
|
|
762
|
+
*/
|
|
763
|
+
InterventionFetcher.create = function (tracker, dispatch) { return new InterventionFetcher(tracker, dispatch); };
|
|
764
|
+
return InterventionFetcher;
|
|
765
|
+
}());
|
|
766
|
+
|
|
767
|
+
var Events = {
|
|
768
|
+
INTERVENTION_RECEIVED: 'iglu:com.snowplowanalytics.signals/intervention_receive/jsonschema/1-0-0',
|
|
769
|
+
INTERVENTION_HANDLE: 'iglu:com.snowplowanalytics.signals/intervention_handle/jsonschema/1-0-0',
|
|
770
|
+
INTERVENTION_HANDLE_ERROR: 'iglu:com.snowplowanalytics.signals/intervention_handle_error/jsonschema/1-0-0',
|
|
771
|
+
};
|
|
772
|
+
var Entities = {
|
|
773
|
+
INTERVENTION: 'iglu:com.snowplowanalytics.signals/intervention_instance/jsonschema/1-0-0',
|
|
774
|
+
};
|
|
775
|
+
var MEASUREMENT_EVENTS = {
|
|
776
|
+
delivery: Events.INTERVENTION_RECEIVED,
|
|
777
|
+
dispatch_accept: Events.INTERVENTION_HANDLE,
|
|
778
|
+
dispatch_error: Events.INTERVENTION_HANDLE_ERROR,
|
|
779
|
+
};
|
|
780
|
+
|
|
781
|
+
var DEFAULT_MEASUREMENT_SETTINGS = {
|
|
782
|
+
delivery: true,
|
|
783
|
+
dispatch_accept: true,
|
|
784
|
+
dispatch_error: true,
|
|
785
|
+
};
|
|
786
|
+
/* Per-tracker state */
|
|
787
|
+
var instances = {}; // entities will likely vary by tracker, so each set will need its own fetcher
|
|
788
|
+
var handlerRegistry = {}; // handlers can be added/removed for individual trackers
|
|
789
|
+
var measurementSettings = {}; // currently global and only specified per-plugin instance but may be required in future
|
|
790
|
+
/**
|
|
791
|
+
* Create an instance of the Signals Interventions plugin.
|
|
792
|
+
* @param configuration Configuration for the plugin
|
|
793
|
+
* @returns Configured plugin instance
|
|
794
|
+
*/
|
|
795
|
+
function SignalsInterventionsPlugin(_a) {
|
|
796
|
+
var _b = _a === void 0 ? {
|
|
797
|
+
measurement: DEFAULT_MEASUREMENT_SETTINGS,
|
|
798
|
+
handlers: {},
|
|
799
|
+
} : _a, fetcher = _b.fetcher, _c = _b.measurement, measurement = _c === void 0 ? DEFAULT_MEASUREMENT_SETTINGS : _c, _d = _b.handlers, handlers = _d === void 0 ? {} : _d;
|
|
800
|
+
return {
|
|
801
|
+
activateBrowserPlugin: function (tracker) {
|
|
802
|
+
var _a;
|
|
803
|
+
logger(LogLevel.INFO, tracker.id, 'Activating plugin for tracker');
|
|
804
|
+
instances[tracker.id] = fetcher ? fetcher(tracker, dispatch) : InterventionFetcher.create(tracker, dispatch);
|
|
805
|
+
measurementSettings[tracker.id] = Object.assign({}, DEFAULT_MEASUREMENT_SETTINGS, measurement);
|
|
806
|
+
handlerRegistry[tracker.id] = Object.assign((_a = handlerRegistry[tracker.id]) !== null && _a !== void 0 ? _a : {}, handlers);
|
|
807
|
+
},
|
|
808
|
+
afterTrack: function (payload) {
|
|
809
|
+
var trackerName = payload['tna'];
|
|
810
|
+
if (typeof trackerName === 'string' && trackerName in instances) {
|
|
811
|
+
instances[trackerName].update(payload);
|
|
812
|
+
}
|
|
813
|
+
},
|
|
814
|
+
logger: function (LOG) {
|
|
815
|
+
setLogger(SignalsInterventionsPlugin.name, LOG);
|
|
816
|
+
},
|
|
817
|
+
};
|
|
818
|
+
}
|
|
819
|
+
/**
|
|
820
|
+
* Tracks an event upon receipt/handling of an intervention unless configured not to.
|
|
821
|
+
* @param settings Measurement settings defining whether an event should fire or not, and configuring custom context
|
|
822
|
+
* @param tracker The tracker to track the event with
|
|
823
|
+
* @param measurement The type of event to track
|
|
824
|
+
* @param intervention The intervention payload in question
|
|
825
|
+
* @param payload An event-specific payload, if required according to `measurement`
|
|
826
|
+
*/
|
|
827
|
+
var measure = function (settings, tracker, measurement, intervention, payload) {
|
|
828
|
+
var _a;
|
|
829
|
+
var filter = settings[measurement];
|
|
830
|
+
if (filter && (typeof filter !== 'function' || filter(intervention))) {
|
|
831
|
+
var entities = [
|
|
832
|
+
{
|
|
833
|
+
schema: Entities.INTERVENTION,
|
|
834
|
+
data: {
|
|
835
|
+
intervention_id: intervention.intervention_id,
|
|
836
|
+
name: intervention.name,
|
|
837
|
+
version: intervention.version,
|
|
838
|
+
entity: intervention.target_entity,
|
|
839
|
+
attributes: intervention.attributes,
|
|
840
|
+
},
|
|
841
|
+
},
|
|
842
|
+
];
|
|
843
|
+
tracker.core.track(buildSelfDescribingEvent({
|
|
844
|
+
event: {
|
|
845
|
+
schema: MEASUREMENT_EVENTS[measurement],
|
|
846
|
+
data: payload,
|
|
847
|
+
},
|
|
848
|
+
}), resolveDynamicContext(__spreadArray(__spreadArray([], entities, true), ((_a = settings.context) !== null && _a !== void 0 ? _a : []), true), measurement, intervention, payload));
|
|
849
|
+
}
|
|
850
|
+
};
|
|
851
|
+
/**
|
|
852
|
+
* Called by the `Fetcher` to track receipt of an Intervention and distribute to any handlers
|
|
853
|
+
* @param intervention The intervention payload that was fetched
|
|
854
|
+
* @param tracker The tracker associated with the plugin
|
|
855
|
+
*/
|
|
856
|
+
var dispatch = function (intervention, tracker) {
|
|
857
|
+
var _a, _b;
|
|
858
|
+
var measurement = (_a = measurementSettings[tracker.id]) !== null && _a !== void 0 ? _a : DEFAULT_MEASUREMENT_SETTINGS;
|
|
859
|
+
var handlers = (_b = handlerRegistry[tracker.id]) !== null && _b !== void 0 ? _b : {};
|
|
860
|
+
var handlerIds = Object.keys(handlers);
|
|
861
|
+
if (!handlerIds.length) {
|
|
862
|
+
return logger(LogLevel.WARN, tracker.id, 'No handlers registered for intervention', intervention);
|
|
863
|
+
}
|
|
864
|
+
logger(LogLevel.INFO, tracker.id, 'Attempting dispatch for intervention', intervention, handlerIds);
|
|
865
|
+
measure(measurement, tracker, 'delivery', intervention, {
|
|
866
|
+
handlers: handlerIds,
|
|
867
|
+
});
|
|
868
|
+
for (var _i = 0, _c = Object.entries(handlers); _i < _c.length; _i++) {
|
|
869
|
+
var _d = _c[_i], handlerId = _d[0], handler = _d[1];
|
|
870
|
+
setTimeout(function (handlerId, handler, intervention, tracker) {
|
|
871
|
+
var success = function () {
|
|
872
|
+
logger(LogLevel.INFO, tracker.id, 'Intervention handled', handlerId, intervention);
|
|
873
|
+
measure(measurement, tracker, 'dispatch_accept', intervention, {
|
|
874
|
+
handler: handlerId,
|
|
875
|
+
});
|
|
876
|
+
};
|
|
877
|
+
var failure = function (err) {
|
|
878
|
+
logger(LogLevel.ERROR, tracker.id, 'Handler failed processing intervention', err, handlerId, intervention);
|
|
879
|
+
measure(measurement, tracker, 'dispatch_error', intervention, {
|
|
880
|
+
handler: handlerId,
|
|
881
|
+
error: err ? String(err) : undefined,
|
|
882
|
+
});
|
|
883
|
+
};
|
|
884
|
+
try {
|
|
885
|
+
var result = handler(intervention, tracker);
|
|
886
|
+
if (result instanceof Promise) {
|
|
887
|
+
result.then(success, failure);
|
|
888
|
+
}
|
|
889
|
+
else if (objWithKey(result, 'then') && typeof result.then === 'function') {
|
|
890
|
+
result.then(success, failure);
|
|
891
|
+
}
|
|
892
|
+
else
|
|
893
|
+
success();
|
|
894
|
+
}
|
|
895
|
+
catch (e) {
|
|
896
|
+
failure(e);
|
|
897
|
+
}
|
|
898
|
+
}, 0, handlerId, handler, intervention, tracker);
|
|
899
|
+
}
|
|
900
|
+
};
|
|
901
|
+
/**
|
|
902
|
+
* Configure the endpoint information for the plugin's `Fetcher` to subscribe to events from
|
|
903
|
+
* @param config Configuration about the endpoint and entity IDs/definitions to configure
|
|
904
|
+
* @param trackers List of tracker IDs that have activated the plugin to configure a `Fetcher` for
|
|
905
|
+
*/
|
|
906
|
+
function subscribeToInterventions(config, trackers) {
|
|
907
|
+
if (trackers === void 0) { trackers = Object.keys(instances); }
|
|
908
|
+
for (var _i = 0, trackers_1 = trackers; _i < trackers_1.length; _i++) {
|
|
909
|
+
var trackerId = trackers_1[_i];
|
|
910
|
+
if (trackerId in instances) {
|
|
911
|
+
instances[trackerId].configure(config);
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
/**
|
|
916
|
+
* Start calling the given handlers when new interventions are received
|
|
917
|
+
* @param handlers Map of handler IDs to handler functions to call with new interventions
|
|
918
|
+
* @param trackers List of tracker IDs that have activated the plugin to add these handlers to
|
|
919
|
+
*/
|
|
920
|
+
function addInterventionHandlers(handlers, trackers) {
|
|
921
|
+
var _a;
|
|
922
|
+
if (trackers === void 0) { trackers = Object.keys(instances); }
|
|
923
|
+
for (var _i = 0, trackers_2 = trackers; _i < trackers_2.length; _i++) {
|
|
924
|
+
var trackerId = trackers_2[_i];
|
|
925
|
+
handlerRegistry[trackerId] = Object.assign((_a = handlerRegistry[trackerId]) !== null && _a !== void 0 ? _a : {}, handlers);
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
/**
|
|
929
|
+
* Stop calling handlers with the given IDs with new interventions
|
|
930
|
+
* @param handlerIds One or more handler IDs to remove
|
|
931
|
+
* @param trackers List of trackers to remove the handlers for; defaults to all trackers that have activated the plugin.
|
|
932
|
+
*/
|
|
933
|
+
function removeInterventionHandlers(handlerIds, trackers) {
|
|
934
|
+
if (trackers === void 0) { trackers = Object.keys(instances); }
|
|
935
|
+
var toRemove = Array.isArray(handlerIds) ? handlerIds : [handlerIds];
|
|
936
|
+
for (var _i = 0, toRemove_1 = toRemove; _i < toRemove_1.length; _i++) {
|
|
937
|
+
var handlerId = toRemove_1[_i];
|
|
938
|
+
for (var _a = 0, trackers_3 = trackers; _a < trackers_3.length; _a++) {
|
|
939
|
+
var trackerId = trackers_3[_a];
|
|
940
|
+
delete handlerRegistry[trackerId][handlerId];
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
exports.SignalsInterventionsPlugin = SignalsInterventionsPlugin;
|
|
946
|
+
exports.addInterventionHandlers = addInterventionHandlers;
|
|
947
|
+
exports.removeInterventionHandlers = removeInterventionHandlers;
|
|
948
|
+
exports.subscribeToInterventions = subscribeToInterventions;
|
|
949
|
+
|
|
950
|
+
}));
|
|
951
|
+
//# sourceMappingURL=index.umd.js.map
|