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