@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.
@@ -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
- return location.hostname.replace('www.', '');
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
- var getCookies = function (useCache) {
46
- if (useCache === void 0) { useCache = false; }
47
- if (useCache && cookieParsingCache) {
48
- return cookieParsingCache;
284
+ function parseCookieString(cookieStr) {
285
+ if (!cookieStr) {
286
+ return {};
49
287
  }
50
288
  var res = {};
51
- var cookies = document.cookie.split(';');
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*" + encodeURIComponent(name).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null;
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, expire, domain, secure) {
69
- var expireString = expire === Infinity ? " expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; max-age=" + expire;
70
- document.cookie = encodeURIComponent(name) + "=" + value + "; path=/;" + expireString + (domain ? "; domain=" + domain : "") + (secure ? "; secure" : "");
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
- document.cookie = name + '= ; expires = Thu, 01 Jan 1970 00:00:00 GMT';
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
- var queryString = qs || window.location.search.substring(1);
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] === '?' ? queryString.substr(1) : queryString).split('&');
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('.')[1];
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) + '0'.repeat(7 - end.length) + 'Z';
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['ph_keyword'] = keyword;
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) > SESSION_CHANGE_THRESHOLD)) {
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
- sessionId: sessionId,
1715
- windowId: windowId,
1908
+ session_id: sessionId,
1909
+ window_id: windowId,
1716
1910
  }
1717
1911
  }
1718
1912
  }
1719
1913
 
