@usermaven/sdk-js 1.0.5 → 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.
@@ -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,6 +88,159 @@ 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
+
41
244
  // Courtesy: https://stackoverflow.com/a/23945027
42
245
  function extractHostname(url) {
43
246
  var hostname;
@@ -71,24 +274,55 @@ var extractRootDomain = function (url) {
71
274
  return domain;
72
275
  };
73
276
  var getCookieDomain = function () {
74
- return ".".concat(extractRootDomain(location.hostname)); // .localhost
75
- // 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;
76
282
  };
77
283
  var cookieParsingCache;
78
- var getCookies = function (useCache) {
79
- if (useCache === void 0) { useCache = false; }
80
- if (useCache && cookieParsingCache) {
81
- return cookieParsingCache;
284
+ function parseCookieString(cookieStr) {
285
+ if (!cookieStr) {
286
+ return {};
82
287
  }
83
288
  var res = {};
84
- var cookies = document.cookie.split(';');
289
+ var cookies = cookieStr.split(";");
85
290
  for (var i = 0; i < cookies.length; i++) {
86
291
  var cookie = cookies[i];
87
- var idx = cookie.indexOf('=');
292
+ var idx = cookie.indexOf("=");
88
293
  if (idx > 0) {
89
294
  res[cookie.substr(i > 0 ? 1 : 0, i > 0 ? idx - 1 : idx)] = cookie.substr(idx + 1);
90
295
  }
91
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);
92
326
  cookieParsingCache = res;
93
327
  return res;
94
328
  };
@@ -96,24 +330,30 @@ var getCookie = function (name) {
96
330
  if (!name) {
97
331
  return null;
98
332
  }
99
- 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);
100
336
  };
101
- var setCookie = function (name, value, expire, domain, secure) {
102
- var expireString = expire === Infinity ? " expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; max-age=" + expire;
103
- 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);
104
340
  };
105
- var deleteCookie = function (name) {
106
- 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) : "");
107
344
  };
108
345
  var generateId = function () { return Math.random().toString(36).substring(2, 12); };
109
346
  var generateRandom = function () { return Math.random().toString(36).substring(2, 7); };
110
347
  var parseQuery = function (qs) {
111
- 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;
112
352
  var query = {};
113
- var pairs = (queryString[0] === '?' ? queryString.substr(1) : queryString).split('&');
353
+ var pairs = (queryString[0] === "?" ? queryString.substr(1) : queryString).split("&");
114
354
  for (var i = 0; i < pairs.length; i++) {
115
- var pair = pairs[i].split('=');
116
- query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || '');
355
+ var pair = pairs[i].split("=");
356
+ query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || "");
117
357
  }
118
358
  return query;
119
359
  };
