@usermaven/sdk-js 1.0.3 → 1.0.6

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