@usermaven/sdk-js 1.0.4 → 1.0.7
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/README.md +18 -3
- package/dist/npm/usermaven.cjs.js +1528 -283
- package/dist/npm/usermaven.d.ts +161 -15
- package/dist/npm/usermaven.es.js +1526 -284
- package/dist/web/lib.js +1 -0
- package/package.json +14 -13
|
@@ -28,6 +28,56 @@ var __assign = function() {
|
|
|
28
28
|
return __assign.apply(this, arguments);
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
+
function __rest(s, e) {
|
|
32
|
+
var t = {};
|
|
33
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
34
|
+
t[p] = s[p];
|
|
35
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
36
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
37
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
38
|
+
t[p[i]] = s[p[i]];
|
|
39
|
+
}
|
|
40
|
+
return t;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
44
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
45
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
46
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
47
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
48
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
49
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function __generator(thisArg, body) {
|
|
54
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
55
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
56
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
57
|
+
function step(op) {
|
|
58
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
59
|
+
while (_) try {
|
|
60
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
61
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
62
|
+
switch (op[0]) {
|
|
63
|
+
case 0: case 1: t = op; break;
|
|
64
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
65
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
66
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
67
|
+
default:
|
|
68
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
69
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
70
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
71
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
72
|
+
if (t[2]) _.ops.pop();
|
|
73
|
+
_.trys.pop(); continue;
|
|
74
|
+
}
|
|
75
|
+
op = body.call(thisArg, _);
|
|
76
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
77
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
31
81
|
function __spreadArray(to, from, pack) {
|
|
32
82
|
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
33
83
|
if (ar || !(i in from)) {
|
|
@@ -38,24 +88,241 @@ function __spreadArray(to, from, pack) {
|
|
|
38
88
|
return to.concat(ar || Array.prototype.slice.call(from));
|
|
39
89
|
}
|
|
40
90
|
|
|
91
|
+
var LogLevels = {
|
|
92
|
+
DEBUG: { name: "DEBUG", severity: 10 },
|
|
93
|
+
INFO: { name: "INFO", severity: 100 },
|
|
94
|
+
WARN: { name: "WARN", severity: 1000 },
|
|
95
|
+
ERROR: { name: "ERROR", severity: 10000 },
|
|
96
|
+
NONE: { name: "NONE", severity: 10000 }
|
|
97
|
+
};
|
|
98
|
+
var rootLogger = null;
|
|
99
|
+
/**
|
|
100
|
+
* Create logger or return cached instance
|
|
101
|
+
*/
|
|
102
|
+
function getLogger() {
|
|
103
|
+
if (rootLogger) {
|
|
104
|
+
return rootLogger;
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
return rootLogger = createLogger();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function setRootLogLevel(logLevelName) {
|
|
111
|
+
var logLevel = LogLevels[logLevelName.toLocaleUpperCase()];
|
|
112
|
+
if (!logLevel) {
|
|
113
|
+
console.warn("Can't find log level with name ".concat(logLevelName.toLocaleUpperCase(), ", defaulting to INFO"));
|
|
114
|
+
logLevel = LogLevels.INFO;
|
|
115
|
+
}
|
|
116
|
+
rootLogger = createLogger(logLevel);
|
|
117
|
+
return rootLogger;
|
|
118
|
+
}
|
|
119
|
+
function setDebugVar(name, val) {
|
|
120
|
+
if (!isWindowAvailable()) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
var win = window;
|
|
124
|
+
if (!win.__usermavenDebug) {
|
|
125
|
+
win.__usermavenDebug = {};
|
|
126
|
+
}
|
|
127
|
+
win.__usermavenDebug[name] = val;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Creates a loggger with given log-level
|
|
131
|
+
* @param logLevel
|
|
132
|
+
*/
|
|
133
|
+
function createLogger(logLevel) {
|
|
134
|
+
var globalLogLevel = isWindowAvailable() && window['__eventNLogLevel'];
|
|
135
|
+
var minLogLevel = LogLevels.WARN;
|
|
136
|
+
if (globalLogLevel) {
|
|
137
|
+
var level = LogLevels[globalLogLevel.toUpperCase()];
|
|
138
|
+
if (level && level > 0) {
|
|
139
|
+
minLogLevel = level;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
else if (logLevel) {
|
|
143
|
+
minLogLevel = logLevel;
|
|
144
|
+
}
|
|
145
|
+
var logger = { minLogLevel: minLogLevel };
|
|
146
|
+
Object.values(LogLevels).forEach(function (_a) {
|
|
147
|
+
var name = _a.name, severity = _a.severity;
|
|
148
|
+
logger[name.toLowerCase()] = function () {
|
|
149
|
+
var args = [];
|
|
150
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
151
|
+
args[_i] = arguments[_i];
|
|
152
|
+
}
|
|
153
|
+
if (severity >= minLogLevel.severity && args.length > 0) {
|
|
154
|
+
var message = args[0];
|
|
155
|
+
var msgArgs = args.splice(1);
|
|
156
|
+
var msgFormatted = "[J-".concat(name, "] ").concat(message);
|
|
157
|
+
if (name === 'DEBUG' || name === 'INFO') {
|
|
158
|
+
console.log.apply(console, __spreadArray([msgFormatted], msgArgs, false));
|
|
159
|
+
}
|
|
160
|
+
else if (name === 'WARN') {
|
|
161
|
+
console.warn.apply(console, __spreadArray([msgFormatted], msgArgs, false));
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
console.error.apply(console, __spreadArray([msgFormatted], msgArgs, false));
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
});
|
|
169
|
+
setDebugVar("logger", logger);
|
|
170
|
+
return logger;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Checks if global variable 'window' is available. If it's available,
|
|
175
|
+
* code runs in browser environment
|
|
176
|
+
*/
|
|
177
|
+
|
|
178
|
+
function isWindowAvailable(warnMsg = undefined) {
|
|
179
|
+
let windowAvailable = !!globalThis.window;
|
|
180
|
+
if (!windowAvailable && warnMsg) {
|
|
181
|
+
getLogger().warn(warnMsg);
|
|
182
|
+
}
|
|
183
|
+
return windowAvailable;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* @param msg
|
|
189
|
+
* @return {Window}
|
|
190
|
+
*/
|
|
191
|
+
function requireWindow(msg = undefined) {
|
|
192
|
+
if (!isWindowAvailable()) {
|
|
193
|
+
throw new Error(msg || "window' is not available. Seems like this code runs outside browser environment. It shouldn't happen")
|
|
194
|
+
}
|
|
195
|
+
return window;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function serializeCookie(name, val, opt) {
|
|
199
|
+
var _a;
|
|
200
|
+
if (opt === void 0) { opt = {}; }
|
|
201
|
+
var enc = encodeURIComponent;
|
|
202
|
+
var value = enc(val);
|
|
203
|
+
var str = name + "=" + value;
|
|
204
|
+
str += "; Path=" + ((_a = opt.path) !== null && _a !== void 0 ? _a : "/");
|
|
205
|
+
if (opt.maxAge) {
|
|
206
|
+
str += "; Max-Age=" + Math.floor(opt.maxAge);
|
|
207
|
+
}
|
|
208
|
+
if (opt.domain) {
|
|
209
|
+
str += "; Domain=" + opt.domain;
|
|
210
|
+
}
|
|
211
|
+
if (opt.expires) {
|
|
212
|
+
str += "; Expires=" + opt.expires.toUTCString();
|
|
213
|
+
}
|
|
214
|
+
if (opt.httpOnly) {
|
|
215
|
+
str += "; HttpOnly";
|
|
216
|
+
}
|
|
217
|
+
if (opt.secure) {
|
|
218
|
+
str += "; Secure";
|
|
219
|
+
}
|
|
220
|
+
if (opt.sameSite) {
|
|
221
|
+
var sameSite = typeof opt.sameSite === "string"
|
|
222
|
+
? opt.sameSite.toLowerCase()
|
|
223
|
+
: opt.sameSite;
|
|
224
|
+
switch (sameSite) {
|
|
225
|
+
case true:
|
|
226
|
+
str += "; SameSite=Strict";
|
|
227
|
+
break;
|
|
228
|
+
case "lax":
|
|
229
|
+
str += "; SameSite=Lax";
|
|
230
|
+
break;
|
|
231
|
+
case "strict":
|
|
232
|
+
str += "; SameSite=Strict";
|
|
233
|
+
break;
|
|
234
|
+
case "none":
|
|
235
|
+
str += "; SameSite=None";
|
|
236
|
+
break;
|
|
237
|
+
default:
|
|
238
|
+
throw new TypeError("option sameSite is invalid");
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return str;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Courtesy: https://stackoverflow.com/a/23945027
|
|
245
|
+
function extractHostname(url) {
|
|
246
|
+
var hostname;
|
|
247
|
+
//find & remove protocol (http, ftp, etc.) and get hostname
|
|
248
|
+
if (url.indexOf("//") > -1) {
|
|
249
|
+
hostname = url.split('/')[2];
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
hostname = url.split('/')[0];
|
|
253
|
+
}
|
|
254
|
+
//find & remove port number
|
|
255
|
+
hostname = hostname.split(':')[0];
|
|
256
|
+
//find & remove "?"
|
|
257
|
+
hostname = hostname.split('?')[0];
|
|
258
|
+
return hostname;
|
|
259
|
+
}
|
|
260
|
+
// Warning: you can use this function to extract the "root" domain, but it will not be as accurate as using the psl package.
|
|
261
|
+
// https://www.npmjs.com/package/psl
|
|
262
|
+
var extractRootDomain = function (url) {
|
|
263
|
+
var domain = extractHostname(url), splitArr = domain.split('.'), arrLen = splitArr.length;
|
|
264
|
+
//extracting the root domain here
|
|
265
|
+
//if there is a subdomain
|
|
266
|
+
if (arrLen > 2) {
|
|
267
|
+
domain = splitArr[arrLen - 2] + '.' + splitArr[arrLen - 1];
|
|
268
|
+
//check to see if it's using a Country Code Top Level Domain (ccTLD) (i.e. ".me.uk")
|
|
269
|
+
if (splitArr[arrLen - 2].length == 2 && splitArr[arrLen - 1].length == 2) {
|
|
270
|
+
//this is using a ccTLD
|
|
271
|
+
domain = splitArr[arrLen - 3] + '.' + domain;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return domain;
|
|
275
|
+
};
|
|
41
276
|
var getCookieDomain = function () {
|
|
42
|
-
|
|
277
|
+
if (isWindowAvailable()) {
|
|
278
|
+
return ".".concat(extractRootDomain(location.hostname)); // .localhost
|
|
279
|
+
// return window.location.hostname.replace("www.", "");
|
|
280
|
+
}
|
|
281
|
+
return undefined;
|
|
43
282
|
};
|
|
44
283
|
var cookieParsingCache;
|
|
45
|
-
|
|
46
|
-
if (
|
|
47
|
-
|
|
48
|
-
return cookieParsingCache;
|
|
284
|
+
function parseCookieString(cookieStr) {
|
|
285
|
+
if (!cookieStr) {
|
|
286
|
+
return {};
|
|
49
287
|
}
|
|
50
288
|
var res = {};
|
|
51
|
-
var cookies =
|
|
289
|
+
var cookies = cookieStr.split(";");
|
|
52
290
|
for (var i = 0; i < cookies.length; i++) {
|
|
53
291
|
var cookie = cookies[i];
|
|
54
|
-
var idx = cookie.indexOf(
|
|
292
|
+
var idx = cookie.indexOf("=");
|
|
55
293
|
if (idx > 0) {
|
|
56
294
|
res[cookie.substr(i > 0 ? 1 : 0, i > 0 ? idx - 1 : idx)] = cookie.substr(idx + 1);
|
|
57
295
|
}
|
|
58
296
|
}
|
|
297
|
+
return res;
|
|
298
|
+
}
|
|
299
|
+
function copyAttributes(source, target) {
|
|
300
|
+
return Array.from(source.attributes).forEach(function (attribute) {
|
|
301
|
+
target.setAttribute(attribute.nodeName, attribute.nodeValue);
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
function insertAndExecute(element, html) {
|
|
305
|
+
element.innerHTML = html;
|
|
306
|
+
var scripts = element.getElementsByTagName("script");
|
|
307
|
+
var index;
|
|
308
|
+
for (index = scripts.length - 1; index >= 0; index--) {
|
|
309
|
+
var script = scripts[index];
|
|
310
|
+
var tag = document.createElement("script");
|
|
311
|
+
copyAttributes(script, tag);
|
|
312
|
+
if (script.innerHTML) {
|
|
313
|
+
tag.innerHTML = script.innerHTML;
|
|
314
|
+
}
|
|
315
|
+
tag.setAttribute("data-usermaven-tag-id", element.id);
|
|
316
|
+
document.getElementsByTagName("head")[0].appendChild(tag);
|
|
317
|
+
scripts[index].parentNode.removeChild(scripts[index]);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
var getCookies = function (useCache) {
|
|
321
|
+
if (useCache === void 0) { useCache = false; }
|
|
322
|
+
if (useCache && cookieParsingCache) {
|
|
323
|
+
return cookieParsingCache;
|
|
324
|
+
}
|
|
325
|
+
var res = parseCookieString(document.cookie);
|
|
59
326
|
cookieParsingCache = res;
|
|
60
327
|
return res;
|
|
61
328
|
};
|
|
@@ -63,24 +330,30 @@ var getCookie = function (name) {
|
|
|
63
330
|
if (!name) {
|
|
64
331
|
return null;
|
|
65
332
|
}
|
|
66
|
-
return decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" +
|
|
333
|
+
return (decodeURIComponent(requireWindow().document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" +
|
|
334
|
+
encodeURIComponent(name).replace(/[\-\.\+\*]/g, "\\$&") +
|
|
335
|
+
"\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null);
|
|
67
336
|
};
|
|
68
|
-
var setCookie = function (name, value,
|
|
69
|
-
|
|
70
|
-
document.cookie =
|
|
337
|
+
var setCookie = function (name, value, opts) {
|
|
338
|
+
if (opts === void 0) { opts = {}; }
|
|
339
|
+
requireWindow().document.cookie = serializeCookie(name, value, opts);
|
|
71
340
|
};
|
|
72
|
-
var deleteCookie = function (name) {
|
|
73
|
-
|
|
341
|
+
var deleteCookie = function (name, path) {
|
|
342
|
+
if (path === void 0) { path = "/"; }
|
|
343
|
+
document.cookie = name + "= ; expires = Thu, 01 Jan 1970 00:00:00 GMT" + (path ? ("; path = " + path) : "");
|
|
74
344
|
};
|
|
75
345
|
var generateId = function () { return Math.random().toString(36).substring(2, 12); };
|
|
76
346
|
var generateRandom = function () { return Math.random().toString(36).substring(2, 7); };
|
|
77
347
|
var parseQuery = function (qs) {
|
|
78
|
-
|
|
348
|
+
if (!qs) {
|
|
349
|
+
return {};
|
|
350
|
+
}
|
|
351
|
+
var queryString = qs.length > 0 && qs.charAt(0) === "?" ? qs.substring(1) : qs;
|
|
79
352
|
var query = {};
|
|
80
|
-
var pairs = (queryString[0] ===
|
|
353
|
+
var pairs = (queryString[0] === "?" ? queryString.substr(1) : queryString).split("&");
|
|
81
354
|
for (var i = 0; i < pairs.length; i++) {
|
|
82
|
-
var pair = pairs[i].split(
|
|
83
|
-
query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] ||
|
|
355
|
+
var pair = pairs[i].split("=");
|
|
356
|
+
query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || "");
|
|
84
357
|
}
|
|
85
358
|
return query;
|
|
86
359
|
};
|
|
@@ -99,7 +372,7 @@ var CLICK_IDS = {
|
|
|
99
372
|
var getDataFromParams = function (params) {
|
|
100
373
|
var result = {
|
|
101
374
|
utm: {},
|
|
102
|
-
click_id: {}
|
|
375
|
+
click_id: {},
|
|
103
376
|
};
|
|
104
377
|
for (var name in params) {
|
|
105
378
|
if (!params.hasOwnProperty(name)) {
|
|
@@ -118,14 +391,14 @@ var getDataFromParams = function (params) {
|
|
|
118
391
|
};
|
|
119
392
|
//2020-08-24T13:42:16.439Z -> 2020-08-24T13:42:16.439123Z
|
|
120
393
|
var reformatDate = function (strDate) {
|
|
121
|
-
var end = strDate.split(
|
|
394
|
+
var end = strDate.split(".")[1];
|
|
122
395
|
if (!end) {
|
|
123
396
|
return strDate;
|
|
124
397
|
}
|
|
125
398
|
if (end.length >= 7) {
|
|
126
399
|
return strDate;
|
|
127
400
|
}
|
|
128
|
-
return strDate.slice(0, -1) +
|
|
401
|
+
return strDate.slice(0, -1) + "0".repeat(7 - end.length) + "Z";
|
|
129
402
|
};
|
|
130
403
|
function endsWith(str, suffix) {
|
|
131
404
|
return str.indexOf(suffix, str.length - suffix.length) !== -1;
|
|
@@ -142,85 +415,6 @@ var getHostWithProtocol = function (host) {
|
|
|
142
415
|
}
|
|
143
416
|
};
|
|
144
417
|
|
|
145
|
-
var LogLevels = {
|
|
146
|
-
DEBUG: { name: "DEBUG", severity: 10 },
|
|
147
|
-
INFO: { name: "INFO", severity: 100 },
|
|
148
|
-
WARN: { name: "WARN", severity: 1000 },
|
|
149
|
-
ERROR: { name: "ERROR", severity: 10000 },
|
|
150
|
-
NONE: { name: "NONE", severity: 10000 }
|
|
151
|
-
};
|
|
152
|
-
var rootLogger = null;
|
|
153
|
-
/**
|
|
154
|
-
* Create logger or return cached instance
|
|
155
|
-
*/
|
|
156
|
-
function getLogger() {
|
|
157
|
-
if (rootLogger) {
|
|
158
|
-
return rootLogger;
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
return rootLogger = createLogger();
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
function setRootLogLevel(logLevelName) {
|
|
165
|
-
var logLevel = LogLevels[logLevelName.toLocaleUpperCase()];
|
|
166
|
-
if (!logLevel) {
|
|
167
|
-
console.warn("Can't find log level with name ".concat(logLevelName.toLocaleUpperCase(), ", defaulting to INFO"));
|
|
168
|
-
logLevel = LogLevels.INFO;
|
|
169
|
-
}
|
|
170
|
-
rootLogger = createLogger(logLevel);
|
|
171
|
-
return rootLogger;
|
|
172
|
-
}
|
|
173
|
-
function setDebugVar(name, val) {
|
|
174
|
-
var win = window;
|
|
175
|
-
if (!win.__usermavenDebug) {
|
|
176
|
-
win.__usermavenDebug = {};
|
|
177
|
-
}
|
|
178
|
-
win.__usermavenDebug[name] = val;
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* Creates a loggger with given log-level
|
|
182
|
-
* @param logLevel
|
|
183
|
-
*/
|
|
184
|
-
function createLogger(logLevel) {
|
|
185
|
-
var globalLogLevel = window['__eventNLogLevel'];
|
|
186
|
-
var minLogLevel = LogLevels.WARN;
|
|
187
|
-
if (globalLogLevel) {
|
|
188
|
-
var level = LogLevels[globalLogLevel.toUpperCase()];
|
|
189
|
-
if (level && level > 0) {
|
|
190
|
-
minLogLevel = level;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
else if (logLevel) {
|
|
194
|
-
minLogLevel = logLevel;
|
|
195
|
-
}
|
|
196
|
-
var logger = { minLogLevel: minLogLevel };
|
|
197
|
-
Object.values(LogLevels).forEach(function (_a) {
|
|
198
|
-
var name = _a.name, severity = _a.severity;
|
|
199
|
-
logger[name.toLowerCase()] = function () {
|
|
200
|
-
var args = [];
|
|
201
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
202
|
-
args[_i] = arguments[_i];
|
|
203
|
-
}
|
|
204
|
-
if (severity >= minLogLevel.severity && args.length > 0) {
|
|
205
|
-
var message = args[0];
|
|
206
|
-
var msgArgs = args.splice(1);
|
|
207
|
-
var msgFormatted = "[J-".concat(name, "] ").concat(message);
|
|
208
|
-
if (name === 'DEBUG' || name === 'INFO') {
|
|
209
|
-
console.log.apply(console, __spreadArray([msgFormatted], msgArgs, false));
|
|
210
|
-
}
|
|
211
|
-
else if (name === 'WARN') {
|
|
212
|
-
console.warn.apply(console, __spreadArray([msgFormatted], msgArgs, false));
|
|
213
|
-
}
|
|
214
|
-
else {
|
|
215
|
-
console.error.apply(console, __spreadArray([msgFormatted], msgArgs, false));
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
};
|
|
219
|
-
});
|
|
220
|
-
setDebugVar("logger", logger);
|
|
221
|
-
return logger;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
418
|
var Config$1 = {
|
|
225
419
|
DEBUG: false,
|
|
226
420
|
LIB_VERSION: '1.0.0',
|
|
@@ -866,7 +1060,7 @@ _.info = {
|
|
|
866
1060
|
|
|
867
1061
|
var keyword = _.getQueryParam(referrer, param);
|
|
868
1062
|
if (keyword.length) {
|
|
869
|
-
ret['
|
|
1063
|
+
ret['um_keyword'] = keyword;
|
|
870
1064
|
}
|
|
871
1065
|
}
|
|
872
1066
|
|
|
@@ -1619,14 +1813,12 @@ UserMavenPersistence.prototype.remove_event_timer = function (event_name) {
|
|
|
1619
1813
|
return timestamp
|
|
1620
1814
|
};
|
|
1621
1815
|
|
|
1622
|
-
// import { INCREMENTAL_SNAPSHOT_EVENT_TYPE, MUTATION_SOURCE_TYPE } from './extensions/sessionrecording'
|
|
1623
|
-
|
|
1624
|
-
const SESSION_CHANGE_THRESHOLD = 30 * 60 * 1000; // 30 mins
|
|
1625
|
-
/* const SESSION_CHANGE_THRESHOLD = 1 * 60 * 1000 // 1 min */
|
|
1626
|
-
|
|
1627
1816
|
class SessionIdManager {
|
|
1628
1817
|
constructor(config, persistence) {
|
|
1629
1818
|
this.persistence = persistence;
|
|
1819
|
+
this.session_change_threshold = config['persistence_time'] || 1800; // 30 mins
|
|
1820
|
+
// this.session_change_threshold = config['persistence_time'] || 60 // 1 min
|
|
1821
|
+
this.session_change_threshold *= 1000;
|
|
1630
1822
|
|
|
1631
1823
|
if (config['persistence_name']) {
|
|
1632
1824
|
this.window_id_storage_key = 'um_' + config['persistence_name'] + '_window_id';
|
|
@@ -1685,6 +1877,9 @@ class SessionIdManager {
|
|
|
1685
1877
|
// Some recording events are triggered by non-user events (e.g. "X minutes ago" text updating on the screen).
|
|
1686
1878
|
// We don't want to update the session and window ids in these cases. These events are designated by event
|
|
1687
1879
|
// type -> incremental update, and source -> mutation.
|
|
1880
|
+
if (this.persistence.disabled) {
|
|
1881
|
+
return {}
|
|
1882
|
+
}
|
|
1688
1883
|
/* const isUserInteraction = !(
|
|
1689
1884
|
recordingEvent &&
|
|
1690
1885
|
recordingEvent.type === INCREMENTAL_SNAPSHOT_EVENT_TYPE &&
|
|
@@ -1698,7 +1893,7 @@ class SessionIdManager {
|
|
|
1698
1893
|
let [lastTimestamp, sessionId] = this._getSessionId();
|
|
1699
1894
|
let windowId = this._getWindowId();
|
|
1700
1895
|
|
|
1701
|
-
if (!sessionId || (Math.abs(timestamp - lastTimestamp) >
|
|
1896
|
+
if (!sessionId || (Math.abs(timestamp - lastTimestamp) > this.session_change_threshold)) {
|
|
1702
1897
|
sessionId = _.UUID();
|
|
1703
1898
|
windowId = _.UUID();
|
|
1704
1899
|
} else if (!windowId) {
|
|
@@ -1709,184 +1904,1015 @@ class SessionIdManager {
|
|
|
1709
1904
|
|
|
1710
1905
|
this._setWindowId(windowId);
|
|
1711
1906
|
this._setSessionId(sessionId, newTimestamp);
|
|
1712
|
-
|
|
1713
1907
|
return {
|
|
1714
|
-
|
|
1715
|
-
|
|
1908
|
+
session_id: sessionId,
|
|
1909
|
+
window_id: windowId,
|
|
1716
1910
|
}
|
|
1717
1911
|
}
|
|
1718
1912
|
}
|
|
1719
1913
|
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
this.cookieDomain = cookieDomain;
|
|
1735
|
-
this.cookieName = cookieName;
|
|
1914
|
+
/*
|
|
1915
|
+
* Get the className of an element, accounting for edge cases where element.className is an object
|
|
1916
|
+
* @param {Element} el - element to get the className of
|
|
1917
|
+
* @returns {string} the element's class
|
|
1918
|
+
*/
|
|
1919
|
+
function getClassName(el) {
|
|
1920
|
+
switch (typeof el.className) {
|
|
1921
|
+
case 'string':
|
|
1922
|
+
return el.className
|
|
1923
|
+
case 'object': // handle cases where className might be SVGAnimatedString or some other type
|
|
1924
|
+
return el.className.baseVal || el.getAttribute('class') || ''
|
|
1925
|
+
default:
|
|
1926
|
+
// future proof
|
|
1927
|
+
return ''
|
|
1736
1928
|
}
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1929
|
+
}
|
|
1930
|
+
|
|
1931
|
+
/*
|
|
1932
|
+
* Get the direct text content of an element, protecting against sensitive data collection.
|
|
1933
|
+
* Concats textContent of each of the element's text node children; this avoids potential
|
|
1934
|
+
* collection of sensitive data that could happen if we used element.textContent and the
|
|
1935
|
+
* element had sensitive child elements, since element.textContent includes child content.
|
|
1936
|
+
* Scrubs values that look like they could be sensitive (i.e. cc or ssn number).
|
|
1937
|
+
* @param {Element} el - element to get the text of
|
|
1938
|
+
* @returns {string} the element's direct text content
|
|
1939
|
+
*/
|
|
1940
|
+
function getSafeText(el) {
|
|
1941
|
+
var elText = '';
|
|
1942
|
+
|
|
1943
|
+
if (shouldCaptureElement(el) && !isSensitiveElement(el) && el.childNodes && el.childNodes.length) {
|
|
1944
|
+
_.each(el.childNodes, function (child) {
|
|
1945
|
+
if (isTextNode(child) && child.textContent) {
|
|
1946
|
+
elText += _.trim(child.textContent)
|
|
1947
|
+
// scrub potentially sensitive values
|
|
1948
|
+
.split(/(\s+)/)
|
|
1949
|
+
.filter(shouldCaptureValue)
|
|
1950
|
+
.join('')
|
|
1951
|
+
// normalize whitespace
|
|
1952
|
+
.replace(/[\r\n]/g, ' ')
|
|
1953
|
+
.replace(/[ ]+/g, ' ')
|
|
1954
|
+
// truncate
|
|
1955
|
+
.substring(0, 255);
|
|
1754
1956
|
}
|
|
1755
|
-
}
|
|
1756
|
-
return undefined;
|
|
1757
|
-
};
|
|
1758
|
-
CookiePersistence.prototype.delete = function () {
|
|
1759
|
-
deleteCookie(this.cookieName);
|
|
1760
|
-
};
|
|
1761
|
-
return CookiePersistence;
|
|
1762
|
-
}());
|
|
1763
|
-
var NoPersistence = /** @class */ (function () {
|
|
1764
|
-
function NoPersistence() {
|
|
1957
|
+
});
|
|
1765
1958
|
}
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
NoPersistence.prototype.restore = function () {
|
|
1769
|
-
return undefined;
|
|
1770
|
-
};
|
|
1771
|
-
NoPersistence.prototype.delete = function () { };
|
|
1772
|
-
return NoPersistence;
|
|
1773
|
-
}());
|
|
1774
|
-
var defaultCompatMode = false;
|
|
1775
|
-
function usermavenClient(opts) {
|
|
1776
|
-
var client = new UsermavenClientImpl();
|
|
1777
|
-
client.init(opts);
|
|
1778
|
-
return client;
|
|
1959
|
+
|
|
1960
|
+
return _.trim(elText)
|
|
1779
1961
|
}
|
|
1962
|
+
|
|
1963
|
+
/*
|
|
1964
|
+
* Check whether an element has nodeType Node.ELEMENT_NODE
|
|
1965
|
+
* @param {Element} el - element to check
|
|
1966
|
+
* @returns {boolean} whether el is of the correct nodeType
|
|
1967
|
+
*/
|
|
1968
|
+
function isElementNode(el) {
|
|
1969
|
+
return el && el.nodeType === 1 // Node.ELEMENT_NODE - use integer constant for browser portability
|
|
1970
|
+
}
|
|
1971
|
+
|
|
1972
|
+
/*
|
|
1973
|
+
* Check whether an element is of a given tag type.
|
|
1974
|
+
* Due to potential reference discrepancies (such as the webcomponents.js polyfill),
|
|
1975
|
+
* we want to match tagNames instead of specific references because something like
|
|
1976
|
+
* element === document.body won't always work because element might not be a native
|
|
1977
|
+
* element.
|
|
1978
|
+
* @param {Element} el - element to check
|
|
1979
|
+
* @param {string} tag - tag name (e.g., "div")
|
|
1980
|
+
* @returns {boolean} whether el is of the given tag type
|
|
1981
|
+
*/
|
|
1982
|
+
function isTag(el, tag) {
|
|
1983
|
+
return el && el.tagName && el.tagName.toLowerCase() === tag.toLowerCase()
|
|
1984
|
+
}
|
|
1985
|
+
|
|
1986
|
+
/*
|
|
1987
|
+
* Check whether an element has nodeType Node.TEXT_NODE
|
|
1988
|
+
* @param {Element} el - element to check
|
|
1989
|
+
* @returns {boolean} whether el is of the correct nodeType
|
|
1990
|
+
*/
|
|
1991
|
+
function isTextNode(el) {
|
|
1992
|
+
return el && el.nodeType === 3 // Node.TEXT_NODE - use integer constant for browser portability
|
|
1993
|
+
}
|
|
1994
|
+
|
|
1995
|
+
var usefulElements = ['a', 'button', 'form', 'input', 'select', 'textarea', 'label'];
|
|
1996
|
+
/*
|
|
1997
|
+
* Check whether a DOM event should be "captured" or if it may contain sentitive data
|
|
1998
|
+
* using a variety of heuristics.
|
|
1999
|
+
* @param {Element} el - element to check
|
|
2000
|
+
* @param {Event} event - event to check
|
|
2001
|
+
* @returns {boolean} whether the event should be captured
|
|
2002
|
+
*/
|
|
2003
|
+
function shouldCaptureDomEvent(el, event) {
|
|
2004
|
+
if (!el || isTag(el, 'html') || !isElementNode(el)) {
|
|
2005
|
+
return false
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
var parentIsUsefulElement = false;
|
|
2009
|
+
var targetElementList = [el];
|
|
2010
|
+
var parentNode = true;
|
|
2011
|
+
var curEl = el;
|
|
2012
|
+
while (curEl.parentNode && !isTag(curEl, 'body')) {
|
|
2013
|
+
// If element is a shadow root, we skip it
|
|
2014
|
+
if (curEl.parentNode.nodeType === 11) {
|
|
2015
|
+
targetElementList.push(curEl.parentNode.host);
|
|
2016
|
+
curEl = curEl.parentNode.host;
|
|
2017
|
+
continue
|
|
2018
|
+
}
|
|
2019
|
+
parentNode = curEl.parentNode;
|
|
2020
|
+
if (!parentNode) break
|
|
2021
|
+
if (usefulElements.indexOf(parentNode.tagName.toLowerCase()) > -1) {
|
|
2022
|
+
parentIsUsefulElement = true;
|
|
2023
|
+
} else {
|
|
2024
|
+
let compStyles = window.getComputedStyle(parentNode);
|
|
2025
|
+
if (compStyles && compStyles.getPropertyValue('cursor') === 'pointer') {
|
|
2026
|
+
parentIsUsefulElement = true;
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
|
|
2030
|
+
targetElementList.push(parentNode);
|
|
2031
|
+
curEl = parentNode;
|
|
2032
|
+
}
|
|
2033
|
+
|
|
2034
|
+
let compStyles = window.getComputedStyle(el);
|
|
2035
|
+
if (compStyles && compStyles.getPropertyValue('cursor') === 'pointer' && event.type === 'click') {
|
|
2036
|
+
return true
|
|
2037
|
+
}
|
|
2038
|
+
|
|
2039
|
+
var tag = el.tagName.toLowerCase();
|
|
2040
|
+
switch (tag) {
|
|
2041
|
+
case 'html':
|
|
2042
|
+
return false
|
|
2043
|
+
case 'form':
|
|
2044
|
+
return event.type === 'submit'
|
|
2045
|
+
case 'input':
|
|
2046
|
+
return event.type === 'change' || event.type === 'click'
|
|
2047
|
+
case 'select':
|
|
2048
|
+
case 'textarea':
|
|
2049
|
+
return event.type === 'change' || event.type === 'click'
|
|
2050
|
+
default:
|
|
2051
|
+
if (parentIsUsefulElement) return event.type === 'click'
|
|
2052
|
+
return (
|
|
2053
|
+
event.type === 'click' &&
|
|
2054
|
+
(usefulElements.indexOf(tag) > -1 || el.getAttribute('contenteditable') === 'true')
|
|
2055
|
+
)
|
|
2056
|
+
}
|
|
2057
|
+
}
|
|
2058
|
+
|
|
2059
|
+
/*
|
|
2060
|
+
* Check whether a DOM element should be "captured" or if it may contain sentitive data
|
|
2061
|
+
* using a variety of heuristics.
|
|
2062
|
+
* @param {Element} el - element to check
|
|
2063
|
+
* @returns {boolean} whether the element should be captured
|
|
2064
|
+
*/
|
|
2065
|
+
function shouldCaptureElement(el) {
|
|
2066
|
+
for (var curEl = el; curEl.parentNode && !isTag(curEl, 'body'); curEl = curEl.parentNode) {
|
|
2067
|
+
var classes = getClassName(curEl).split(' ');
|
|
2068
|
+
if (_.includes(classes, 'um-sensitive') || _.includes(classes, 'um-no-capture')) {
|
|
2069
|
+
return false
|
|
2070
|
+
}
|
|
2071
|
+
}
|
|
2072
|
+
|
|
2073
|
+
if (_.includes(getClassName(el).split(' '), 'um-include')) {
|
|
2074
|
+
return true
|
|
2075
|
+
}
|
|
2076
|
+
|
|
2077
|
+
// don't include hidden or password fields
|
|
2078
|
+
var type = el.type || '';
|
|
2079
|
+
if (typeof type === 'string') {
|
|
2080
|
+
// it's possible for el.type to be a DOM element if el is a form with a child input[name="type"]
|
|
2081
|
+
switch (type.toLowerCase()) {
|
|
2082
|
+
case 'hidden':
|
|
2083
|
+
return false
|
|
2084
|
+
case 'password':
|
|
2085
|
+
return false
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
|
|
2089
|
+
// filter out data from fields that look like sensitive fields
|
|
2090
|
+
var name = el.name || el.id || '';
|
|
2091
|
+
if (typeof name === 'string') {
|
|
2092
|
+
// it's possible for el.name or el.id to be a DOM element if el is a form with a child input[name="name"]
|
|
2093
|
+
var sensitiveNameRegex = /^cc|cardnum|ccnum|creditcard|csc|cvc|cvv|exp|pass|pwd|routing|seccode|securitycode|securitynum|socialsec|socsec|ssn/i;
|
|
2094
|
+
if (sensitiveNameRegex.test(name.replace(/[^a-zA-Z0-9]/g, ''))) {
|
|
2095
|
+
return false
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
|
|
2099
|
+
return true
|
|
2100
|
+
}
|
|
2101
|
+
|
|
2102
|
+
/*
|
|
2103
|
+
* Check whether a DOM element is 'sensitive' and we should only capture limited data
|
|
2104
|
+
* @param {Element} el - element to check
|
|
2105
|
+
* @returns {boolean} whether the element should be captured
|
|
2106
|
+
*/
|
|
2107
|
+
function isSensitiveElement(el) {
|
|
2108
|
+
// don't send data from inputs or similar elements since there will always be
|
|
2109
|
+
// a risk of clientside javascript placing sensitive data in attributes
|
|
2110
|
+
const allowedInputTypes = ['button', 'checkbox', 'submit', 'reset'];
|
|
2111
|
+
if (
|
|
2112
|
+
(isTag(el, 'input') && !allowedInputTypes.includes(el.type)) ||
|
|
2113
|
+
isTag(el, 'select') ||
|
|
2114
|
+
isTag(el, 'textarea') ||
|
|
2115
|
+
el.getAttribute('contenteditable') === 'true'
|
|
2116
|
+
) {
|
|
2117
|
+
return true
|
|
2118
|
+
}
|
|
2119
|
+
return false
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2122
|
+
/*
|
|
2123
|
+
* Check whether a string value should be "captured" or if it may contain sentitive data
|
|
2124
|
+
* using a variety of heuristics.
|
|
2125
|
+
* @param {string} value - string value to check
|
|
2126
|
+
* @returns {boolean} whether the element should be captured
|
|
2127
|
+
*/
|
|
2128
|
+
function shouldCaptureValue(value) {
|
|
2129
|
+
if (value === null || _.isUndefined(value)) {
|
|
2130
|
+
return false
|
|
2131
|
+
}
|
|
2132
|
+
|
|
2133
|
+
if (typeof value === 'string') {
|
|
2134
|
+
value = _.trim(value);
|
|
2135
|
+
|
|
2136
|
+
// check to see if input value looks like a credit card number
|
|
2137
|
+
// see: https://www.safaribooksonline.com/library/view/regular-expressions-cookbook/9781449327453/ch04s20.html
|
|
2138
|
+
var ccRegex = /^(?:(4[0-9]{12}(?:[0-9]{3})?)|(5[1-5][0-9]{14})|(6(?:011|5[0-9]{2})[0-9]{12})|(3[47][0-9]{13})|(3(?:0[0-5]|[68][0-9])[0-9]{11})|((?:2131|1800|35[0-9]{3})[0-9]{11}))$/;
|
|
2139
|
+
if (ccRegex.test((value || '').replace(/[- ]/g, ''))) {
|
|
2140
|
+
return false
|
|
2141
|
+
}
|
|
2142
|
+
|
|
2143
|
+
// check to see if input value looks like a social security number
|
|
2144
|
+
var ssnRegex = /(^\d{3}-?\d{2}-?\d{4}$)/;
|
|
2145
|
+
if (ssnRegex.test(value)) {
|
|
2146
|
+
return false
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
|
|
2150
|
+
return true
|
|
2151
|
+
}
|
|
2152
|
+
|
|
2153
|
+
/*
|
|
2154
|
+
* Check whether an attribute name is an Angular style attr (either _ngcontent or _nghost)
|
|
2155
|
+
* These update on each build and lead to noise in the element chain
|
|
2156
|
+
* More details on the attributes here: https://angular.io/guide/view-encapsulation
|
|
2157
|
+
* @param {string} attributeName - string value to check
|
|
2158
|
+
* @returns {boolean} whether the element is an angular tag
|
|
2159
|
+
*/
|
|
2160
|
+
function isAngularStyleAttr(attributeName) {
|
|
2161
|
+
if (typeof attributeName === 'string') {
|
|
2162
|
+
return attributeName.substring(0, 10) === '_ngcontent' || attributeName.substring(0, 7) === '_nghost'
|
|
2163
|
+
}
|
|
2164
|
+
return false
|
|
2165
|
+
}
|
|
2166
|
+
|
|
2167
|
+
// Naive rage click implementation: If mouse has not moved than RAGE_CLICK_THRESHOLD_PX
|
|
2168
|
+
// over RAGE_CLICK_CLICK_COUNT clicks with max RAGE_CLICK_TIMEOUT_MS between clicks, it's
|
|
2169
|
+
// counted as a rage click
|
|
2170
|
+
const RAGE_CLICK_THRESHOLD_PX = 30;
|
|
2171
|
+
const RAGE_CLICK_TIMEOUT_MS = 1000;
|
|
2172
|
+
const RAGE_CLICK_CLICK_COUNT = 3;
|
|
2173
|
+
|
|
2174
|
+
class RageClick {
|
|
2175
|
+
constructor(instance, enabled = instance.get_config('rageclick')) {
|
|
2176
|
+
this.clicks = [];
|
|
2177
|
+
this.instance = instance;
|
|
2178
|
+
this.enabled = enabled;
|
|
2179
|
+
}
|
|
2180
|
+
|
|
2181
|
+
click(x, y, timestamp) {
|
|
2182
|
+
if (!this.enabled) {
|
|
2183
|
+
return
|
|
2184
|
+
}
|
|
2185
|
+
|
|
2186
|
+
const lastClick = this.clicks[this.clicks.length - 1];
|
|
2187
|
+
if (
|
|
2188
|
+
lastClick &&
|
|
2189
|
+
Math.abs(x - lastClick.x) + Math.abs(y - lastClick.y) < RAGE_CLICK_THRESHOLD_PX &&
|
|
2190
|
+
timestamp - lastClick.timestamp < RAGE_CLICK_TIMEOUT_MS
|
|
2191
|
+
) {
|
|
2192
|
+
this.clicks.push({ x, y, timestamp });
|
|
2193
|
+
|
|
2194
|
+
if (this.clicks.length === RAGE_CLICK_CLICK_COUNT) {
|
|
2195
|
+
this.instance.capture('$rageclick');
|
|
2196
|
+
}
|
|
2197
|
+
} else {
|
|
2198
|
+
this.clicks = [{ x, y, timestamp }];
|
|
2199
|
+
}
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
|
|
2203
|
+
var autocapture = {
|
|
2204
|
+
_initializedTokens: [],
|
|
2205
|
+
|
|
2206
|
+
_previousElementSibling: function (el) {
|
|
2207
|
+
if (el.previousElementSibling) {
|
|
2208
|
+
return el.previousElementSibling
|
|
2209
|
+
} else {
|
|
2210
|
+
do {
|
|
2211
|
+
el = el.previousSibling;
|
|
2212
|
+
} while (el && !isElementNode(el))
|
|
2213
|
+
return el
|
|
2214
|
+
}
|
|
2215
|
+
},
|
|
2216
|
+
|
|
2217
|
+
_getPropertiesFromElement: function (elem, maskInputs, maskText) {
|
|
2218
|
+
var tag_name = elem.tagName.toLowerCase();
|
|
2219
|
+
var props = {
|
|
2220
|
+
tag_name: tag_name,
|
|
2221
|
+
};
|
|
2222
|
+
if (usefulElements.indexOf(tag_name) > -1 && !maskText) {
|
|
2223
|
+
props['$el_text'] = getSafeText(elem);
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
var classes = getClassName(elem);
|
|
2227
|
+
if (classes.length > 0)
|
|
2228
|
+
props['classes'] = classes.split(' ').filter(function (c) {
|
|
2229
|
+
return c !== ''
|
|
2230
|
+
});
|
|
2231
|
+
|
|
2232
|
+
_.each(elem.attributes, function (attr) {
|
|
2233
|
+
// Only capture attributes we know are safe
|
|
2234
|
+
if (isSensitiveElement(elem) && ['name', 'id', 'class'].indexOf(attr.name) === -1) return
|
|
2235
|
+
|
|
2236
|
+
if (!maskInputs && shouldCaptureValue(attr.value) && !isAngularStyleAttr(attr.name)) {
|
|
2237
|
+
props['attr__' + attr.name] = attr.value;
|
|
2238
|
+
}
|
|
2239
|
+
});
|
|
2240
|
+
|
|
2241
|
+
var nthChild = 1;
|
|
2242
|
+
var nthOfType = 1;
|
|
2243
|
+
var currentElem = elem;
|
|
2244
|
+
while ((currentElem = this._previousElementSibling(currentElem))) {
|
|
2245
|
+
// eslint-disable-line no-cond-assign
|
|
2246
|
+
nthChild++;
|
|
2247
|
+
if (currentElem.tagName === elem.tagName) {
|
|
2248
|
+
nthOfType++;
|
|
2249
|
+
}
|
|
2250
|
+
}
|
|
2251
|
+
props['nth_child'] = nthChild;
|
|
2252
|
+
props['nth_of_type'] = nthOfType;
|
|
2253
|
+
|
|
2254
|
+
return props
|
|
2255
|
+
},
|
|
2256
|
+
|
|
2257
|
+
_getDefaultProperties: function (eventType) {
|
|
2258
|
+
return {
|
|
2259
|
+
$event_type: eventType,
|
|
2260
|
+
$ce_version: 1,
|
|
2261
|
+
}
|
|
2262
|
+
},
|
|
2263
|
+
|
|
2264
|
+
_extractCustomPropertyValue: function (customProperty) {
|
|
2265
|
+
var propValues = [];
|
|
2266
|
+
_.each(document.querySelectorAll(customProperty['css_selector']), function (matchedElem) {
|
|
2267
|
+
var value;
|
|
2268
|
+
|
|
2269
|
+
if (['input', 'select'].indexOf(matchedElem.tagName.toLowerCase()) > -1) {
|
|
2270
|
+
value = matchedElem['value'];
|
|
2271
|
+
} else if (matchedElem['textContent']) {
|
|
2272
|
+
value = matchedElem['textContent'];
|
|
2273
|
+
}
|
|
2274
|
+
|
|
2275
|
+
if (shouldCaptureValue(value)) {
|
|
2276
|
+
propValues.push(value);
|
|
2277
|
+
}
|
|
2278
|
+
});
|
|
2279
|
+
return propValues.join(', ')
|
|
2280
|
+
},
|
|
2281
|
+
|
|
2282
|
+
_getCustomProperties: function (targetElementList) {
|
|
2283
|
+
var props = {};
|
|
2284
|
+
_.each(
|
|
2285
|
+
this._customProperties,
|
|
2286
|
+
function (customProperty) {
|
|
2287
|
+
_.each(
|
|
2288
|
+
customProperty['event_selectors'],
|
|
2289
|
+
function (eventSelector) {
|
|
2290
|
+
var eventElements = document.querySelectorAll(eventSelector);
|
|
2291
|
+
_.each(
|
|
2292
|
+
eventElements,
|
|
2293
|
+
function (eventElement) {
|
|
2294
|
+
if (_.includes(targetElementList, eventElement) && shouldCaptureElement(eventElement)) {
|
|
2295
|
+
props[customProperty['name']] = this._extractCustomPropertyValue(customProperty);
|
|
2296
|
+
}
|
|
2297
|
+
},
|
|
2298
|
+
this
|
|
2299
|
+
);
|
|
2300
|
+
},
|
|
2301
|
+
this
|
|
2302
|
+
);
|
|
2303
|
+
},
|
|
2304
|
+
this
|
|
2305
|
+
);
|
|
2306
|
+
return props
|
|
2307
|
+
},
|
|
2308
|
+
|
|
2309
|
+
_getEventTarget: function (e) {
|
|
2310
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Event/target#Compatibility_notes
|
|
2311
|
+
if (typeof e.target === 'undefined') {
|
|
2312
|
+
return e.srcElement
|
|
2313
|
+
} else {
|
|
2314
|
+
if (e.target.shadowRoot) {
|
|
2315
|
+
return e.composedPath()[0]
|
|
2316
|
+
}
|
|
2317
|
+
return e.target
|
|
2318
|
+
}
|
|
2319
|
+
},
|
|
2320
|
+
|
|
2321
|
+
_captureEvent: function (e, instance) {
|
|
2322
|
+
/*** Don't mess with this code without running IE8 tests on it ***/
|
|
2323
|
+
var target = this._getEventTarget(e);
|
|
2324
|
+
if (isTextNode(target)) {
|
|
2325
|
+
// defeat Safari bug (see: http://www.quirksmode.org/js/events_properties.html)
|
|
2326
|
+
target = target.parentNode;
|
|
2327
|
+
}
|
|
2328
|
+
|
|
2329
|
+
if (e.type === 'click') {
|
|
2330
|
+
this.rageclicks.click(e.clientX, e.clientY, new Date().getTime());
|
|
2331
|
+
}
|
|
2332
|
+
|
|
2333
|
+
if (shouldCaptureDomEvent(target, e)) {
|
|
2334
|
+
var targetElementList = [target];
|
|
2335
|
+
var curEl = target;
|
|
2336
|
+
while (curEl.parentNode && !isTag(curEl, 'body')) {
|
|
2337
|
+
if (curEl.parentNode.nodeType === 11) {
|
|
2338
|
+
targetElementList.push(curEl.parentNode.host);
|
|
2339
|
+
curEl = curEl.parentNode.host;
|
|
2340
|
+
continue
|
|
2341
|
+
}
|
|
2342
|
+
targetElementList.push(curEl.parentNode);
|
|
2343
|
+
curEl = curEl.parentNode;
|
|
2344
|
+
}
|
|
2345
|
+
|
|
2346
|
+
var elementsJson = [];
|
|
2347
|
+
var href,
|
|
2348
|
+
explicitNoCapture = false;
|
|
2349
|
+
_.each(
|
|
2350
|
+
targetElementList,
|
|
2351
|
+
function (el) {
|
|
2352
|
+
var shouldCaptureEl = shouldCaptureElement(el);
|
|
2353
|
+
|
|
2354
|
+
// if the element or a parent element is an anchor tag
|
|
2355
|
+
// include the href as a property
|
|
2356
|
+
if (el.tagName.toLowerCase() === 'a') {
|
|
2357
|
+
href = el.getAttribute('href');
|
|
2358
|
+
href = shouldCaptureEl && shouldCaptureValue(href) && href;
|
|
2359
|
+
}
|
|
2360
|
+
|
|
2361
|
+
// allow users to programmatically prevent capturing of elements by adding class 'um-no-capture'
|
|
2362
|
+
var classes = getClassName(el).split(' ');
|
|
2363
|
+
if (_.includes(classes, 'um-no-capture')) {
|
|
2364
|
+
explicitNoCapture = true;
|
|
2365
|
+
}
|
|
2366
|
+
|
|
2367
|
+
elementsJson.push(
|
|
2368
|
+
this._getPropertiesFromElement(
|
|
2369
|
+
el,
|
|
2370
|
+
instance.get_config('mask_all_element_attributes'),
|
|
2371
|
+
instance.get_config('mask_all_text')
|
|
2372
|
+
)
|
|
2373
|
+
);
|
|
2374
|
+
},
|
|
2375
|
+
this
|
|
2376
|
+
);
|
|
2377
|
+
|
|
2378
|
+
if (!instance.get_config('mask_all_text')) {
|
|
2379
|
+
elementsJson[0]['$el_text'] = getSafeText(target);
|
|
2380
|
+
}
|
|
2381
|
+
|
|
2382
|
+
if (href) {
|
|
2383
|
+
elementsJson[0]['attr__href'] = href;
|
|
2384
|
+
}
|
|
2385
|
+
|
|
2386
|
+
if (explicitNoCapture) {
|
|
2387
|
+
return false
|
|
2388
|
+
}
|
|
2389
|
+
|
|
2390
|
+
var props = _.extend(
|
|
2391
|
+
this._getDefaultProperties(e.type),
|
|
2392
|
+
{
|
|
2393
|
+
$elements: elementsJson,
|
|
2394
|
+
},
|
|
2395
|
+
this._getCustomProperties(targetElementList)
|
|
2396
|
+
);
|
|
2397
|
+
|
|
2398
|
+
instance.capture('$autocapture', props);
|
|
2399
|
+
return true
|
|
2400
|
+
}
|
|
2401
|
+
},
|
|
2402
|
+
|
|
2403
|
+
// only reason is to stub for unit tests
|
|
2404
|
+
// since you can't override window.location props
|
|
2405
|
+
_navigate: function (href) {
|
|
2406
|
+
window.location.href = href;
|
|
2407
|
+
},
|
|
2408
|
+
|
|
2409
|
+
_addDomEventHandlers: function (instance) {
|
|
2410
|
+
var handler = _.bind(function (e) {
|
|
2411
|
+
e = e || window.event;
|
|
2412
|
+
this._captureEvent(e, instance);
|
|
2413
|
+
}, this);
|
|
2414
|
+
_.register_event(document, 'submit', handler, false, true);
|
|
2415
|
+
_.register_event(document, 'change', handler, false, true);
|
|
2416
|
+
_.register_event(document, 'click', handler, false, true);
|
|
2417
|
+
},
|
|
2418
|
+
|
|
2419
|
+
_customProperties: {},
|
|
2420
|
+
init: function (instance) {
|
|
2421
|
+
var token = instance.get_config('token');
|
|
2422
|
+
console.log('Initializing autocapture for token "' + token + '"');
|
|
2423
|
+
if (this._initializedTokens.indexOf(token) > -1) {
|
|
2424
|
+
console.log('autocapture already initialized for token "' + token + '"');
|
|
2425
|
+
return
|
|
2426
|
+
}
|
|
2427
|
+
|
|
2428
|
+
this._initializedTokens.push(token);
|
|
2429
|
+
|
|
2430
|
+
if (instance.get_config('autocapture')) {
|
|
2431
|
+
this._addDomEventHandlers(instance);
|
|
2432
|
+
} else {
|
|
2433
|
+
instance['__autocapture_enabled'] = false;
|
|
2434
|
+
}
|
|
2435
|
+
|
|
2436
|
+
this.rageclicks = new RageClick(instance);
|
|
2437
|
+
},
|
|
2438
|
+
|
|
2439
|
+
// this is a mechanism to ramp up CE with no server-side interaction.
|
|
2440
|
+
// when CE is active, every page load results in a decide request. we
|
|
2441
|
+
// need to gently ramp this up so we don't overload decide. this decides
|
|
2442
|
+
// deterministically if CE is enabled for this project by modding the char
|
|
2443
|
+
// value of the project token.
|
|
2444
|
+
enabledForProject: function (token, numBuckets, numEnabledBuckets) {
|
|
2445
|
+
numBuckets = !_.isUndefined(numBuckets) ? numBuckets : 10;
|
|
2446
|
+
numEnabledBuckets = !_.isUndefined(numEnabledBuckets) ? numEnabledBuckets : 10;
|
|
2447
|
+
var charCodeSum = 0;
|
|
2448
|
+
for (var i = 0; i < token.length; i++) {
|
|
2449
|
+
charCodeSum += token.charCodeAt(i);
|
|
2450
|
+
}
|
|
2451
|
+
return charCodeSum % numBuckets < numEnabledBuckets
|
|
2452
|
+
},
|
|
2453
|
+
|
|
2454
|
+
isBrowserSupported: function () {
|
|
2455
|
+
return _.isFunction(document.querySelectorAll)
|
|
2456
|
+
},
|
|
2457
|
+
};
|
|
2458
|
+
|
|
2459
|
+
_.bind_instance_methods(autocapture);
|
|
2460
|
+
_.safewrap_instance_methods(autocapture);
|
|
2461
|
+
|
|
2462
|
+
var VERSION_INFO = {
|
|
2463
|
+
env: 'production',
|
|
2464
|
+
date: '2022-04-06T22:08:10.244Z',
|
|
2465
|
+
version: '1.0.7'
|
|
2466
|
+
};
|
|
2467
|
+
var USERMAVEN_VERSION = "".concat(VERSION_INFO.version, "/").concat(VERSION_INFO.env, "@").concat(VERSION_INFO.date);
|
|
2468
|
+
var MAX_AGE_TEN_YEARS = 31622400 * 10;
|
|
2469
|
+
var beaconTransport = function (url, json) {
|
|
2470
|
+
getLogger().debug("Sending beacon", json);
|
|
2471
|
+
var blob = new Blob([json], { type: "text/plain" });
|
|
2472
|
+
navigator.sendBeacon(url, blob);
|
|
2473
|
+
return Promise.resolve();
|
|
2474
|
+
};
|
|
2475
|
+
function tryFormat(string) {
|
|
2476
|
+
if (typeof string === "string") {
|
|
2477
|
+
try {
|
|
2478
|
+
return JSON.stringify(JSON.parse(string), null, 2);
|
|
2479
|
+
}
|
|
2480
|
+
catch (e) {
|
|
2481
|
+
return string;
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2485
|
+
var echoTransport = function (url, json) {
|
|
2486
|
+
console.log("Jitsu client tried to send payload to ".concat(url), tryFormat(json));
|
|
2487
|
+
return Promise.resolve();
|
|
2488
|
+
};
|
|
2489
|
+
// This is a hack to expire all cookies with non-root path left behind by invalid tracking.
|
|
2490
|
+
// TODO remove soon
|
|
2491
|
+
function expireNonRootCookies(name, path) {
|
|
2492
|
+
if (path === void 0) { path = undefined; }
|
|
2493
|
+
path = path !== null && path !== void 0 ? path : window.location.pathname;
|
|
2494
|
+
if (path == "" || path == "/") {
|
|
2495
|
+
return;
|
|
2496
|
+
}
|
|
2497
|
+
deleteCookie(name, path);
|
|
2498
|
+
expireNonRootCookies(name, path.slice(0, path.lastIndexOf("/")));
|
|
2499
|
+
}
|
|
2500
|
+
var CookiePersistence = /** @class */ (function () {
|
|
2501
|
+
function CookiePersistence(cookieDomain, cookieName) {
|
|
2502
|
+
this.cookieDomain = cookieDomain;
|
|
2503
|
+
this.cookieName = cookieName;
|
|
2504
|
+
}
|
|
2505
|
+
CookiePersistence.prototype.save = function (props) {
|
|
2506
|
+
setCookie(this.cookieName, JSON.stringify(props), {
|
|
2507
|
+
domain: this.cookieDomain,
|
|
2508
|
+
secure: document.location.protocol !== "http:",
|
|
2509
|
+
maxAge: MAX_AGE_TEN_YEARS,
|
|
2510
|
+
});
|
|
2511
|
+
};
|
|
2512
|
+
CookiePersistence.prototype.restore = function () {
|
|
2513
|
+
expireNonRootCookies(this.cookieName);
|
|
2514
|
+
var str = getCookie(this.cookieName);
|
|
2515
|
+
if (str) {
|
|
2516
|
+
try {
|
|
2517
|
+
var parsed = JSON.parse(decodeURIComponent(str));
|
|
2518
|
+
if (typeof parsed !== "object") {
|
|
2519
|
+
getLogger().warn("Can't restore value of ".concat(this.cookieName, "@").concat(this.cookieDomain, ", expected to be object, but found ").concat(typeof parsed !== "object", ": ").concat(parsed, ". Ignoring"));
|
|
2520
|
+
return undefined;
|
|
2521
|
+
}
|
|
2522
|
+
return parsed;
|
|
2523
|
+
}
|
|
2524
|
+
catch (e) {
|
|
2525
|
+
getLogger().error("Failed to decode JSON from " + str, e);
|
|
2526
|
+
return undefined;
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
return undefined;
|
|
2530
|
+
};
|
|
2531
|
+
CookiePersistence.prototype.delete = function () {
|
|
2532
|
+
deleteCookie(this.cookieName);
|
|
2533
|
+
};
|
|
2534
|
+
return CookiePersistence;
|
|
2535
|
+
}());
|
|
2536
|
+
var NoPersistence = /** @class */ (function () {
|
|
2537
|
+
function NoPersistence() {
|
|
2538
|
+
}
|
|
2539
|
+
NoPersistence.prototype.save = function (props) { };
|
|
2540
|
+
NoPersistence.prototype.restore = function () {
|
|
2541
|
+
return undefined;
|
|
2542
|
+
};
|
|
2543
|
+
NoPersistence.prototype.delete = function () { };
|
|
2544
|
+
return NoPersistence;
|
|
2545
|
+
}());
|
|
2546
|
+
var defaultCompatMode = false;
|
|
2547
|
+
function usermavenClient(opts) {
|
|
2548
|
+
var client = new UsermavenClientImpl();
|
|
2549
|
+
client.init(opts);
|
|
2550
|
+
return client;
|
|
2551
|
+
}
|
|
2552
|
+
var browserEnv = {
|
|
2553
|
+
getSourceIp: function () { return undefined; },
|
|
2554
|
+
describeClient: function () { return ({
|
|
2555
|
+
referer: document.referrer,
|
|
2556
|
+
url: window.location.href,
|
|
2557
|
+
page_title: document.title,
|
|
2558
|
+
doc_path: document.location.pathname,
|
|
2559
|
+
doc_host: document.location.hostname,
|
|
2560
|
+
doc_search: window.location.search,
|
|
2561
|
+
screen_resolution: screen.width + "x" + screen.height,
|
|
2562
|
+
vp_size: Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0) +
|
|
2563
|
+
"x" +
|
|
2564
|
+
Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0),
|
|
2565
|
+
user_agent: navigator.userAgent,
|
|
2566
|
+
user_language: navigator.language,
|
|
2567
|
+
doc_encoding: document.characterSet,
|
|
2568
|
+
}); },
|
|
2569
|
+
getAnonymousId: function (_a) {
|
|
2570
|
+
var name = _a.name, domain = _a.domain;
|
|
2571
|
+
expireNonRootCookies(name);
|
|
2572
|
+
var idCookie = getCookie(name);
|
|
2573
|
+
if (idCookie) {
|
|
2574
|
+
getLogger().debug("Existing user id", idCookie);
|
|
2575
|
+
return idCookie;
|
|
2576
|
+
}
|
|
2577
|
+
var newId = generateId();
|
|
2578
|
+
getLogger().debug("New user id", newId);
|
|
2579
|
+
setCookie(name, newId, {
|
|
2580
|
+
domain: domain,
|
|
2581
|
+
secure: document.location.protocol !== "http:",
|
|
2582
|
+
maxAge: MAX_AGE_TEN_YEARS,
|
|
2583
|
+
});
|
|
2584
|
+
return newId;
|
|
2585
|
+
},
|
|
2586
|
+
};
|
|
2587
|
+
function ensurePrefix(prefix, str) {
|
|
2588
|
+
if (!str) {
|
|
2589
|
+
return str;
|
|
2590
|
+
}
|
|
2591
|
+
return (str === null || str === void 0 ? void 0 : str.length) > 0 && str.indexOf(prefix) !== 0 ? prefix + str : str;
|
|
2592
|
+
}
|
|
2593
|
+
function cutPostfix(postfixes, str) {
|
|
2594
|
+
for (var _i = 0, _a = typeof postfixes === "string"
|
|
2595
|
+
? [postfixes]
|
|
2596
|
+
: postfixes; _i < _a.length; _i++) {
|
|
2597
|
+
var postfix = _a[_i];
|
|
2598
|
+
while (str && str.length > 0 && str.charAt(str.length - 1) === postfix) {
|
|
2599
|
+
str = str.substring(0, str.length - 1);
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2602
|
+
return str;
|
|
2603
|
+
}
|
|
2604
|
+
function fetchApi(req, res, opts) {
|
|
2605
|
+
if (opts === void 0) { opts = {}; }
|
|
2606
|
+
return {
|
|
2607
|
+
getAnonymousId: function (_a) {
|
|
2608
|
+
var name = _a.name, domain = _a.domain;
|
|
2609
|
+
if (opts === null || opts === void 0 ? void 0 : opts.disableCookies) {
|
|
2610
|
+
return "";
|
|
2611
|
+
}
|
|
2612
|
+
var cookie = parseCookieString(req.headers["cookie"])[name];
|
|
2613
|
+
if (!cookie) {
|
|
2614
|
+
var cookieOpts = {
|
|
2615
|
+
maxAge: 31622400 * 10,
|
|
2616
|
+
httpOnly: false,
|
|
2617
|
+
};
|
|
2618
|
+
if (domain) {
|
|
2619
|
+
cookieOpts.domain = domain;
|
|
2620
|
+
}
|
|
2621
|
+
var newId = generateId();
|
|
2622
|
+
res.headers.set("Set-Cookie", serializeCookie(name, newId, cookieOpts));
|
|
2623
|
+
return newId;
|
|
2624
|
+
}
|
|
2625
|
+
else {
|
|
2626
|
+
return cookie;
|
|
2627
|
+
}
|
|
2628
|
+
},
|
|
2629
|
+
getSourceIp: function () {
|
|
2630
|
+
var ip = req.headers["x-forwarded-for"] || req.headers["x-real-ip"] || req["ip"];
|
|
2631
|
+
return ip && ip.split(",")[0].trim();
|
|
2632
|
+
},
|
|
2633
|
+
describeClient: function () {
|
|
2634
|
+
var requestHost = req.headers.get("host") || req.headers.get("host");
|
|
2635
|
+
var proto = cutPostfix([":", "/"], req.headers["x-forwarded-proto"] || req["nextUrl"]["protocol"] || "http");
|
|
2636
|
+
while (proto && proto.length > 0 && proto.charAt(proto.length - 1)) {
|
|
2637
|
+
proto = proto.substring(0, proto.length - 1);
|
|
2638
|
+
}
|
|
2639
|
+
var reqUrl = req.url || "/";
|
|
2640
|
+
var queryPos = reqUrl.indexOf("?");
|
|
2641
|
+
var path, query;
|
|
2642
|
+
if (queryPos >= 0) {
|
|
2643
|
+
path = reqUrl.substring(0, queryPos);
|
|
2644
|
+
query = reqUrl.substring(queryPos + 1);
|
|
2645
|
+
}
|
|
2646
|
+
else {
|
|
2647
|
+
path = reqUrl;
|
|
2648
|
+
query = undefined;
|
|
2649
|
+
}
|
|
2650
|
+
query = ensurePrefix(query, "?");
|
|
2651
|
+
path = ensurePrefix(path, "/");
|
|
2652
|
+
return {
|
|
2653
|
+
doc_encoding: "",
|
|
2654
|
+
doc_host: requestHost,
|
|
2655
|
+
doc_path: reqUrl,
|
|
2656
|
+
doc_search: query,
|
|
2657
|
+
page_title: "",
|
|
2658
|
+
referer: req.headers["referrer"],
|
|
2659
|
+
screen_resolution: "",
|
|
2660
|
+
url: "".concat(proto, "://").concat(requestHost).concat(path || "").concat(query || ""),
|
|
2661
|
+
user_agent: req.headers["user-agent"],
|
|
2662
|
+
user_language: req.headers["accept-language"] &&
|
|
2663
|
+
req.headers["accept-language"].split(",")[0],
|
|
2664
|
+
vp_size: "",
|
|
2665
|
+
};
|
|
2666
|
+
},
|
|
2667
|
+
};
|
|
2668
|
+
}
|
|
2669
|
+
function httpApi(req, res, opts) {
|
|
2670
|
+
if (opts === void 0) { opts = {}; }
|
|
2671
|
+
var header = function (req, name) {
|
|
2672
|
+
var vals = req.headers[name.toLowerCase()];
|
|
2673
|
+
if (!vals) {
|
|
2674
|
+
return undefined;
|
|
2675
|
+
}
|
|
2676
|
+
if (typeof vals === "string") {
|
|
2677
|
+
return vals;
|
|
2678
|
+
}
|
|
2679
|
+
else if (vals.length > 0) {
|
|
2680
|
+
return vals.join(",");
|
|
2681
|
+
}
|
|
2682
|
+
};
|
|
2683
|
+
return {
|
|
2684
|
+
getAnonymousId: function (_a) {
|
|
2685
|
+
var name = _a.name, domain = _a.domain;
|
|
2686
|
+
if (opts === null || opts === void 0 ? void 0 : opts.disableCookies) {
|
|
2687
|
+
return "";
|
|
2688
|
+
}
|
|
2689
|
+
var cookie = parseCookieString(req.headers["cookie"])[name];
|
|
2690
|
+
if (!cookie) {
|
|
2691
|
+
var cookieOpts = {
|
|
2692
|
+
maxAge: 31622400 * 10,
|
|
2693
|
+
httpOnly: false,
|
|
2694
|
+
};
|
|
2695
|
+
if (domain) {
|
|
2696
|
+
cookieOpts.domain = domain;
|
|
2697
|
+
}
|
|
2698
|
+
var newId = generateId();
|
|
2699
|
+
res.setHeader("Set-Cookie", serializeCookie(name, newId, cookieOpts));
|
|
2700
|
+
return newId;
|
|
2701
|
+
}
|
|
2702
|
+
else {
|
|
2703
|
+
return cookie;
|
|
2704
|
+
}
|
|
2705
|
+
},
|
|
2706
|
+
getSourceIp: function () {
|
|
2707
|
+
var ip = header(req, "x-forwarded-for") ||
|
|
2708
|
+
header(req, "x-real-ip") ||
|
|
2709
|
+
req.socket.remoteAddress;
|
|
2710
|
+
return ip && ip.split(",")[0].trim();
|
|
2711
|
+
},
|
|
2712
|
+
describeClient: function () {
|
|
2713
|
+
var url = req.url
|
|
2714
|
+
? new URL(req.url, req.url.startsWith("http") ? undefined : "http://localhost")
|
|
2715
|
+
: {};
|
|
2716
|
+
var requestHost = header(req, "x-forwarded-host") || header(req, "host") || url.hostname;
|
|
2717
|
+
var proto = cutPostfix([":", "/"], header(req, "x-forwarded-proto") || url.protocol);
|
|
2718
|
+
var query = ensurePrefix("?", url.search);
|
|
2719
|
+
var path = ensurePrefix("/", url.pathname);
|
|
2720
|
+
return {
|
|
2721
|
+
doc_encoding: "",
|
|
2722
|
+
doc_host: requestHost,
|
|
2723
|
+
doc_path: req.url,
|
|
2724
|
+
doc_search: query,
|
|
2725
|
+
page_title: "",
|
|
2726
|
+
referer: header(req, "referrer"),
|
|
2727
|
+
screen_resolution: "",
|
|
2728
|
+
url: "".concat(proto, "://").concat(requestHost).concat(path || "").concat(query || ""),
|
|
2729
|
+
user_agent: req.headers["user-agent"],
|
|
2730
|
+
user_language: req.headers["accept-language"] &&
|
|
2731
|
+
req.headers["accept-language"].split(",")[0],
|
|
2732
|
+
vp_size: "",
|
|
2733
|
+
};
|
|
2734
|
+
},
|
|
2735
|
+
};
|
|
2736
|
+
}
|
|
2737
|
+
var emptyEnv = {
|
|
2738
|
+
getSourceIp: function () { return undefined; },
|
|
2739
|
+
describeClient: function () { return ({}); },
|
|
2740
|
+
getAnonymousId: function () { return ""; },
|
|
2741
|
+
};
|
|
2742
|
+
/**
|
|
2743
|
+
* Dictionary of supported environments
|
|
2744
|
+
*/
|
|
2745
|
+
var envs = {
|
|
2746
|
+
httpApi: httpApi,
|
|
2747
|
+
nextjsApi: httpApi,
|
|
2748
|
+
// fetchApi: fetchApi,
|
|
2749
|
+
// nextjsMiddleware: fetchApi,
|
|
2750
|
+
browser: function () { return browserEnv; },
|
|
2751
|
+
express: httpApi,
|
|
2752
|
+
empty: function () { return emptyEnv; },
|
|
2753
|
+
};
|
|
2754
|
+
var xmlHttpTransport = function (url, jsonPayload, additionalHeaders, handler) {
|
|
2755
|
+
if (handler === void 0) { handler = function (code, body) { }; }
|
|
2756
|
+
var req = new window.XMLHttpRequest();
|
|
2757
|
+
return new Promise(function (resolve, reject) {
|
|
2758
|
+
req.onerror = function (e) {
|
|
2759
|
+
getLogger().error("Failed to send", jsonPayload, e);
|
|
2760
|
+
handler(-1, {});
|
|
2761
|
+
reject(new Error("Failed to send JSON. See console logs"));
|
|
2762
|
+
};
|
|
2763
|
+
req.onload = function () {
|
|
2764
|
+
if (req.status !== 200) {
|
|
2765
|
+
handler(req.status, {});
|
|
2766
|
+
getLogger().warn("Failed to send data to ".concat(url, " (#").concat(req.status, " - ").concat(req.statusText, ")"), jsonPayload);
|
|
2767
|
+
reject(new Error("Failed to send JSON. Error code: ".concat(req.status, ". See logs for details")));
|
|
2768
|
+
}
|
|
2769
|
+
else {
|
|
2770
|
+
handler(req.status, req.responseText);
|
|
2771
|
+
}
|
|
2772
|
+
resolve();
|
|
2773
|
+
};
|
|
2774
|
+
req.open("POST", url);
|
|
2775
|
+
req.setRequestHeader("Content-Type", "application/json");
|
|
2776
|
+
Object.entries(additionalHeaders || {}).forEach(function (_a) {
|
|
2777
|
+
var key = _a[0], val = _a[1];
|
|
2778
|
+
return req.setRequestHeader(key, val);
|
|
2779
|
+
});
|
|
2780
|
+
req.send(jsonPayload);
|
|
2781
|
+
getLogger().debug("sending json", jsonPayload);
|
|
2782
|
+
});
|
|
2783
|
+
};
|
|
2784
|
+
var fetchTransport = function (fetch) {
|
|
2785
|
+
return function (url, jsonPayload, additionalHeaders, handler) {
|
|
2786
|
+
if (handler === void 0) { handler = function (code, body) { }; }
|
|
2787
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
|
2788
|
+
var res, e_1, resJson;
|
|
2789
|
+
return __generator(this, function (_a) {
|
|
2790
|
+
switch (_a.label) {
|
|
2791
|
+
case 0:
|
|
2792
|
+
_a.trys.push([0, 2, , 3]);
|
|
2793
|
+
return [4 /*yield*/, fetch(url, {
|
|
2794
|
+
method: "POST",
|
|
2795
|
+
headers: __assign({ Accept: "application/json", "Content-Type": "application/json" }, (additionalHeaders || {})),
|
|
2796
|
+
body: jsonPayload,
|
|
2797
|
+
})];
|
|
2798
|
+
case 1:
|
|
2799
|
+
res = _a.sent();
|
|
2800
|
+
return [3 /*break*/, 3];
|
|
2801
|
+
case 2:
|
|
2802
|
+
e_1 = _a.sent();
|
|
2803
|
+
getLogger().error("Failed to send", jsonPayload, e_1);
|
|
2804
|
+
handler(-1, {});
|
|
2805
|
+
throw new Error("Failed to send JSON. See console logs");
|
|
2806
|
+
case 3:
|
|
2807
|
+
if (res.status !== 200) {
|
|
2808
|
+
getLogger().warn("Failed to send data to ".concat(url, " (#").concat(res.status, " - ").concat(res.statusText, ")"), jsonPayload);
|
|
2809
|
+
throw new Error("Failed to send JSON. Error code: ".concat(res.status, ". See logs for details"));
|
|
2810
|
+
}
|
|
2811
|
+
return [4 /*yield*/, res.json()];
|
|
2812
|
+
case 4:
|
|
2813
|
+
resJson = _a.sent();
|
|
2814
|
+
handler(res.status, resJson);
|
|
2815
|
+
return [2 /*return*/];
|
|
2816
|
+
}
|
|
2817
|
+
});
|
|
2818
|
+
});
|
|
2819
|
+
};
|
|
2820
|
+
};
|
|
1780
2821
|
var UsermavenClientImpl = /** @class */ (function () {
|
|
1781
2822
|
function UsermavenClientImpl() {
|
|
1782
|
-
this.anonymousId = '';
|
|
1783
2823
|
this.userProperties = {};
|
|
1784
|
-
this.permanentProperties = {
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
2824
|
+
this.permanentProperties = {
|
|
2825
|
+
globalProps: {},
|
|
2826
|
+
propsPerEvent: {},
|
|
2827
|
+
};
|
|
2828
|
+
this.cookieDomain = "";
|
|
2829
|
+
this.trackingHost = "";
|
|
2830
|
+
this.idCookieName = "";
|
|
1788
2831
|
this.randomizeUrl = false;
|
|
1789
|
-
this.apiKey =
|
|
2832
|
+
this.apiKey = "";
|
|
1790
2833
|
this.initialized = false;
|
|
1791
2834
|
this._3pCookies = {};
|
|
1792
|
-
this.cookiePolicy =
|
|
1793
|
-
this.ipPolicy =
|
|
2835
|
+
this.cookiePolicy = "keep";
|
|
2836
|
+
this.ipPolicy = "keep";
|
|
1794
2837
|
this.beaconApi = false;
|
|
1795
|
-
|
|
2838
|
+
this.transport = xmlHttpTransport;
|
|
2839
|
+
this.customHeaders = function () { return ({}); };
|
|
2840
|
+
this.__autocapture_enabled = false;
|
|
2841
|
+
}
|
|
2842
|
+
// private anonymousId: string = '';
|
|
2843
|
+
// Used for session + autocapture
|
|
2844
|
+
UsermavenClientImpl.prototype.get_config = function (prop_name) {
|
|
2845
|
+
return this.config ? this.config[prop_name] : null;
|
|
2846
|
+
};
|
|
1796
2847
|
UsermavenClientImpl.prototype.id = function (props, doNotSendEvent) {
|
|
1797
2848
|
this.userProperties = __assign(__assign({}, this.userProperties), props);
|
|
1798
|
-
getLogger().debug(
|
|
2849
|
+
getLogger().debug("Usermaven user identified", props);
|
|
1799
2850
|
if (this.userIdPersistence) {
|
|
1800
2851
|
this.userIdPersistence.save(props);
|
|
1801
2852
|
}
|
|
1802
2853
|
else {
|
|
1803
|
-
getLogger().warn(
|
|
2854
|
+
getLogger().warn("Id() is called before initialization");
|
|
1804
2855
|
}
|
|
1805
2856
|
if (!doNotSendEvent) {
|
|
1806
|
-
return this.track(
|
|
2857
|
+
return this.track("user_identify", {});
|
|
1807
2858
|
}
|
|
1808
2859
|
else {
|
|
1809
2860
|
return Promise.resolve();
|
|
1810
2861
|
}
|
|
1811
2862
|
};
|
|
1812
2863
|
UsermavenClientImpl.prototype.rawTrack = function (payload) {
|
|
1813
|
-
this.sendJson(payload);
|
|
1814
|
-
};
|
|
1815
|
-
UsermavenClientImpl.prototype.getAnonymousId = function () {
|
|
1816
|
-
var idCookie = getCookie(this.idCookieName);
|
|
1817
|
-
if (idCookie) {
|
|
1818
|
-
getLogger().debug('Existing user id', idCookie);
|
|
1819
|
-
return idCookie;
|
|
1820
|
-
}
|
|
1821
|
-
var newId = generateId();
|
|
1822
|
-
getLogger().debug('New user id', newId);
|
|
1823
|
-
setCookie(this.idCookieName, newId, Infinity, this.cookieDomain, document.location.protocol !== 'http:');
|
|
1824
|
-
return newId;
|
|
2864
|
+
return this.sendJson(payload);
|
|
1825
2865
|
};
|
|
1826
2866
|
UsermavenClientImpl.prototype.makeEvent = function (event_type, src, payload) {
|
|
1827
2867
|
var _a;
|
|
2868
|
+
var env = payload.env, payloadData = __rest(payload, ["env"]);
|
|
2869
|
+
if (!env) {
|
|
2870
|
+
env = isWindowAvailable() ? envs.browser() : envs.empty();
|
|
2871
|
+
}
|
|
1828
2872
|
this.restoreId();
|
|
1829
|
-
var context = this.getCtx();
|
|
2873
|
+
var context = this.getCtx(env);
|
|
1830
2874
|
var persistentProps = __assign(__assign({}, this.permanentProperties.globalProps), ((_a = this.permanentProperties.propsPerEvent[event_type]) !== null && _a !== void 0 ? _a : {}));
|
|
1831
|
-
var base = __assign({ api_key: this.apiKey, src: src, event_type: event_type },
|
|
1832
|
-
|
|
2875
|
+
var base = __assign({ api_key: this.apiKey, src: src, event_type: event_type }, payloadData);
|
|
2876
|
+
var sourceIp = env.getSourceIp();
|
|
2877
|
+
if (sourceIp) {
|
|
2878
|
+
base["source_ip"] = sourceIp;
|
|
2879
|
+
}
|
|
2880
|
+
return this.compatMode
|
|
2881
|
+
? __assign(__assign(__assign({}, persistentProps), { eventn_ctx: context }), base) : __assign(__assign(__assign({}, persistentProps), context), base);
|
|
1833
2882
|
};
|
|
1834
2883
|
UsermavenClientImpl.prototype._send3p = function (sourceType, object, type) {
|
|
1835
|
-
var eventType =
|
|
1836
|
-
if (type && type !==
|
|
2884
|
+
var eventType = "3rdparty";
|
|
2885
|
+
if (type && type !== "") {
|
|
1837
2886
|
eventType = type;
|
|
1838
2887
|
}
|
|
1839
2888
|
var e = this.makeEvent(eventType, sourceType, {
|
|
1840
|
-
src_payload: object
|
|
2889
|
+
src_payload: object,
|
|
1841
2890
|
});
|
|
1842
2891
|
return this.sendJson(e);
|
|
1843
2892
|
};
|
|
1844
2893
|
UsermavenClientImpl.prototype.sendJson = function (json) {
|
|
1845
|
-
var
|
|
1846
|
-
var
|
|
1847
|
-
var
|
|
2894
|
+
var _this = this;
|
|
2895
|
+
var cookiePolicy = this.cookiePolicy !== "keep" ? "&cookie_policy=".concat(this.cookiePolicy) : "";
|
|
2896
|
+
var ipPolicy = this.ipPolicy !== "keep" ? "&ip_policy=".concat(this.ipPolicy) : "";
|
|
2897
|
+
var urlPrefix = isWindowAvailable() ? "/api/v1/event" : "/api/v1/s2s/event";
|
|
2898
|
+
var url = "".concat(this.trackingHost).concat(urlPrefix, "?token=").concat(this.apiKey).concat(cookiePolicy).concat(ipPolicy);
|
|
1848
2899
|
if (this.randomizeUrl) {
|
|
1849
2900
|
url = "".concat(this.trackingHost, "/api.").concat(generateRandom(), "?p_").concat(generateRandom(), "=").concat(this.apiKey).concat(cookiePolicy).concat(ipPolicy);
|
|
1850
2901
|
}
|
|
1851
2902
|
var jsonString = JSON.stringify(json);
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
else {
|
|
1856
|
-
return this.xmlHttpReqTransport(url, jsonString);
|
|
1857
|
-
}
|
|
1858
|
-
};
|
|
1859
|
-
UsermavenClientImpl.prototype.xmlHttpReqTransport = function (url, json) {
|
|
1860
|
-
var _this = this;
|
|
1861
|
-
var req = new XMLHttpRequest();
|
|
1862
|
-
return new Promise(function (resolve, reject) {
|
|
1863
|
-
req.onerror = function (e) {
|
|
1864
|
-
getLogger().error('Failed to send', json, e);
|
|
1865
|
-
_this.postHandle(-1, {});
|
|
1866
|
-
reject(new Error("Failed to send JSON. See console logs"));
|
|
1867
|
-
};
|
|
1868
|
-
req.onload = function () {
|
|
1869
|
-
_this.postHandle(req.status, req.response);
|
|
1870
|
-
if (req.status !== 200) {
|
|
1871
|
-
getLogger().warn("Failed to send data to ".concat(url, " (#").concat(req.status, " - ").concat(req.statusText, ")"), json);
|
|
1872
|
-
reject(new Error("Failed to send JSON. Error code: ".concat(req.status, ". See logs for details")));
|
|
1873
|
-
}
|
|
1874
|
-
resolve();
|
|
1875
|
-
};
|
|
1876
|
-
req.open('POST', url);
|
|
1877
|
-
req.setRequestHeader('Content-Type', 'application/json');
|
|
1878
|
-
req.send(json);
|
|
1879
|
-
getLogger().debug('sending json', json);
|
|
2903
|
+
getLogger().debug("Sending payload to ".concat(url), jsonString);
|
|
2904
|
+
return this.transport(url, jsonString, this.customHeaders(), function (code, body) {
|
|
2905
|
+
return _this.postHandle(code, body);
|
|
1880
2906
|
});
|
|
1881
2907
|
};
|
|
1882
2908
|
UsermavenClientImpl.prototype.postHandle = function (status, response) {
|
|
1883
|
-
if (this.cookiePolicy ===
|
|
2909
|
+
if (this.cookiePolicy === "strict" || this.cookiePolicy === "comply") {
|
|
1884
2910
|
if (status === 200) {
|
|
1885
2911
|
var data = response;
|
|
1886
|
-
if (typeof response ===
|
|
2912
|
+
if (typeof response === "string") {
|
|
1887
2913
|
data = JSON.parse(response);
|
|
1888
2914
|
}
|
|
1889
|
-
if (!data[
|
|
2915
|
+
if (!data["delete_cookie"]) {
|
|
1890
2916
|
return;
|
|
1891
2917
|
}
|
|
1892
2918
|
}
|
|
@@ -1894,15 +2920,45 @@ var UsermavenClientImpl = /** @class */ (function () {
|
|
|
1894
2920
|
this.propsPersistance.delete();
|
|
1895
2921
|
deleteCookie(this.idCookieName);
|
|
1896
2922
|
}
|
|
2923
|
+
if (status === 200) {
|
|
2924
|
+
var data = response;
|
|
2925
|
+
if (typeof response === "string" && response.length > 0) {
|
|
2926
|
+
data = JSON.parse(response);
|
|
2927
|
+
var extras = data["jitsu_sdk_extras"];
|
|
2928
|
+
if (extras && extras.length > 0) {
|
|
2929
|
+
var isWindow = isWindowAvailable();
|
|
2930
|
+
if (!isWindow) {
|
|
2931
|
+
getLogger().error("Tags destination supported only in browser environment");
|
|
2932
|
+
}
|
|
2933
|
+
else {
|
|
2934
|
+
for (var _i = 0, extras_1 = extras; _i < extras_1.length; _i++) {
|
|
2935
|
+
var _a = extras_1[_i], type = _a.type, id = _a.id, value = _a.value;
|
|
2936
|
+
if (type === "tag") {
|
|
2937
|
+
var tag = document.createElement("div");
|
|
2938
|
+
tag.id = id;
|
|
2939
|
+
insertAndExecute(tag, value);
|
|
2940
|
+
if (tag.childElementCount > 0) {
|
|
2941
|
+
document.body.appendChild(tag);
|
|
2942
|
+
}
|
|
2943
|
+
}
|
|
2944
|
+
}
|
|
2945
|
+
}
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
}
|
|
1897
2949
|
};
|
|
1898
|
-
UsermavenClientImpl.prototype.getCtx = function () {
|
|
2950
|
+
UsermavenClientImpl.prototype.getCtx = function (env) {
|
|
1899
2951
|
var now = new Date();
|
|
1900
|
-
var
|
|
1901
|
-
|
|
1902
|
-
var
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
2952
|
+
var props = env.describeClient() || {};
|
|
2953
|
+
var _a = this.sessionManager.getSessionAndWindowId(), session_id = _a.session_id, window_id = _a.window_id;
|
|
2954
|
+
var company = this.userProperties['company'] || {};
|
|
2955
|
+
delete this.userProperties['company'];
|
|
2956
|
+
var payload = __assign(__assign({ event_id: "", session_id: session_id, window_id: window_id, user: __assign({ anonymous_id: this.cookiePolicy !== "strict"
|
|
2957
|
+
? env.getAnonymousId({
|
|
2958
|
+
name: this.idCookieName,
|
|
2959
|
+
domain: this.cookieDomain,
|
|
2960
|
+
})
|
|
2961
|
+
: "" }, this.userProperties), ids: this._getIds(), utc_time: reformatDate(now.toISOString()), local_tz_offset: now.getTimezoneOffset() }, props), getDataFromParams(parseQuery(props.doc_search)));
|
|
1906
2962
|
// id and name attributes will be checked on backend
|
|
1907
2963
|
if (Object.keys(company).length) {
|
|
1908
2964
|
payload['company'] = company;
|
|
@@ -1910,74 +2966,104 @@ var UsermavenClientImpl = /** @class */ (function () {
|
|
|
1910
2966
|
return payload;
|
|
1911
2967
|
};
|
|
1912
2968
|
UsermavenClientImpl.prototype._getIds = function () {
|
|
2969
|
+
if (!isWindowAvailable()) {
|
|
2970
|
+
return {};
|
|
2971
|
+
}
|
|
1913
2972
|
var cookies = getCookies(false);
|
|
1914
2973
|
var res = {};
|
|
1915
2974
|
for (var _i = 0, _a = Object.entries(cookies); _i < _a.length; _i++) {
|
|
1916
2975
|
var _b = _a[_i], key = _b[0], value = _b[1];
|
|
1917
2976
|
if (this._3pCookies[key]) {
|
|
1918
|
-
res[key.charAt(0) ==
|
|
1919
|
-
key.substr(1) :
|
|
1920
|
-
key] = value;
|
|
2977
|
+
res[key.charAt(0) == "_" ? key.substr(1) : key] = value;
|
|
1921
2978
|
}
|
|
1922
2979
|
}
|
|
1923
2980
|
return res;
|
|
1924
2981
|
};
|
|
1925
2982
|
UsermavenClientImpl.prototype.track = function (type, payload) {
|
|
1926
2983
|
var data = payload || {};
|
|
1927
|
-
getLogger().debug(
|
|
1928
|
-
var e = this.makeEvent(type, this.compatMode ?
|
|
1929
|
-
'eventn' :
|
|
1930
|
-
'usermaven', payload || {});
|
|
2984
|
+
getLogger().debug("track event of type", type, data);
|
|
2985
|
+
var e = this.makeEvent(type, this.compatMode ? "eventn" : "usermaven", payload || {});
|
|
1931
2986
|
return this.sendJson(e);
|
|
1932
2987
|
};
|
|
1933
2988
|
UsermavenClientImpl.prototype.init = function (options) {
|
|
1934
2989
|
var _this = this;
|
|
1935
2990
|
var _a, _b;
|
|
2991
|
+
if (isWindowAvailable() && !options.force_use_fetch) {
|
|
2992
|
+
if (options.fetch) {
|
|
2993
|
+
getLogger().warn("Custom fetch implementation is provided to Usermaven. However, it will be ignored since Usermaven runs in browser");
|
|
2994
|
+
}
|
|
2995
|
+
this.transport = this.beaconApi ? beaconTransport : xmlHttpTransport;
|
|
2996
|
+
}
|
|
2997
|
+
else {
|
|
2998
|
+
if (!options.fetch && !globalThis.fetch) {
|
|
2999
|
+
throw new Error("Usermaven runs in Node environment. However, neither UsermavenOptions.fetch is provided, nor global fetch function is defined. \n" +
|
|
3000
|
+
"Please, provide custom fetch implementation. You can get it via node-fetch package");
|
|
3001
|
+
}
|
|
3002
|
+
this.transport = fetchTransport(options.fetch || globalThis.fetch);
|
|
3003
|
+
}
|
|
3004
|
+
if (options.custom_headers &&
|
|
3005
|
+
typeof options.custom_headers === "function") {
|
|
3006
|
+
this.customHeaders = options.custom_headers;
|
|
3007
|
+
}
|
|
3008
|
+
else if (options.custom_headers) {
|
|
3009
|
+
this.customHeaders = function () {
|
|
3010
|
+
return options.custom_headers;
|
|
3011
|
+
};
|
|
3012
|
+
}
|
|
3013
|
+
if (options.tracking_host === "echo") {
|
|
3014
|
+
getLogger().warn('jitsuClient is configured with "echo" transport. Outgoing requests will be written to console');
|
|
3015
|
+
this.transport = echoTransport;
|
|
3016
|
+
}
|
|
1936
3017
|
if (options.ip_policy) {
|
|
1937
3018
|
this.ipPolicy = options.ip_policy;
|
|
1938
3019
|
}
|
|
1939
3020
|
if (options.cookie_policy) {
|
|
1940
3021
|
this.cookiePolicy = options.cookie_policy;
|
|
1941
3022
|
}
|
|
1942
|
-
if (options.privacy_policy ===
|
|
1943
|
-
this.ipPolicy =
|
|
1944
|
-
this.cookiePolicy =
|
|
3023
|
+
if (options.privacy_policy === "strict") {
|
|
3024
|
+
this.ipPolicy = "strict";
|
|
3025
|
+
this.cookiePolicy = "strict";
|
|
1945
3026
|
}
|
|
1946
3027
|
if (options.use_beacon_api && navigator.sendBeacon) {
|
|
1947
3028
|
this.beaconApi = true;
|
|
1948
3029
|
}
|
|
1949
3030
|
//can't handle delete cookie response when beacon api
|
|
1950
|
-
if (this.cookiePolicy ===
|
|
1951
|
-
this.cookiePolicy =
|
|
3031
|
+
if (this.cookiePolicy === "comply" && this.beaconApi) {
|
|
3032
|
+
this.cookiePolicy = "strict";
|
|
1952
3033
|
}
|
|
1953
3034
|
if (options.log_level) {
|
|
1954
3035
|
setRootLogLevel(options.log_level);
|
|
1955
3036
|
}
|
|
1956
3037
|
this.initialOptions = options;
|
|
1957
|
-
getLogger().debug(
|
|
3038
|
+
getLogger().debug("Initializing Usemaven Tracker tracker", options, USERMAVEN_VERSION);
|
|
1958
3039
|
if (!options.key) {
|
|
1959
|
-
getLogger().error(
|
|
3040
|
+
getLogger().error("Can't initialize Usemaven, key property is not set");
|
|
1960
3041
|
return;
|
|
1961
3042
|
}
|
|
1962
|
-
this.compatMode =
|
|
1963
|
-
|
|
1964
|
-
|
|
3043
|
+
this.compatMode =
|
|
3044
|
+
options.compat_mode === undefined
|
|
3045
|
+
? defaultCompatMode
|
|
3046
|
+
: !!options.compat_mode;
|
|
1965
3047
|
this.cookieDomain = options.cookie_domain || getCookieDomain();
|
|
1966
|
-
this.trackingHost = getHostWithProtocol(options[
|
|
3048
|
+
this.trackingHost = getHostWithProtocol(options["tracking_host"] || "t.usermaven.com");
|
|
1967
3049
|
this.randomizeUrl = options.randomize_url || false;
|
|
1968
|
-
this.idCookieName = options.cookie_name ||
|
|
3050
|
+
this.idCookieName = options.cookie_name || "__eventn_id";
|
|
1969
3051
|
this.apiKey = options.key;
|
|
1970
|
-
if (this.cookiePolicy ===
|
|
3052
|
+
if (this.cookiePolicy === "strict") {
|
|
1971
3053
|
this.propsPersistance = new NoPersistence();
|
|
1972
3054
|
}
|
|
1973
3055
|
else {
|
|
1974
|
-
this.propsPersistance =
|
|
3056
|
+
this.propsPersistance = isWindowAvailable()
|
|
3057
|
+
? new CookiePersistence(this.cookieDomain, this.idCookieName + "_props")
|
|
3058
|
+
: new NoPersistence();
|
|
1975
3059
|
}
|
|
1976
|
-
if (this.cookiePolicy ===
|
|
3060
|
+
if (this.cookiePolicy === "strict") {
|
|
1977
3061
|
this.userIdPersistence = new NoPersistence();
|
|
1978
3062
|
}
|
|
1979
3063
|
else {
|
|
1980
|
-
this.userIdPersistence =
|
|
3064
|
+
this.userIdPersistence = isWindowAvailable()
|
|
3065
|
+
? new CookiePersistence(this.cookieDomain, this.idCookieName + "_usr")
|
|
3066
|
+
: new NoPersistence();
|
|
1981
3067
|
}
|
|
1982
3068
|
if (this.propsPersistance) {
|
|
1983
3069
|
var restored = this.propsPersistance.restore();
|
|
@@ -1986,26 +3072,45 @@ var UsermavenClientImpl = /** @class */ (function () {
|
|
|
1986
3072
|
this.permanentProperties.globalProps = (_a = restored.globalProps) !== null && _a !== void 0 ? _a : {};
|
|
1987
3073
|
this.permanentProperties.propsPerEvent = (_b = restored.propsPerEvent) !== null && _b !== void 0 ? _b : {};
|
|
1988
3074
|
}
|
|
1989
|
-
getLogger().debug(
|
|
3075
|
+
getLogger().debug("Restored persistent properties", this.permanentProperties);
|
|
1990
3076
|
}
|
|
1991
|
-
|
|
3077
|
+
// Added these configuration for session management + autocapture
|
|
3078
|
+
var defaultConfig = {
|
|
3079
|
+
persistence: 'cookie',
|
|
3080
|
+
persistence_name: 'session',
|
|
3081
|
+
autocapture: false,
|
|
3082
|
+
capture_pageview: true,
|
|
3083
|
+
store_google: false,
|
|
3084
|
+
save_referrer: false,
|
|
3085
|
+
properties_string_max_length: null,
|
|
3086
|
+
property_blacklist: [],
|
|
3087
|
+
sanitize_properties: null
|
|
3088
|
+
};
|
|
3089
|
+
this.config = _.extend({}, defaultConfig, options || {}, this.config || {}, { token: this.apiKey });
|
|
3090
|
+
getLogger().debug('Default Configuration', this.config);
|
|
3091
|
+
this.manageSession(this.config);
|
|
3092
|
+
this.manageAutoCapture(this.config);
|
|
1992
3093
|
if (options.capture_3rd_party_cookies === false) {
|
|
1993
3094
|
this._3pCookies = {};
|
|
1994
3095
|
}
|
|
1995
3096
|
else {
|
|
1996
|
-
(options.capture_3rd_party_cookies || [
|
|
1997
|
-
|
|
3097
|
+
(options.capture_3rd_party_cookies || [
|
|
3098
|
+
"_ga",
|
|
3099
|
+
"_fbp",
|
|
3100
|
+
"_ym_uid",
|
|
3101
|
+
"ajs_user_id",
|
|
3102
|
+
"ajs_anonymous_id",
|
|
3103
|
+
]).forEach(function (name) { return (_this._3pCookies[name] = true); });
|
|
1998
3104
|
}
|
|
1999
3105
|
if (options.ga_hook) {
|
|
2000
|
-
getLogger().warn(
|
|
3106
|
+
getLogger().warn("GA event interceptor isn't supported anymore");
|
|
2001
3107
|
}
|
|
2002
3108
|
if (options.segment_hook) {
|
|
2003
3109
|
interceptSegmentCalls(this);
|
|
2004
3110
|
}
|
|
2005
|
-
if (this.cookiePolicy !== 'strict') {
|
|
2006
|
-
this.anonymousId = this.getAnonymousId();
|
|
2007
|
-
}
|
|
2008
3111
|
this.initialized = true;
|
|
3112
|
+
// Set up the window close event handler "unload"
|
|
3113
|
+
window.addEventListener && window.addEventListener('unload', this._handle_unload.bind(this));
|
|
2009
3114
|
};
|
|
2010
3115
|
UsermavenClientImpl.prototype.interceptAnalytics = function (analytics) {
|
|
2011
3116
|
var _this = this;
|
|
@@ -2013,11 +3118,13 @@ var UsermavenClientImpl = /** @class */ (function () {
|
|
|
2013
3118
|
var _a;
|
|
2014
3119
|
try {
|
|
2015
3120
|
var payload = __assign({}, chain.payload);
|
|
2016
|
-
getLogger().debug(
|
|
2017
|
-
var integration = chain.integrations[
|
|
3121
|
+
getLogger().debug("Intercepted segment payload", payload.obj);
|
|
3122
|
+
var integration = chain.integrations["Segment.io"];
|
|
2018
3123
|
if (integration && integration.analytics) {
|
|
2019
3124
|
var analyticsOriginal = integration.analytics;
|
|
2020
|
-
if (typeof analyticsOriginal.user ===
|
|
3125
|
+
if (typeof analyticsOriginal.user === "function" &&
|
|
3126
|
+
analyticsOriginal.user() &&
|
|
3127
|
+
typeof analyticsOriginal.user().id === "function") {
|
|
2021
3128
|
payload.obj.userId = analyticsOriginal.user().id();
|
|
2022
3129
|
}
|
|
2023
3130
|
}
|
|
@@ -2025,26 +3132,26 @@ var UsermavenClientImpl = /** @class */ (function () {
|
|
|
2025
3132
|
payload.obj.sentAt = payload.obj.timestamp;
|
|
2026
3133
|
}
|
|
2027
3134
|
var type = chain.payload.type();
|
|
2028
|
-
if (type ===
|
|
3135
|
+
if (type === "track") {
|
|
2029
3136
|
type = chain.payload.event();
|
|
2030
3137
|
}
|
|
2031
|
-
_this._send3p(
|
|
3138
|
+
_this._send3p("ajs", payload, type);
|
|
2032
3139
|
}
|
|
2033
3140
|
catch (e) {
|
|
2034
|
-
getLogger().warn(
|
|
3141
|
+
getLogger().warn("Failed to send an event", e);
|
|
2035
3142
|
}
|
|
2036
3143
|
chain.next(chain.payload);
|
|
2037
3144
|
};
|
|
2038
|
-
if (typeof analytics.addSourceMiddleware ===
|
|
3145
|
+
if (typeof analytics.addSourceMiddleware === "function") {
|
|
2039
3146
|
//analytics is fully initialized
|
|
2040
|
-
getLogger().debug(
|
|
3147
|
+
getLogger().debug("Analytics.js is initialized, calling addSourceMiddleware");
|
|
2041
3148
|
analytics.addSourceMiddleware(interceptor);
|
|
2042
3149
|
}
|
|
2043
3150
|
else {
|
|
2044
|
-
getLogger().debug(
|
|
2045
|
-
analytics.push([
|
|
3151
|
+
getLogger().debug("Analytics.js is not initialized, pushing addSourceMiddleware to callstack");
|
|
3152
|
+
analytics.push(["addSourceMiddleware", interceptor]);
|
|
2046
3153
|
}
|
|
2047
|
-
analytics[
|
|
3154
|
+
analytics["__en_intercepted"] = true;
|
|
2048
3155
|
};
|
|
2049
3156
|
UsermavenClientImpl.prototype.restoreId = function () {
|
|
2050
3157
|
if (this.userIdPersistence) {
|
|
@@ -2070,6 +3177,7 @@ var UsermavenClientImpl = /** @class */ (function () {
|
|
|
2070
3177
|
}
|
|
2071
3178
|
};
|
|
2072
3179
|
UsermavenClientImpl.prototype.unset = function (propertyName, opts) {
|
|
3180
|
+
requireWindow();
|
|
2073
3181
|
var eventType = opts === null || opts === void 0 ? void 0 : opts.eventType;
|
|
2074
3182
|
var persist = (opts === null || opts === void 0 ? void 0 : opts.persist) === undefined || (opts === null || opts === void 0 ? void 0 : opts.persist);
|
|
2075
3183
|
if (!eventType) {
|
|
@@ -2081,9 +3189,6 @@ var UsermavenClientImpl = /** @class */ (function () {
|
|
|
2081
3189
|
if (this.propsPersistance && persist) {
|
|
2082
3190
|
this.propsPersistance.save(this.permanentProperties);
|
|
2083
3191
|
}
|
|
2084
|
-
if (this.sessionManager) {
|
|
2085
|
-
this.sessionManager.resetSessionId();
|
|
2086
|
-
}
|
|
2087
3192
|
};
|
|
2088
3193
|
/**
|
|
2089
3194
|
* Manage session capability
|
|
@@ -2091,9 +3196,13 @@ var UsermavenClientImpl = /** @class */ (function () {
|
|
|
2091
3196
|
*/
|
|
2092
3197
|
UsermavenClientImpl.prototype.manageSession = function (options) {
|
|
2093
3198
|
getLogger().debug('Options', options);
|
|
3199
|
+
options = options || {};
|
|
3200
|
+
getLogger().debug('Options', options);
|
|
3201
|
+
// cross_subdomain_cookie: whether to keep cookie across domains and subdomains
|
|
2094
3202
|
var defaultConfig = {
|
|
2095
|
-
persistence: options
|
|
2096
|
-
persistence_name: options
|
|
3203
|
+
persistence: options.persistence || 'cookie',
|
|
3204
|
+
persistence_name: options.persistence_name || 'session',
|
|
3205
|
+
cross_subdomain_cookie: options.cross_subdomain_cookie || true
|
|
2097
3206
|
};
|
|
2098
3207
|
// TODO: Default session name would be session_
|
|
2099
3208
|
this.config = _.extend(defaultConfig, this.config || {}, {
|
|
@@ -2105,6 +3214,139 @@ var UsermavenClientImpl = /** @class */ (function () {
|
|
|
2105
3214
|
this.sessionManager = new SessionIdManager(this.config, this.persistence);
|
|
2106
3215
|
getLogger().debug('Session Configuration', this.sessionManager);
|
|
2107
3216
|
};
|
|
3217
|
+
/**
|
|
3218
|
+
* Manage auto-capturing
|
|
3219
|
+
* @param options
|
|
3220
|
+
*/
|
|
3221
|
+
UsermavenClientImpl.prototype.manageAutoCapture = function (options) {
|
|
3222
|
+
getLogger().debug("Auto Capture Status: ", this.config['autocapture']);
|
|
3223
|
+
this.__autocapture_enabled = this.config['autocapture'];
|
|
3224
|
+
if (!this.__autocapture_enabled) {
|
|
3225
|
+
return;
|
|
3226
|
+
}
|
|
3227
|
+
var num_buckets = 100;
|
|
3228
|
+
var num_enabled_buckets = 100;
|
|
3229
|
+
if (!autocapture.enabledForProject(this.apiKey, num_buckets, num_enabled_buckets)) {
|
|
3230
|
+
this.config['autocapture'] = false;
|
|
3231
|
+
console.log('Not in active bucket: disabling Automatic Event Collection.');
|
|
3232
|
+
}
|
|
3233
|
+
else if (!autocapture.isBrowserSupported()) {
|
|
3234
|
+
this.config['autocapture'] = false;
|
|
3235
|
+
console.log('Disabling Automatic Event Collection because this browser is not supported');
|
|
3236
|
+
}
|
|
3237
|
+
else {
|
|
3238
|
+
autocapture.init(this);
|
|
3239
|
+
}
|
|
3240
|
+
};
|
|
3241
|
+
/**
|
|
3242
|
+
* Capture an event. This is the most important and
|
|
3243
|
+
* frequently used usermaven function.
|
|
3244
|
+
*
|
|
3245
|
+
* ### Usage:
|
|
3246
|
+
*
|
|
3247
|
+
* // capture an event named 'Registered'
|
|
3248
|
+
* usermaven.capture('Registered', {'Gender': 'Male', 'Age': 21});
|
|
3249
|
+
*
|
|
3250
|
+
* // capture an event using navigator.sendBeacon
|
|
3251
|
+
* usermaven.capture('Left page', {'duration_seconds': 35}, {transport: 'sendBeacon'});
|
|
3252
|
+
*
|
|
3253
|
+
* @param {String} event_name The name of the event. This can be anything the user does - 'Button Click', 'Sign Up', 'Item Purchased', etc.
|
|
3254
|
+
* @param {Object} [properties] A set of properties to include with the event you're sending. These describe the user who did the event or details about the event itself.
|
|
3255
|
+
* @param {Object} [options] Optional configuration for this capture request.
|
|
3256
|
+
* @param {String} [options.transport] Transport method for network request ('XHR' or 'sendBeacon').
|
|
3257
|
+
*/
|
|
3258
|
+
UsermavenClientImpl.prototype.capture = function (event_name, properties) {
|
|
3259
|
+
var _a, _b;
|
|
3260
|
+
if (properties === void 0) { properties = {}; }
|
|
3261
|
+
if (!this.initialized) {
|
|
3262
|
+
console.error('Trying to capture event before initialization');
|
|
3263
|
+
return;
|
|
3264
|
+
}
|
|
3265
|
+
if (_.isUndefined(event_name) || typeof event_name !== 'string') {
|
|
3266
|
+
console.error('No event name provided to posthog.capture');
|
|
3267
|
+
return;
|
|
3268
|
+
}
|
|
3269
|
+
if (_.isBlockedUA(userAgent)) {
|
|
3270
|
+
return;
|
|
3271
|
+
}
|
|
3272
|
+
var start_timestamp = this['persistence'].remove_event_timer(event_name);
|
|
3273
|
+
// update persistence
|
|
3274
|
+
this['persistence'].update_search_keyword(document.referrer);
|
|
3275
|
+
if (this.get_config('store_google')) {
|
|
3276
|
+
this['persistence'].update_campaign_params();
|
|
3277
|
+
}
|
|
3278
|
+
if (this.get_config('save_referrer')) {
|
|
3279
|
+
this['persistence'].update_referrer_info(document.referrer);
|
|
3280
|
+
}
|
|
3281
|
+
var data = {
|
|
3282
|
+
event: event_name + (properties['$event_type'] ? '_' + properties['$event_type'] : ''),
|
|
3283
|
+
properties: this._calculate_event_properties(event_name, properties, start_timestamp),
|
|
3284
|
+
};
|
|
3285
|
+
data = _.copyAndTruncateStrings(data, this.get_config('properties_string_max_length'));
|
|
3286
|
+
// send evnet if there is a tagname available
|
|
3287
|
+
if ((_b = (_a = data.properties) === null || _a === void 0 ? void 0 : _a.autocapture_attributes) === null || _b === void 0 ? void 0 : _b.tag_name) {
|
|
3288
|
+
this.track("$autocapture", data.properties);
|
|
3289
|
+
// this.track(data.event, data.properties)
|
|
3290
|
+
}
|
|
3291
|
+
};
|
|
3292
|
+
UsermavenClientImpl.prototype._calculate_event_properties = function (event_name, event_properties, start_timestamp) {
|
|
3293
|
+
var _a, _b;
|
|
3294
|
+
// set defaults
|
|
3295
|
+
var properties = event_properties || {};
|
|
3296
|
+
if (event_name === '$snapshot') {
|
|
3297
|
+
return properties;
|
|
3298
|
+
}
|
|
3299
|
+
// set $duration if time_event was previously called for this event
|
|
3300
|
+
if (!_.isUndefined(start_timestamp)) {
|
|
3301
|
+
var duration_in_ms = new Date().getTime() - start_timestamp;
|
|
3302
|
+
properties['$duration'] = parseFloat((duration_in_ms / 1000).toFixed(3));
|
|
3303
|
+
}
|
|
3304
|
+
// note: extend writes to the first object, so lets make sure we
|
|
3305
|
+
// don't write to the persistence properties object and info
|
|
3306
|
+
// properties object by passing in a new object
|
|
3307
|
+
// update properties with pageview info and super-properties
|
|
3308
|
+
// exlude , _.info.properties()
|
|
3309
|
+
properties = _.extend({}, this['persistence'].properties(), properties);
|
|
3310
|
+
var property_blacklist = this.get_config('property_blacklist');
|
|
3311
|
+
if (_.isArray(property_blacklist)) {
|
|
3312
|
+
_.each(property_blacklist, function (blacklisted_prop) {
|
|
3313
|
+
delete properties[blacklisted_prop];
|
|
3314
|
+
});
|
|
3315
|
+
}
|
|
3316
|
+
else {
|
|
3317
|
+
console.error('Invalid value for property_blacklist config: ' + property_blacklist);
|
|
3318
|
+
}
|
|
3319
|
+
var sanitize_properties = this.get_config('sanitize_properties');
|
|
3320
|
+
if (sanitize_properties) {
|
|
3321
|
+
properties = sanitize_properties(properties, event_name);
|
|
3322
|
+
}
|
|
3323
|
+
// assign first element from $elements only
|
|
3324
|
+
var attributes = {};
|
|
3325
|
+
var elements = properties['$elements'] || [];
|
|
3326
|
+
if (elements.length) {
|
|
3327
|
+
attributes = elements[0];
|
|
3328
|
+
}
|
|
3329
|
+
properties['autocapture_attributes'] = attributes;
|
|
3330
|
+
properties['autocapture_attributes']["el_text"] = (_a = properties['autocapture_attributes']["$el_text"]) !== null && _a !== void 0 ? _a : "";
|
|
3331
|
+
properties['autocapture_attributes']["event_type"] = (_b = properties["$event_type"]) !== null && _b !== void 0 ? _b : "";
|
|
3332
|
+
delete properties['$ce_version'];
|
|
3333
|
+
delete properties['$event_type'];
|
|
3334
|
+
delete properties['$initial_referrer'];
|
|
3335
|
+
delete properties['$initial_referring_domain'];
|
|
3336
|
+
delete properties['$referrer'];
|
|
3337
|
+
delete properties['$referring_domain'];
|
|
3338
|
+
delete properties['$elements'];
|
|
3339
|
+
// TODO: later remove this from the autotrack code.
|
|
3340
|
+
delete properties['autocapture_attributes']["$el_text"];
|
|
3341
|
+
delete properties['autocapture_attributes']["nth_child"];
|
|
3342
|
+
delete properties['autocapture_attributes']["nth_of_type"];
|
|
3343
|
+
return properties;
|
|
3344
|
+
};
|
|
3345
|
+
UsermavenClientImpl.prototype._handle_unload = function () {
|
|
3346
|
+
if (this.get_config('capture_pageview')) {
|
|
3347
|
+
this.capture('$pageleave');
|
|
3348
|
+
}
|
|
3349
|
+
};
|
|
2108
3350
|
return UsermavenClientImpl;
|
|
2109
3351
|
}());
|
|
2110
3352
|
function interceptSegmentCalls(t) {
|
|
@@ -2115,4 +3357,7 @@ function interceptSegmentCalls(t) {
|
|
|
2115
3357
|
t.interceptAnalytics(win.analytics);
|
|
2116
3358
|
}
|
|
2117
3359
|
|
|
3360
|
+
exports.envs = envs;
|
|
3361
|
+
exports.fetchApi = fetchApi;
|
|
3362
|
+
exports.httpApi = httpApi;
|
|
2118
3363
|
exports.usermavenClient = usermavenClient;
|