@@ -132,7 +372,7 @@ var CLICK_IDS = {
132
372
  var getDataFromParams = function (params) {
133
373
  var result = {
134
374
  utm: {},
135
- click_id: {}
375
+ click_id: {},
136
376
  };
137
377
  for (var name in params) {
138
378
  if (!params.hasOwnProperty(name)) {
@@ -151,14 +391,14 @@ var getDataFromParams = function (params) {
151
391
  };
152
392
  //2020-08-24T13:42:16.439Z -> 2020-08-24T13:42:16.439123Z
153
393
  var reformatDate = function (strDate) {
154
- var end = strDate.split('.')[1];
394
+ var end = strDate.split(".")[1];
155
395
  if (!end) {
156
396
  return strDate;
157
397
  }
158
398
  if (end.length >= 7) {
159
399
  return strDate;
160
400
  }
161
- return strDate.slice(0, -1) + '0'.repeat(7 - end.length) + 'Z';
401
+ return strDate.slice(0, -1) + "0".repeat(7 - end.length) + "Z";
162
402
  };
163
403
  function endsWith(str, suffix) {
164
404
  return str.indexOf(suffix, str.length - suffix.length) !== -1;
@@ -175,85 +415,6 @@ var getHostWithProtocol = function (host) {
175
415
  }
176
416
  };
177
417
 
178
- var LogLevels = {
179
- DEBUG: { name: "DEBUG", severity: 10 },
180
- INFO: { name: "INFO", severity: 100 },
181
- WARN: { name: "WARN", severity: 1000 },
182
- ERROR: { name: "ERROR", severity: 10000 },
183
- NONE: { name: "NONE", severity: 10000 }
184
- };
185
- var rootLogger = null;
186
- /**
187
- * Create logger or return cached instance
188
- */
189
- function getLogger() {
190
- if (rootLogger) {
191
- return rootLogger;
192
- }
193
- else {
194
- return rootLogger = createLogger();
195
- }
196
- }
197
- function setRootLogLevel(logLevelName) {
198
- var logLevel = LogLevels[logLevelName.toLocaleUpperCase()];
199
- if (!logLevel) {
200
- console.warn("Can't find log level with name ".concat(logLevelName.toLocaleUpperCase(), ", defaulting to INFO"));
201
- logLevel = LogLevels.INFO;
202
- }
203
- rootLogger = createLogger(logLevel);
204
- return rootLogger;
205
- }
206
- function setDebugVar(name, val) {
207
- var win = window;
208
- if (!win.__usermavenDebug) {
209
- win.__usermavenDebug = {};
210
- }
211
- win.__usermavenDebug[name] = val;
212
- }
213
- /**
214
- * Creates a loggger with given log-level
215
- * @param logLevel
216
- */
217
- function createLogger(logLevel) {
218
- var globalLogLevel = window['__eventNLogLevel'];
219
- var minLogLevel = LogLevels.WARN;
220
- if (globalLogLevel) {
221
- var level = LogLevels[globalLogLevel.toUpperCase()];
222
- if (level && level > 0) {
223
- minLogLevel = level;
224
- }
225
- }
226
- else if (logLevel) {
227
- minLogLevel = logLevel;
228
- }
229
- var logger = { minLogLevel: minLogLevel };
230
- Object.values(LogLevels).forEach(function (_a) {
231
- var name = _a.name, severity = _a.severity;
232
- logger[name.toLowerCase()] = function () {
233
- var args = [];
234
- for (var _i = 0; _i < arguments.length; _i++) {
235
- args[_i] = arguments[_i];
236
- }
237
- if (severity >= minLogLevel.severity && args.length > 0) {
238
- var message = args[0];
239
- var msgArgs = args.splice(1);
240
- var msgFormatted = "[J-".concat(name, "] ").concat(message);
241
- if (name === 'DEBUG' || name === 'INFO') {
242
- console.log.apply(console, __spreadArray([msgFormatted], msgArgs, false));
243
- }
244
- else if (name === 'WARN') {
245
- console.warn.apply(console, __spreadArray([msgFormatted], msgArgs, false));
246
- }
247
- else {
248
- console.error.apply(console, __spreadArray([msgFormatted], msgArgs, false));
249
- }
250
- }
251
- };
252
- });
253
- setDebugVar("logger", logger);
254
- return logger;
255
- }
256
-
257
418
  var Config$1 = {
258
419
  DEBUG: false,
259
420
  LIB_VERSION: '1.0.0',
@@ -899,7 +1060,7 @@ _.info = {
899
1060
 
900
1061
  var keyword = _.getQueryParam(referrer, param);
901
1062
  if (keyword.length) {
902
- ret['ph_keyword'] = keyword;
1063
+ ret['um_keyword'] = keyword;
903
1064
  }
904
1065
  }
905
1066
 
@@ -1652,14 +1813,12 @@ UserMavenPersistence.prototype.remove_event_timer = function (event_name) {
1652
1813
  return timestamp
1653
1814
  };
1654
1815
 
1655
- // import { INCREMENTAL_SNAPSHOT_EVENT_TYPE, MUTATION_SOURCE_TYPE } from './extensions/sessionrecording'
1656
-
1657
- const SESSION_CHANGE_THRESHOLD = 30 * 60 * 1000; // 30 mins
1658
- /* const SESSION_CHANGE_THRESHOLD = 1 * 60 * 1000 // 1 min */
1659
-
1660
1816
  class SessionIdManager {
1661
1817
  constructor(config, persistence) {
1662
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;
1663
1822
 
1664
1823
  if (config['persistence_name']) {
1665
1824
  this.window_id_storage_key = 'um_' + config['persistence_name'] + '_window_id';
@@ -1718,6 +1877,9 @@ class SessionIdManager {
1718
1877
  // Some recording events are triggered by non-user events (e.g. "X minutes ago" text updating on the screen).
1719
1878
  // We don't want to update the session and window ids in these cases. These events are designated by event
1720
1879
  // type -> incremental update, and source -> mutation.
1880
+ if (this.persistence.disabled) {
1881
+ return {}
1882
+ }
1721
1883
  /* const isUserInteraction = !(
1722
1884
  recordingEvent &&
1723
1885
  recordingEvent.type === INCREMENTAL_SNAPSHOT_EVENT_TYPE &&
@@ -1731,7 +1893,7 @@ class SessionIdManager {
1731
1893
  let [lastTimestamp, sessionId] = this._getSessionId();
1732
1894
  let windowId = this._getWindowId();
1733
1895
 
1734
- if (!sessionId || (Math.abs(timestamp - lastTimestamp) > SESSION_CHANGE_THRESHOLD)) {
1896
+ if (!sessionId || (Math.abs(timestamp - lastTimestamp) > this.session_change_threshold)) {
1735
1897
  sessionId = _.UUID();
1736
1898
  windowId = _.UUID();
1737
1899
  } else if (!windowId) {
@@ -1742,47 +1904,625 @@ class SessionIdManager {
1742
1904
 
1743
1905
  this._setWindowId(windowId);
1744
1906
  this._setSessionId(sessionId, newTimestamp);
1745
-
1746
1907
  return {
1747
- sessionId: sessionId,
1748
- windowId: windowId,
1908
+ session_id: sessionId,
1909
+ window_id: windowId,
1749
1910
  }
1750
1911
  }
1751
1912
  }
1752
1913
 
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 ''
1928
+ }
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);
1956
+ }
1957
+ });
1958
+ }
1959
+
1960
+ return _.trim(elText)
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
+
1753
2462
  var VERSION_INFO = {
1754
2463
  env: 'production',
1755
- date: '2022-03-29T11:24:13.204Z',
1756
- version: '1.0.5'
2464
+ date: '2022-04-05T15:14:31.029Z',
2465
+ version: '1.0.6'
1757
2466
  };
1758
2467
  var USERMAVEN_VERSION = "".concat(VERSION_INFO.version, "/").concat(VERSION_INFO.env, "@").concat(VERSION_INFO.date);
2468
+ var MAX_AGE_TEN_YEARS = 31622400 * 10;
1759
2469
  var beaconTransport = function (url, json) {
1760
- getLogger().debug('Sending beacon', json);
1761
- var blob = new Blob([json], { type: 'text/plain' });
2470
+ getLogger().debug("Sending beacon", json);
2471
+ var blob = new Blob([json], { type: "text/plain" });
1762
2472
  navigator.sendBeacon(url, blob);
1763
2473
  return Promise.resolve();
1764
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
+ }
1765
2500
  var CookiePersistence = /** @class */ (function () {
1766
2501
  function CookiePersistence(cookieDomain, cookieName) {
1767
2502
  this.cookieDomain = cookieDomain;
1768
2503
  this.cookieName = cookieName;
1769
2504
  }
1770
2505
  CookiePersistence.prototype.save = function (props) {
1771
- setCookie(this.cookieName, encodeURIComponent(JSON.stringify(props)), Infinity, this.cookieDomain, document.location.protocol !== 'http:');
2506
+ setCookie(this.cookieName, JSON.stringify(props), {
2507
+ domain: this.cookieDomain,
2508
+ secure: document.location.protocol !== "http:",
2509
+ maxAge: MAX_AGE_TEN_YEARS,
2510
+ });
1772
2511
  };
1773
2512
  CookiePersistence.prototype.restore = function () {
2513
+ expireNonRootCookies(this.cookieName);
1774
2514
  var str = getCookie(this.cookieName);
1775
2515
  if (str) {
1776
2516
  try {
1777
2517
  var parsed = JSON.parse(decodeURIComponent(str));
1778
- if (typeof parsed !== 'object') {
1779
- 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"));
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"));
1780
2520
  return undefined;
1781
2521
  }
1782
2522
  return parsed;
1783
2523
  }
1784
2524
  catch (e) {
1785
- getLogger().error('Failed to decode JSON from ' + str, e);
2525
+ getLogger().error("Failed to decode JSON from " + str, e);
1786
2526
  return undefined;
1787
2527
  }
1788
2528
  }
@@ -1796,8 +2536,7 @@ var CookiePersistence = /** @class */ (function () {
1796
2536
  var NoPersistence = /** @class */ (function () {
1797
2537
  function NoPersistence() {
1798
2538
  }
1799
- NoPersistence.prototype.save = function (props) {
1800
- };
2539
+ NoPersistence.prototype.save = function (props) { };
1801
2540
  NoPersistence.prototype.restore = function () {
1802
2541
  return undefined;
1803
2542
  };
@@ -1810,116 +2549,370 @@ function usermavenClient(opts) {
1810
2549
  client.init(opts);
1811
2550
  return client;
1812
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
+ };
1813
2821
  var UsermavenClientImpl = /** @class */ (function () {
1814
2822
  function UsermavenClientImpl() {
1815
- this.anonymousId = '';
1816
2823
  this.userProperties = {};
1817
- this.permanentProperties = { globalProps: {}, propsPerEvent: {} };
1818
- this.cookieDomain = '';
1819
- this.trackingHost = '';
1820
- this.idCookieName = '';
2824
+ this.permanentProperties = {
2825
+ globalProps: {},
2826
+ propsPerEvent: {},
2827
+ };
2828
+ this.cookieDomain = "";
2829
+ this.trackingHost = "";
2830
+ this.idCookieName = "";
1821
2831
  this.randomizeUrl = false;
1822
- this.apiKey = '';
2832
+ this.apiKey = "";
1823
2833
  this.initialized = false;
1824
2834
  this._3pCookies = {};
1825
- this.cookiePolicy = 'keep';
1826
- this.ipPolicy = 'keep';
2835
+ this.cookiePolicy = "keep";
2836
+ this.ipPolicy = "keep";
1827
2837
  this.beaconApi = false;
1828
- }
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
+ };
1829
2847
  UsermavenClientImpl.prototype.id = function (props, doNotSendEvent) {
1830
2848
  this.userProperties = __assign(__assign({}, this.userProperties), props);
1831
- getLogger().debug('Usermaven user identified', props);
2849
+ getLogger().debug("Usermaven user identified", props);
1832
2850
  if (this.userIdPersistence) {
1833
2851
  this.userIdPersistence.save(props);
1834
2852
  }
1835
2853
  else {
1836
- getLogger().warn('Id() is called before initialization');
2854
+ getLogger().warn("Id() is called before initialization");
1837
2855
  }
1838
2856
  if (!doNotSendEvent) {
1839
- return this.track('user_identify', {});
2857
+ return this.track("user_identify", {});
1840
2858
  }
1841
2859
  else {
1842
2860
  return Promise.resolve();
1843
2861
  }
1844
2862
  };
1845
2863
  UsermavenClientImpl.prototype.rawTrack = function (payload) {
1846
- this.sendJson(payload);
1847
- };
1848
- UsermavenClientImpl.prototype.getAnonymousId = function () {
1849
- var idCookie = getCookie(this.idCookieName);
1850
- if (idCookie) {
1851
- getLogger().debug('Existing user id', idCookie);
1852
- return idCookie;
1853
- }
1854
- var newId = generateId();
1855
- getLogger().debug('New user id', newId);
1856
- setCookie(this.idCookieName, newId, Infinity, this.cookieDomain, document.location.protocol !== 'http:');
1857
- return newId;
2864
+ return this.sendJson(payload);
1858
2865
  };
1859
2866
  UsermavenClientImpl.prototype.makeEvent = function (event_type, src, payload) {
1860
2867
  var _a;
2868
+ var env = payload.env, payloadData = __rest(payload, ["env"]);
2869
+ if (!env) {
2870
+ env = isWindowAvailable() ? envs.browser() : envs.empty();
2871
+ }
1861
2872
  this.restoreId();
1862
- var context = this.getCtx();
2873
+ var context = this.getCtx(env);
1863
2874
  var persistentProps = __assign(__assign({}, this.permanentProperties.globalProps), ((_a = this.permanentProperties.propsPerEvent[event_type]) !== null && _a !== void 0 ? _a : {}));
1864
- var base = __assign({ api_key: this.apiKey, src: src, event_type: event_type }, payload);
1865
- 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);
1866
2882
  };
1867
2883
  UsermavenClientImpl.prototype._send3p = function (sourceType, object, type) {
1868
- var eventType = '3rdparty';
1869
- if (type && type !== '') {
2884
+ var eventType = "3rdparty";
2885
+ if (type && type !== "") {
1870
2886
  eventType = type;
1871
2887
  }
1872
2888
  var e = this.makeEvent(eventType, sourceType, {
1873
- src_payload: object
2889
+ src_payload: object,
1874
2890
  });
1875
2891
  return this.sendJson(e);
1876
2892
  };
1877
2893
  UsermavenClientImpl.prototype.sendJson = function (json) {
1878
- var cookiePolicy = this.cookiePolicy !== 'keep' ? "&cookie_policy=".concat(this.cookiePolicy) : '';
1879
- var ipPolicy = this.ipPolicy !== 'keep' ? "&ip_policy=".concat(this.ipPolicy) : '';
1880
- 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);
1881
2899
  if (this.randomizeUrl) {
1882
2900
  url = "".concat(this.trackingHost, "/api.").concat(generateRandom(), "?p_").concat(generateRandom(), "=").concat(this.apiKey).concat(cookiePolicy).concat(ipPolicy);
1883
2901
  }
1884
2902
  var jsonString = JSON.stringify(json);
1885
- if (this.beaconApi) {
1886
- return beaconTransport(url, jsonString);
1887
- }
1888
- else {
1889
- return this.xmlHttpReqTransport(url, jsonString);
1890
- }
1891
- };
1892
- UsermavenClientImpl.prototype.xmlHttpReqTransport = function (url, json) {
1893
- var _this = this;
1894
- var req = new XMLHttpRequest();
1895
- return new Promise(function (resolve, reject) {
1896
- req.onerror = function (e) {
1897
- getLogger().error('Failed to send', json, e);
1898
- _this.postHandle(-1, {});
1899
- reject(new Error("Failed to send JSON. See console logs"));
1900
- };
1901
- req.onload = function () {
1902
- _this.postHandle(req.status, req.response);
1903
- if (req.status !== 200) {
1904
- getLogger().warn("Failed to send data to ".concat(url, " (#").concat(req.status, " - ").concat(req.statusText, ")"), json);
1905
- reject(new Error("Failed to send JSON. Error code: ".concat(req.status, ". See logs for details")));
1906
- }
1907
- resolve();
1908
- };
1909
- req.open('POST', url);
1910
- req.setRequestHeader('Content-Type', 'application/json');
1911
- req.send(json);
1912
- 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);
1913
2906
  });
1914
2907
  };
1915
2908
  UsermavenClientImpl.prototype.postHandle = function (status, response) {
1916
- if (this.cookiePolicy === 'strict' || this.cookiePolicy === 'comply') {
2909
+ if (this.cookiePolicy === "strict" || this.cookiePolicy === "comply") {
1917
2910
  if (status === 200) {
1918
2911
  var data = response;
1919
- if (typeof response === 'string') {
2912
+ if (typeof response === "string") {
1920
2913
  data = JSON.parse(response);
1921
2914
  }
1922
- if (!data['delete_cookie']) {
2915
+ if (!data["delete_cookie"]) {
1923
2916
  return;
1924
2917
  }
1925
2918
  }
@@ -1927,15 +2920,45 @@ var UsermavenClientImpl = /** @class */ (function () {
1927
2920
  this.propsPersistance.delete();
1928
2921
  deleteCookie(this.idCookieName);
1929
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
+ }
1930
2949
  };
1931
- UsermavenClientImpl.prototype.getCtx = function () {
2950
+ UsermavenClientImpl.prototype.getCtx = function (env) {
1932
2951
  var now = new Date();
1933
- var _a = this.sessionManager.getSessionAndWindowId(), sessionId = _a.sessionId, windowId = _a.windowId;
1934
- // extract company details from identity payload
1935
- var user = __assign({ anonymous_id: this.anonymousId }, this.userProperties);
1936
- var company = user['company'] || {};
1937
- delete user['company'];
1938
- 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)));
1939
2962
  // id and name attributes will be checked on backend
1940
2963
  if (Object.keys(company).length) {
1941
2964
  payload['company'] = company;
@@ -1943,74 +2966,104 @@ var UsermavenClientImpl = /** @class */ (function () {
1943
2966
  return payload;
1944
2967
  };
1945
2968
  UsermavenClientImpl.prototype._getIds = function () {
2969
+ if (!isWindowAvailable()) {
2970
+ return {};
2971
+ }
1946
2972
  var cookies = getCookies(false);
1947
2973
  var res = {};
1948
2974
  for (var _i = 0, _a = Object.entries(cookies); _i < _a.length; _i++) {
1949
2975
  var _b = _a[_i], key = _b[0], value = _b[1];
1950
2976
  if (this._3pCookies[key]) {
1951
- res[key.charAt(0) == '_' ?
1952
- key.substr(1) :
1953
- key] = value;
2977
+ res[key.charAt(0) == "_" ? key.substr(1) : key] = value;
1954
2978
  }
1955
2979
  }
1956
2980
  return res;
1957
2981
  };
1958
2982
  UsermavenClientImpl.prototype.track = function (type, payload) {
1959
2983
  var data = payload || {};
1960
- getLogger().debug('track event of type', type, data);
1961
- var e = this.makeEvent(type, this.compatMode ?
1962
- 'eventn' :
1963
- 'usermaven', payload || {});
2984
+ getLogger().debug("track event of type", type, data);
2985
+ var e = this.makeEvent(type, this.compatMode ? "eventn" : "usermaven", payload || {});
1964
2986
  return this.sendJson(e);
1965
2987
  };
1966
2988
  UsermavenClientImpl.prototype.init = function (options) {
1967
2989
  var _this = this;
1968
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
+ }
1969
3017
  if (options.ip_policy) {
1970
3018
  this.ipPolicy = options.ip_policy;
1971
3019
  }
1972
3020
  if (options.cookie_policy) {
1973
3021
  this.cookiePolicy = options.cookie_policy;
1974
3022
  }
1975
- if (options.privacy_policy === 'strict') {
1976
- this.ipPolicy = 'strict';
1977
- this.cookiePolicy = 'strict';
3023
+ if (options.privacy_policy === "strict") {
3024
+ this.ipPolicy = "strict";
3025
+ this.cookiePolicy = "strict";
1978
3026
  }
1979
3027
  if (options.use_beacon_api && navigator.sendBeacon) {
1980
3028
  this.beaconApi = true;
1981
3029
  }
1982
3030
  //can't handle delete cookie response when beacon api
1983
- if (this.cookiePolicy === 'comply' && this.beaconApi) {
1984
- this.cookiePolicy = 'strict';
3031
+ if (this.cookiePolicy === "comply" && this.beaconApi) {
3032
+ this.cookiePolicy = "strict";
1985
3033
  }
1986
3034
  if (options.log_level) {
1987
3035
  setRootLogLevel(options.log_level);
1988
3036
  }
1989
3037
  this.initialOptions = options;
1990
- getLogger().debug('Initializing Usermaven Tracker tracker', options, USERMAVEN_VERSION);
3038
+ getLogger().debug("Initializing Usemaven Tracker tracker", options, USERMAVEN_VERSION);
1991
3039
  if (!options.key) {
1992
- getLogger().error('Can\'t initialize Usermaven, key property is not set');
3040
+ getLogger().error("Can't initialize Usemaven, key property is not set");
1993
3041
  return;
1994
3042
  }
1995
- this.compatMode = options.compat_mode === undefined ?
1996
- defaultCompatMode :
1997
- !!options.compat_mode;
3043
+ this.compatMode =
3044
+ options.compat_mode === undefined
3045
+ ? defaultCompatMode
3046
+ : !!options.compat_mode;
1998
3047
  this.cookieDomain = options.cookie_domain || getCookieDomain();
1999
- this.trackingHost = getHostWithProtocol(options['tracking_host'] || 't.usermaven.com');
3048
+ this.trackingHost = getHostWithProtocol(options["tracking_host"] || "t.usermaven.com");
2000
3049
  this.randomizeUrl = options.randomize_url || false;
2001
- this.idCookieName = options.cookie_name || '__eventn_id';
3050
+ this.idCookieName = options.cookie_name || "__eventn_id";
2002
3051
  this.apiKey = options.key;
2003
- if (this.cookiePolicy === 'strict') {
3052
+ if (this.cookiePolicy === "strict") {
2004
3053
  this.propsPersistance = new NoPersistence();
2005
3054
  }
2006
3055
  else {
2007
- this.propsPersistance = new CookiePersistence(this.cookieDomain, this.idCookieName + '_props');
3056
+ this.propsPersistance = isWindowAvailable()
3057
+ ? new CookiePersistence(this.cookieDomain, this.idCookieName + "_props")
3058
+ : new NoPersistence();
2008
3059
  }
2009
- if (this.cookiePolicy === 'strict') {
3060
+ if (this.cookiePolicy === "strict") {
2010
3061
  this.userIdPersistence = new NoPersistence();
2011
3062
  }
2012
3063
  else {
2013
- this.userIdPersistence = new CookiePersistence(this.cookieDomain, this.idCookieName + '_usr');
3064
+ this.userIdPersistence = isWindowAvailable()
3065
+ ? new CookiePersistence(this.cookieDomain, this.idCookieName + "_usr")
3066
+ : new NoPersistence();
2014
3067
  }
2015
3068
  if (this.propsPersistance) {
2016
3069
  var restored = this.propsPersistance.restore();
@@ -2019,26 +3072,45 @@ var UsermavenClientImpl = /** @class */ (function () {
2019
3072
  this.permanentProperties.globalProps = (_a = restored.globalProps) !== null && _a !== void 0 ? _a : {};
2020
3073
  this.permanentProperties.propsPerEvent = (_b = restored.propsPerEvent) !== null && _b !== void 0 ? _b : {};
2021
3074
  }
2022
- getLogger().debug('Restored persistent properties', this.permanentProperties);
3075
+ getLogger().debug("Restored persistent properties", this.permanentProperties);
2023
3076
  }
2024
- 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: true,
3084
+ save_referrer: true,
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);
2025
3093
  if (options.capture_3rd_party_cookies === false) {
2026
3094
  this._3pCookies = {};
2027
3095
  }
2028
3096
  else {
2029
- (options.capture_3rd_party_cookies || ['_ga', '_fbp', '_ym_uid', 'ajs_user_id', 'ajs_anonymous_id'])
2030
- .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); });
2031
3104
  }
2032
3105
  if (options.ga_hook) {
2033
- getLogger().warn('GA event interceptor isn\'t supported anymore');
3106
+ getLogger().warn("GA event interceptor isn't supported anymore");
2034
3107
  }
2035
3108
  if (options.segment_hook) {
2036
3109
  interceptSegmentCalls(this);
2037
3110
  }
2038
- if (this.cookiePolicy !== 'strict') {
2039
- this.anonymousId = this.getAnonymousId();
2040
- }
2041
3111
  this.initialized = true;
3112
+ // Set up the window close event handler "unload"
3113
+ window.addEventListener && window.addEventListener('unload', this._handle_unload.bind(this));
2042
3114
  };
2043
3115
  UsermavenClientImpl.prototype.interceptAnalytics = function (analytics) {
2044
3116
  var _this = this;
@@ -2046,11 +3118,13 @@ var UsermavenClientImpl = /** @class */ (function () {
2046
3118
  var _a;
2047
3119
  try {
2048
3120
  var payload = __assign({}, chain.payload);
2049
- getLogger().debug('Intercepted segment payload', payload.obj);
2050
- var integration = chain.integrations['Segment.io'];
3121
+ getLogger().debug("Intercepted segment payload", payload.obj);
3122
+ var integration = chain.integrations["Segment.io"];
2051
3123
  if (integration && integration.analytics) {
2052
3124
  var analyticsOriginal = integration.analytics;
2053
- 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") {
2054
3128
  payload.obj.userId = analyticsOriginal.user().id();
2055
3129
  }
2056
3130
  }
@@ -2058,26 +3132,26 @@ var UsermavenClientImpl = /** @class */ (function () {
2058
3132
  payload.obj.sentAt = payload.obj.timestamp;
2059
3133
  }
2060
3134
  var type = chain.payload.type();
2061
- if (type === 'track') {
3135
+ if (type === "track") {
2062
3136
  type = chain.payload.event();
2063
3137
  }
2064
- _this._send3p('ajs', payload, type);
3138
+ _this._send3p("ajs", payload, type);
2065
3139
  }
2066
3140
  catch (e) {
2067
- getLogger().warn('Failed to send an event', e);
3141
+ getLogger().warn("Failed to send an event", e);
2068
3142
  }
2069
3143
  chain.next(chain.payload);
2070
3144
  };
2071
- if (typeof analytics.addSourceMiddleware === 'function') {
3145
+ if (typeof analytics.addSourceMiddleware === "function") {
2072
3146
  //analytics is fully initialized
2073
- getLogger().debug('Analytics.js is initialized, calling addSourceMiddleware');
3147
+ getLogger().debug("Analytics.js is initialized, calling addSourceMiddleware");
2074
3148
  analytics.addSourceMiddleware(interceptor);
2075
3149
  }
2076
3150
  else {
2077
- getLogger().debug('Analytics.js is not initialized, pushing addSourceMiddleware to callstack');
2078
- analytics.push(['addSourceMiddleware', interceptor]);
3151
+ getLogger().debug("Analytics.js is not initialized, pushing addSourceMiddleware to callstack");
3152
+ analytics.push(["addSourceMiddleware", interceptor]);
2079
3153
  }
2080
- analytics['__en_intercepted'] = true;
3154
+ analytics["__en_intercepted"] = true;
2081
3155
  };
2082
3156
  UsermavenClientImpl.prototype.restoreId = function () {
2083
3157
  if (this.userIdPersistence) {
@@ -2103,6 +3177,7 @@ var UsermavenClientImpl = /** @class */ (function () {
2103
3177
  }
2104
3178
  };
2105
3179
  UsermavenClientImpl.prototype.unset = function (propertyName, opts) {
3180
+ requireWindow();
2106
3181
  var eventType = opts === null || opts === void 0 ? void 0 : opts.eventType;
2107
3182
  var persist = (opts === null || opts === void 0 ? void 0 : opts.persist) === undefined || (opts === null || opts === void 0 ? void 0 : opts.persist);
2108
3183
  if (!eventType) {
@@ -2114,15 +3189,13 @@ var UsermavenClientImpl = /** @class */ (function () {
2114
3189
  if (this.propsPersistance && persist) {
2115
3190
  this.propsPersistance.save(this.permanentProperties);
2116
3191
  }
2117
- if (this.sessionManager) {
2118
- this.sessionManager.resetSessionId();
2119
- }
2120
3192
  };
2121
3193
  /**
2122
3194
  * Manage session capability
2123
3195
  * @param options
2124
3196
  */
2125
3197
  UsermavenClientImpl.prototype.manageSession = function (options) {
3198
+ getLogger().debug('Options', options);
2126
3199
  options = options || {};
2127
3200
  getLogger().debug('Options', options);
2128
3201
  // cross_subdomain_cookie: whether to keep cookie across domains and subdomains
@@ -2141,6 +3214,135 @@ var UsermavenClientImpl = /** @class */ (function () {
2141
3214
  this.sessionManager = new SessionIdManager(this.config, this.persistence);
2142
3215
  getLogger().debug('Session Configuration', this.sessionManager);
2143
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
+ if (properties === void 0) { properties = {}; }
3260
+ if (!this.initialized) {
3261
+ console.error('Trying to capture event before initialization');
3262
+ return;
3263
+ }
3264
+ if (_.isUndefined(event_name) || typeof event_name !== 'string') {
3265
+ console.error('No event name provided to posthog.capture');
3266
+ return;
3267
+ }
3268
+ if (_.isBlockedUA(userAgent)) {
3269
+ return;
3270
+ }
3271
+ var start_timestamp = this['persistence'].remove_event_timer(event_name);
3272
+ // update persistence
3273
+ this['persistence'].update_search_keyword(document.referrer);
3274
+ if (this.get_config('store_google')) {
3275
+ this['persistence'].update_campaign_params();
3276
+ }
3277
+ if (this.get_config('save_referrer')) {
3278
+ this['persistence'].update_referrer_info(document.referrer);
3279
+ }
3280
+ var data = {
3281
+ event: event_name + (properties['$event_type'] ? '_' + properties['$event_type'] : ''),
3282
+ properties: this._calculate_event_properties(event_name, properties, start_timestamp),
3283
+ };
3284
+ data = _.copyAndTruncateStrings(data, this.get_config('properties_string_max_length'));
3285
+ // this.track(data.event, data.properties)
3286
+ this.track("$autocapture", data.properties);
3287
+ };
3288
+ UsermavenClientImpl.prototype._calculate_event_properties = function (event_name, event_properties, start_timestamp) {
3289
+ var _a, _b;
3290
+ // set defaults
3291
+ var properties = event_properties || {};
3292
+ if (event_name === '$snapshot') {
3293
+ return properties;
3294
+ }
3295
+ // set $duration if time_event was previously called for this event
3296
+ if (!_.isUndefined(start_timestamp)) {
3297
+ var duration_in_ms = new Date().getTime() - start_timestamp;
3298
+ properties['$duration'] = parseFloat((duration_in_ms / 1000).toFixed(3));
3299
+ }
3300
+ // note: extend writes to the first object, so lets make sure we
3301
+ // don't write to the persistence properties object and info
3302
+ // properties object by passing in a new object
3303
+ // update properties with pageview info and super-properties
3304
+ // exlude , _.info.properties()
3305
+ properties = _.extend({}, this['persistence'].properties(), properties);
3306
+ var property_blacklist = this.get_config('property_blacklist');
3307
+ if (_.isArray(property_blacklist)) {
3308
+ _.each(property_blacklist, function (blacklisted_prop) {
3309
+ delete properties[blacklisted_prop];
3310
+ });
3311
+ }
3312
+ else {
3313
+ console.error('Invalid value for property_blacklist config: ' + property_blacklist);
3314
+ }
3315
+ var sanitize_properties = this.get_config('sanitize_properties');
3316
+ if (sanitize_properties) {
3317
+ properties = sanitize_properties(properties, event_name);
3318
+ }
3319
+ // assign first element from $elements only
3320
+ var attributes = {};
3321
+ var elements = properties['$elements'] || [];
3322
+ if (elements.length) {
3323
+ attributes = elements[0];
3324
+ }
3325
+ properties['autocapture_attributes'] = attributes;
3326
+ properties['autocapture_attributes']["el_text"] = (_a = properties['autocapture_attributes']["$el_text"]) !== null && _a !== void 0 ? _a : "";
3327
+ properties['autocapture_attributes']["event_type"] = (_b = properties["$event_type"]) !== null && _b !== void 0 ? _b : "";
3328
+ delete properties['$ce_version'];
3329
+ delete properties['$event_type'];
3330
+ delete properties['$initial_referrer'];
3331
+ delete properties['$initial_referring_domain'];
3332
+ delete properties['$referrer'];
3333
+ delete properties['$referring_domain'];
3334
+ delete properties['$elements'];
3335
+ // TODO: later remove this from the autotrack code.
3336
+ delete properties['autocapture_attributes']["$el_text"];
3337
+ delete properties['autocapture_attributes']["nth_child"];
3338
+ delete properties['autocapture_attributes']["nth_of_type"];
3339
+ return properties;
3340
+ };
3341
+ UsermavenClientImpl.prototype._handle_unload = function () {
3342
+ if (this.get_config('capture_pageview')) {
3343
+ this.capture('$pageleave');
3344
+ }
3345
+ };
2144
3346
  return UsermavenClientImpl;
2145
3347
  }());
2146
3348
  function interceptSegmentCalls(t) {
@@ -2151,4 +3353,7 @@ function interceptSegmentCalls(t) {
2151
3353
  t.interceptAnalytics(win.analytics);
2152
3354
  }
2153
3355
 
3356
+ exports.envs = envs;
3357
+ exports.fetchApi = fetchApi;
3358
+ exports.httpApi = httpApi;
2154
3359
  exports.usermavenClient = usermavenClient;