1720
- var VERSION_INFO = {
1721
- env: 'production',
1722
- date: '2022-02-18T12:44:44.465Z',
1723
- version: '1.0.4'
1724
- };
1725
- var USERMAVEN_VERSION = "".concat(VERSION_INFO.version, "/").concat(VERSION_INFO.env, "@").concat(VERSION_INFO.date);
1726
- var beaconTransport = function (url, json) {
1727
- getLogger().debug('Sending beacon', json);
1728
- var blob = new Blob([json], { type: 'text/plain' });
1729
- navigator.sendBeacon(url, blob);
1730
- return Promise.resolve();
1731
- };
1732
- var CookiePersistence = /** @class */ (function () {
1733
- function CookiePersistence(cookieDomain, cookieName) {
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
- CookiePersistence.prototype.save = function (props) {
1738
- setCookie(this.cookieName, encodeURIComponent(JSON.stringify(props)), Infinity, this.cookieDomain, document.location.protocol !== 'http:');
1739
- };
1740
- CookiePersistence.prototype.restore = function () {
1741
- var str = getCookie(this.cookieName);
1742
- if (str) {
1743
- try {
1744
- var parsed = JSON.parse(decodeURIComponent(str));
1745
- if (typeof parsed !== 'object') {
1746
- 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"));
1747
- return undefined;
1748
- }
1749
- return parsed;
1750
- }
1751
- catch (e) {
1752
- getLogger().error('Failed to decode JSON from ' + str, e);
1753
- return undefined;
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
- NoPersistence.prototype.save = function (props) {
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 = { globalProps: {}, propsPerEvent: {} };
1785
- this.cookieDomain = '';
1786
- this.trackingHost = '';
1787
- this.idCookieName = '';
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 = 'keep';
1793
- this.ipPolicy = 'keep';
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('Usermaven user identified', props);
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('Id() is called before initialization');
2854
+ getLogger().warn("Id() is called before initialization");
1804
2855
  }
1805
2856
  if (!doNotSendEvent) {
1806
- return this.track('user_identify', {});
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 }, payload);
1832
- return this.compatMode ? __assign(__assign(__assign({}, persistentProps), { eventn_ctx: context }), base) : __assign(__assign(__assign({}, persistentProps), context), base);
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 = '3rdparty';
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 cookiePolicy = this.cookiePolicy !== 'keep' ? "&cookie_policy=".concat(this.cookiePolicy) : '';
1846
- var ipPolicy = this.ipPolicy !== 'keep' ? "&ip_policy=".concat(this.ipPolicy) : '';
1847
- var url = "".concat(this.trackingHost, "/api/v1/event?token=").concat(this.apiKey).concat(cookiePolicy).concat(ipPolicy);
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
- if (this.beaconApi) {
1853
- return beaconTransport(url, jsonString);
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 === 'strict' || this.cookiePolicy === 'comply') {
2909
+ if (this.cookiePolicy === "strict" || this.cookiePolicy === "comply") {
1884
2910
  if (status === 200) {
1885
2911
  var data = response;
1886
- if (typeof response === 'string') {
2912
+ if (typeof response === "string") {
1887
2913
  data = JSON.parse(response);
1888
2914
  }
1889
- if (!data['delete_cookie']) {
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 _a = this.sessionManager.getSessionAndWindowId(), sessionId = _a.sessionId, windowId = _a.windowId;
1901
- // extract company details from identity payload
1902
- var user = __assign({ anonymous_id: this.anonymousId }, this.userProperties);
1903
- var company = user['company'] || {};
1904
- delete user['company'];
1905
- var payload = __assign({ event_id: '', session_id: sessionId, window_id: windowId, user: user, ids: this._getIds(), user_agent: navigator.userAgent, utc_time: reformatDate(now.toISOString()), local_tz_offset: now.getTimezoneOffset(), referer: document.referrer, url: window.location.href, page_title: document.title, doc_path: document.location.pathname, doc_host: document.location.hostname, doc_search: window.location.search, screen_resolution: screen.width + 'x' + screen.height, vp_size: Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0) + 'x' + Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0), user_language: navigator.language, doc_encoding: document.characterSet }, getDataFromParams(parseQuery()));
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('track event of type', type, data);
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 === 'strict') {
1943
- this.ipPolicy = 'strict';
1944
- this.cookiePolicy = 'strict';
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 === 'comply' && this.beaconApi) {
1951
- this.cookiePolicy = 'strict';
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('Initializing Usermaven Tracker tracker', options, USERMAVEN_VERSION);
3038
+ getLogger().debug("Initializing Usemaven Tracker tracker", options, USERMAVEN_VERSION);
1958
3039
  if (!options.key) {
1959
- getLogger().error('Can\'t initialize Usermaven, key property is not set');
3040
+ getLogger().error("Can't initialize Usemaven, key property is not set");
1960
3041
  return;
1961
3042
  }
1962
- this.compatMode = options.compat_mode === undefined ?
1963
- defaultCompatMode :
1964
- !!options.compat_mode;
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['tracking_host'] || 't.usermaven.com');
3048
+ this.trackingHost = getHostWithProtocol(options["tracking_host"] || "t.usermaven.com");
1967
3049
  this.randomizeUrl = options.randomize_url || false;
1968
- this.idCookieName = options.cookie_name || '__eventn_id';
3050
+ this.idCookieName = options.cookie_name || "__eventn_id";
1969
3051
  this.apiKey = options.key;
1970
- if (this.cookiePolicy === 'strict') {
3052
+ if (this.cookiePolicy === "strict") {
1971
3053
  this.propsPersistance = new NoPersistence();
1972
3054
  }
1973
3055
  else {
1974
- this.propsPersistance = new CookiePersistence(this.cookieDomain, this.idCookieName + '_props');
3056
+ this.propsPersistance = isWindowAvailable()
3057
+ ? new CookiePersistence(this.cookieDomain, this.idCookieName + "_props")
3058
+ : new NoPersistence();
1975
3059
  }
1976
- if (this.cookiePolicy === 'strict') {
3060
+ if (this.cookiePolicy === "strict") {
1977
3061
  this.userIdPersistence = new NoPersistence();
1978
3062
  }
1979
3063
  else {
1980
- this.userIdPersistence = new CookiePersistence(this.cookieDomain, this.idCookieName + '_usr');
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('Restored persistent properties', this.permanentProperties);
3075
+ getLogger().debug("Restored persistent properties", this.permanentProperties);
1990
3076
  }
1991
- this.manageSession(options);
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 || ['_ga', '_fbp', '_ym_uid', 'ajs_user_id', 'ajs_anonymous_id'])
1997
- .forEach(function (name) { return _this._3pCookies[name] = true; });
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('GA event interceptor isn\'t supported anymore');
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('Intercepted segment payload', payload.obj);
2017
- var integration = chain.integrations['Segment.io'];
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 === 'function' && analyticsOriginal.user() && typeof analyticsOriginal.user().id === 'function') {
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 === 'track') {
3135
+ if (type === "track") {
2029
3136
  type = chain.payload.event();
2030
3137
  }
2031
- _this._send3p('ajs', payload, type);
3138
+ _this._send3p("ajs", payload, type);
2032
3139
  }
2033
3140
  catch (e) {
2034
- getLogger().warn('Failed to send an event', e);
3141
+ getLogger().warn("Failed to send an event", e);
2035
3142
  }
2036
3143
  chain.next(chain.payload);
2037
3144
  };
2038
- if (typeof analytics.addSourceMiddleware === 'function') {
3145
+ if (typeof analytics.addSourceMiddleware === "function") {
2039
3146
  //analytics is fully initialized
2040
- getLogger().debug('Analytics.js is initialized, calling addSourceMiddleware');
3147
+ getLogger().debug("Analytics.js is initialized, calling addSourceMiddleware");
2041
3148
  analytics.addSourceMiddleware(interceptor);
2042
3149
  }
2043
3150
  else {
2044
- getLogger().debug('Analytics.js is not initialized, pushing addSourceMiddleware to callstack');
2045
- analytics.push(['addSourceMiddleware', interceptor]);
3151
+ getLogger().debug("Analytics.js is not initialized, pushing addSourceMiddleware to callstack");
3152
+ analytics.push(["addSourceMiddleware", interceptor]);
2046
3153
  }
2047
- analytics['__en_intercepted'] = true;
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 ? options.persistence || 'cookie' : 'cookie',
2096
- persistence_name: options ? options.persistence_name || 'session' : 'session',
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;