@usermaven/sdk-js 1.0.5 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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,184 +1904,1023 @@ 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
 
1753
- var VERSION_INFO = {
1754
- env: 'production',
1755
- date: '2022-03-29T11:24:13.204Z',
1756
- version: '1.0.5'
1757
- };
1758
- var USERMAVEN_VERSION = "".concat(VERSION_INFO.version, "/").concat(VERSION_INFO.env, "@").concat(VERSION_INFO.date);
1759
- var beaconTransport = function (url, json) {
1760
- getLogger().debug('Sending beacon', json);
1761
- var blob = new Blob([json], { type: 'text/plain' });
1762
- navigator.sendBeacon(url, blob);
1763
- return Promise.resolve();
1764
- };
1765
- var CookiePersistence = /** @class */ (function () {
1766
- function CookiePersistence(cookieDomain, cookieName) {
1767
- this.cookieDomain = cookieDomain;
1768
- this.cookieName = cookieName;
1914
+ /*
1915
+ * Get the className of an element, accounting for edge cases where element.className is an object
1916
+ * @param {Element} el - element to get the className of
1917
+ * @returns {string} the element's class
1918
+ */
1919
+ function getClassName(el) {
1920
+ switch (typeof el.className) {
1921
+ case 'string':
1922
+ return el.className
1923
+ case 'object': // handle cases where className might be SVGAnimatedString or some other type
1924
+ return el.className.baseVal || el.getAttribute('class') || ''
1925
+ default:
1926
+ // future proof
1927
+ return ''
1769
1928
  }
1770
- CookiePersistence.prototype.save = function (props) {
1771
- setCookie(this.cookieName, encodeURIComponent(JSON.stringify(props)), Infinity, this.cookieDomain, document.location.protocol !== 'http:');
1772
- };
1773
- CookiePersistence.prototype.restore = function () {
1774
- var str = getCookie(this.cookieName);
1775
- if (str) {
1776
- try {
1777
- 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"));
1780
- return undefined;
1781
- }
1782
- return parsed;
1783
- }
1784
- catch (e) {
1785
- getLogger().error('Failed to decode JSON from ' + str, e);
1786
- return undefined;
1929
+ }
1930
+
1931
+ /*
1932
+ * Get the direct text content of an element, protecting against sensitive data collection.
1933
+ * Concats textContent of each of the element's text node children; this avoids potential
1934
+ * collection of sensitive data that could happen if we used element.textContent and the
1935
+ * element had sensitive child elements, since element.textContent includes child content.
1936
+ * Scrubs values that look like they could be sensitive (i.e. cc or ssn number).
1937
+ * @param {Element} el - element to get the text of
1938
+ * @returns {string} the element's direct text content
1939
+ */
1940
+ function getSafeText(el) {
1941
+ var elText = '';
1942
+
1943
+ if (shouldCaptureElement(el) && !isSensitiveElement(el) && el.childNodes && el.childNodes.length) {
1944
+ _.each(el.childNodes, function (child) {
1945
+ if (isTextNode(child) && child.textContent) {
1946
+ elText += _.trim(child.textContent)
1947
+ // scrub potentially sensitive values
1948
+ .split(/(\s+)/)
1949
+ .filter(shouldCaptureValue)
1950
+ .join('')
1951
+ // normalize whitespace
1952
+ .replace(/[\r\n]/g, ' ')
1953
+ .replace(/[ ]+/g, ' ')
1954
+ // truncate
1955
+ .substring(0, 255);
1787
1956
  }
1788
- }
1789
- return undefined;
1790
- };
1791
- CookiePersistence.prototype.delete = function () {
1792
- deleteCookie(this.cookieName);
1793
- };
1794
- return CookiePersistence;
1795
- }());
1796
- var NoPersistence = /** @class */ (function () {
1797
- function NoPersistence() {
1957
+ });
1798
1958
  }
1799
- NoPersistence.prototype.save = function (props) {
1800
- };
1801
- NoPersistence.prototype.restore = function () {
1802
- return undefined;
1803
- };
1804
- NoPersistence.prototype.delete = function () { };
1805
- return NoPersistence;
1806
- }());
1807
- var defaultCompatMode = false;
1808
- function usermavenClient(opts) {
1809
- var client = new UsermavenClientImpl();
1810
- client.init(opts);
1811
- return client;
1959
+
1960
+ return _.trim(elText)
1812
1961
  }
1813
- var UsermavenClientImpl = /** @class */ (function () {
1814
- function UsermavenClientImpl() {
1815
- this.anonymousId = '';
1816
- this.userProperties = {};
1817
- this.permanentProperties = { globalProps: {}, propsPerEvent: {} };
1818
- this.cookieDomain = '';
1819
- this.trackingHost = '';
1820
- this.idCookieName = '';
1821
- this.randomizeUrl = false;
1822
- this.apiKey = '';
1823
- this.initialized = false;
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
+ function isDataAttribute(attributeName)
2168
+ {
2169
+ if (typeof attributeName === 'string') {
2170
+ return attributeName.startsWith('data-')
2171
+ }
2172
+ return false
2173
+ }
2174
+
2175
+ // Naive rage click implementation: If mouse has not moved than RAGE_CLICK_THRESHOLD_PX
2176
+ // over RAGE_CLICK_CLICK_COUNT clicks with max RAGE_CLICK_TIMEOUT_MS between clicks, it's
2177
+ // counted as a rage click
2178
+ const RAGE_CLICK_THRESHOLD_PX = 30;
2179
+ const RAGE_CLICK_TIMEOUT_MS = 1000;
2180
+ const RAGE_CLICK_CLICK_COUNT = 3;
2181
+
2182
+ class RageClick {
2183
+ constructor(instance, enabled = instance.get_config('rageclick')) {
2184
+ this.clicks = [];
2185
+ this.instance = instance;
2186
+ this.enabled = enabled;
2187
+ }
2188
+
2189
+ click(x, y, timestamp) {
2190
+ if (!this.enabled) {
2191
+ return
2192
+ }
2193
+
2194
+ const lastClick = this.clicks[this.clicks.length - 1];
2195
+ if (
2196
+ lastClick &&
2197
+ Math.abs(x - lastClick.x) + Math.abs(y - lastClick.y) < RAGE_CLICK_THRESHOLD_PX &&
2198
+ timestamp - lastClick.timestamp < RAGE_CLICK_TIMEOUT_MS
2199
+ ) {
2200
+ this.clicks.push({ x, y, timestamp });
2201
+
2202
+ if (this.clicks.length === RAGE_CLICK_CLICK_COUNT) {
2203
+ this.instance.capture('$rageclick');
2204
+ }
2205
+ } else {
2206
+ this.clicks = [{ x, y, timestamp }];
2207
+ }
2208
+ }
2209
+ }
2210
+
2211
+ var autocapture = {
2212
+ _initializedTokens: [],
2213
+
2214
+ _previousElementSibling: function (el) {
2215
+ if (el.previousElementSibling) {
2216
+ return el.previousElementSibling
2217
+ } else {
2218
+ do {
2219
+ el = el.previousSibling;
2220
+ } while (el && !isElementNode(el))
2221
+ return el
2222
+ }
2223
+ },
2224
+
2225
+ _getPropertiesFromElement: function (elem, maskInputs, maskText) {
2226
+ var tag_name = elem.tagName.toLowerCase();
2227
+ var props = {
2228
+ tag_name: tag_name,
2229
+ };
2230
+ if (usefulElements.indexOf(tag_name) > -1 && !maskText) {
2231
+ props['$el_text'] = getSafeText(elem);
2232
+ }
2233
+
2234
+ var classes = getClassName(elem);
2235
+ if (classes.length > 0)
2236
+ props['classes'] = classes.split(' ').filter(function (c) {
2237
+ return c !== ''
2238
+ });
2239
+
2240
+ _.each(elem.attributes, function (attr) {
2241
+ // Only capture attributes we know are safe
2242
+ if (isSensitiveElement(elem) && ['name', 'id', 'class'].indexOf(attr.name) === -1) return
2243
+
2244
+ if (!maskInputs && shouldCaptureValue(attr.value) && !isAngularStyleAttr(attr.name) && !isDataAttribute(attr.name)) {
2245
+ props['attr__' + attr.name] = attr.value;
2246
+ }
2247
+ });
2248
+
2249
+ var nthChild = 1;
2250
+ var nthOfType = 1;
2251
+ var currentElem = elem;
2252
+ while ((currentElem = this._previousElementSibling(currentElem))) {
2253
+ // eslint-disable-line no-cond-assign
2254
+ nthChild++;
2255
+ if (currentElem.tagName === elem.tagName) {
2256
+ nthOfType++;
2257
+ }
2258
+ }
2259
+ props['nth_child'] = nthChild;
2260
+ props['nth_of_type'] = nthOfType;
2261
+
2262
+ return props
2263
+ },
2264
+
2265
+ _getDefaultProperties: function (eventType) {
2266
+ return {
2267
+ $event_type: eventType,
2268
+ $ce_version: 1,
2269
+ }
2270
+ },
2271
+
2272
+ _extractCustomPropertyValue: function (customProperty) {
2273
+ var propValues = [];
2274
+ _.each(document.querySelectorAll(customProperty['css_selector']), function (matchedElem) {
2275
+ var value;
2276
+
2277
+ if (['input', 'select'].indexOf(matchedElem.tagName.toLowerCase()) > -1) {
2278
+ value = matchedElem['value'];
2279
+ } else if (matchedElem['textContent']) {
2280
+ value = matchedElem['textContent'];
2281
+ }
2282
+
2283
+ if (shouldCaptureValue(value)) {
2284
+ propValues.push(value);
2285
+ }
2286
+ });
2287
+ return propValues.join(', ')
2288
+ },
2289
+
2290
+ _getCustomProperties: function (targetElementList) {
2291
+ var props = {};
2292
+ _.each(
2293
+ this._customProperties,
2294
+ function (customProperty) {
2295
+ _.each(
2296
+ customProperty['event_selectors'],
2297
+ function (eventSelector) {
2298
+ var eventElements = document.querySelectorAll(eventSelector);
2299
+ _.each(
2300
+ eventElements,
2301
+ function (eventElement) {
2302
+ if (_.includes(targetElementList, eventElement) && shouldCaptureElement(eventElement)) {
2303
+ props[customProperty['name']] = this._extractCustomPropertyValue(customProperty);
2304
+ }
2305
+ },
2306
+ this
2307
+ );
2308
+ },
2309
+ this
2310
+ );
2311
+ },
2312
+ this
2313
+ );
2314
+ return props
2315
+ },
2316
+
2317
+ _getEventTarget: function (e) {
2318
+ // https://developer.mozilla.org/en-US/docs/Web/API/Event/target#Compatibility_notes
2319
+ if (typeof e.target === 'undefined') {
2320
+ return e.srcElement
2321
+ } else {
2322
+ if (e.target.shadowRoot) {
2323
+ return e.composedPath()[0]
2324
+ }
2325
+ return e.target
2326
+ }
2327
+ },
2328
+
2329
+ _captureEvent: function (e, instance) {
2330
+ /*** Don't mess with this code without running IE8 tests on it ***/
2331
+ var target = this._getEventTarget(e);
2332
+ if (isTextNode(target)) {
2333
+ // defeat Safari bug (see: http://www.quirksmode.org/js/events_properties.html)
2334
+ target = target.parentNode;
2335
+ }
2336
+
2337
+ if (e.type === 'click') {
2338
+ this.rageclicks.click(e.clientX, e.clientY, new Date().getTime());
2339
+ }
2340
+
2341
+ if (shouldCaptureDomEvent(target, e)) {
2342
+ var targetElementList = [target];
2343
+ var curEl = target;
2344
+ while (curEl.parentNode && !isTag(curEl, 'body')) {
2345
+ if (curEl.parentNode.nodeType === 11) {
2346
+ targetElementList.push(curEl.parentNode.host);
2347
+ curEl = curEl.parentNode.host;
2348
+ continue
2349
+ }
2350
+ targetElementList.push(curEl.parentNode);
2351
+ curEl = curEl.parentNode;
2352
+ }
2353
+
2354
+ var elementsJson = [];
2355
+ var href,
2356
+ explicitNoCapture = false;
2357
+ _.each(
2358
+ targetElementList,
2359
+ function (el) {
2360
+ var shouldCaptureEl = shouldCaptureElement(el);
2361
+
2362
+ // if the element or a parent element is an anchor tag
2363
+ // include the href as a property
2364
+ if (el.tagName.toLowerCase() === 'a') {
2365
+ href = el.getAttribute('href');
2366
+ href = shouldCaptureEl && shouldCaptureValue(href) && href;
2367
+ }
2368
+
2369
+ // allow users to programmatically prevent capturing of elements by adding class 'um-no-capture'
2370
+ var classes = getClassName(el).split(' ');
2371
+ if (_.includes(classes, 'um-no-capture')) {
2372
+ explicitNoCapture = true;
2373
+ }
2374
+
2375
+ elementsJson.push(
2376
+ this._getPropertiesFromElement(
2377
+ el,
2378
+ instance.get_config('mask_all_element_attributes'),
2379
+ instance.get_config('mask_all_text')
2380
+ )
2381
+ );
2382
+ },
2383
+ this
2384
+ );
2385
+
2386
+ if (!instance.get_config('mask_all_text')) {
2387
+ elementsJson[0]['$el_text'] = getSafeText(target);
2388
+ }
2389
+
2390
+ if (href) {
2391
+ elementsJson[0]['attr__href'] = href;
2392
+ }
2393
+
2394
+ if (explicitNoCapture) {
2395
+ return false
2396
+ }
2397
+
2398
+ var props = _.extend(
2399
+ this._getDefaultProperties(e.type),
2400
+ {
2401
+ $elements: elementsJson,
2402
+ },
2403
+ this._getCustomProperties(targetElementList)
2404
+ );
2405
+
2406
+ instance.capture('$autocapture', props);
2407
+ return true
2408
+ }
2409
+ },
2410
+
2411
+ // only reason is to stub for unit tests
2412
+ // since you can't override window.location props
2413
+ _navigate: function (href) {
2414
+ window.location.href = href;
2415
+ },
2416
+
2417
+ _addDomEventHandlers: function (instance) {
2418
+ var handler = _.bind(function (e) {
2419
+ e = e || window.event;
2420
+ this._captureEvent(e, instance);
2421
+ }, this);
2422
+ _.register_event(document, 'submit', handler, false, true);
2423
+ _.register_event(document, 'change', handler, false, true);
2424
+ _.register_event(document, 'click', handler, false, true);
2425
+ },
2426
+
2427
+ _customProperties: {},
2428
+ init: function (instance) {
2429
+ var token = instance.get_config('token');
2430
+ console.log('Initializing autocapture for token "' + token + '"');
2431
+ if (this._initializedTokens.indexOf(token) > -1) {
2432
+ console.log('autocapture already initialized for token "' + token + '"');
2433
+ return
2434
+ }
2435
+
2436
+ this._initializedTokens.push(token);
2437
+
2438
+ if (instance.get_config('autocapture')) {
2439
+ this._addDomEventHandlers(instance);
2440
+ } else {
2441
+ instance['__autocapture_enabled'] = false;
2442
+ }
2443
+
2444
+ this.rageclicks = new RageClick(instance);
2445
+ },
2446
+
2447
+ // this is a mechanism to ramp up CE with no server-side interaction.
2448
+ // when CE is active, every page load results in a decide request. we
2449
+ // need to gently ramp this up so we don't overload decide. this decides
2450
+ // deterministically if CE is enabled for this project by modding the char
2451
+ // value of the project token.
2452
+ enabledForProject: function (token, numBuckets, numEnabledBuckets) {
2453
+ numBuckets = !_.isUndefined(numBuckets) ? numBuckets : 10;
2454
+ numEnabledBuckets = !_.isUndefined(numEnabledBuckets) ? numEnabledBuckets : 10;
2455
+ var charCodeSum = 0;
2456
+ for (var i = 0; i < token.length; i++) {
2457
+ charCodeSum += token.charCodeAt(i);
2458
+ }
2459
+ return charCodeSum % numBuckets < numEnabledBuckets
2460
+ },
2461
+
2462
+ isBrowserSupported: function () {
2463
+ return _.isFunction(document.querySelectorAll)
2464
+ },
2465
+ };
2466
+
2467
+ _.bind_instance_methods(autocapture);
2468
+ _.safewrap_instance_methods(autocapture);
2469
+
2470
+ var VERSION_INFO = {
2471
+ env: 'production',
2472
+ date: '2022-04-09T09:14:05.991Z',
2473
+ version: '1.0.8'
2474
+ };
2475
+ var USERMAVEN_VERSION = "".concat(VERSION_INFO.version, "/").concat(VERSION_INFO.env, "@").concat(VERSION_INFO.date);
2476
+ var MAX_AGE_TEN_YEARS = 31622400 * 10;
2477
+ var beaconTransport = function (url, json) {
2478
+ getLogger().debug("Sending beacon", json);
2479
+ var blob = new Blob([json], { type: "text/plain" });
2480
+ navigator.sendBeacon(url, blob);
2481
+ return Promise.resolve();
2482
+ };
2483
+ function tryFormat(string) {
2484
+ if (typeof string === "string") {
2485
+ try {
2486
+ return JSON.stringify(JSON.parse(string), null, 2);
2487
+ }
2488
+ catch (e) {
2489
+ return string;
2490
+ }
2491
+ }
2492
+ }
2493
+ var echoTransport = function (url, json) {
2494
+ console.log("Jitsu client tried to send payload to ".concat(url), tryFormat(json));
2495
+ return Promise.resolve();
2496
+ };
2497
+ // This is a hack to expire all cookies with non-root path left behind by invalid tracking.
2498
+ // TODO remove soon
2499
+ function expireNonRootCookies(name, path) {
2500
+ if (path === void 0) { path = undefined; }
2501
+ path = path !== null && path !== void 0 ? path : window.location.pathname;
2502
+ if (path == "" || path == "/") {
2503
+ return;
2504
+ }
2505
+ deleteCookie(name, path);
2506
+ expireNonRootCookies(name, path.slice(0, path.lastIndexOf("/")));
2507
+ }
2508
+ var CookiePersistence = /** @class */ (function () {
2509
+ function CookiePersistence(cookieDomain, cookieName) {
2510
+ this.cookieDomain = cookieDomain;
2511
+ this.cookieName = cookieName;
2512
+ }
2513
+ CookiePersistence.prototype.save = function (props) {
2514
+ setCookie(this.cookieName, JSON.stringify(props), {
2515
+ domain: this.cookieDomain,
2516
+ secure: document.location.protocol !== "http:",
2517
+ maxAge: MAX_AGE_TEN_YEARS,
2518
+ });
2519
+ };
2520
+ CookiePersistence.prototype.restore = function () {
2521
+ expireNonRootCookies(this.cookieName);
2522
+ var str = getCookie(this.cookieName);
2523
+ if (str) {
2524
+ try {
2525
+ var parsed = JSON.parse(decodeURIComponent(str));
2526
+ if (typeof parsed !== "object") {
2527
+ 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"));
2528
+ return undefined;
2529
+ }
2530
+ return parsed;
2531
+ }
2532
+ catch (e) {
2533
+ getLogger().error("Failed to decode JSON from " + str, e);
2534
+ return undefined;
2535
+ }
2536
+ }
2537
+ return undefined;
2538
+ };
2539
+ CookiePersistence.prototype.delete = function () {
2540
+ deleteCookie(this.cookieName);
2541
+ };
2542
+ return CookiePersistence;
2543
+ }());
2544
+ var NoPersistence = /** @class */ (function () {
2545
+ function NoPersistence() {
2546
+ }
2547
+ NoPersistence.prototype.save = function (props) { };
2548
+ NoPersistence.prototype.restore = function () {
2549
+ return undefined;
2550
+ };
2551
+ NoPersistence.prototype.delete = function () { };
2552
+ return NoPersistence;
2553
+ }());
2554
+ var defaultCompatMode = false;
2555
+ function usermavenClient(opts) {
2556
+ var client = new UsermavenClientImpl();
2557
+ client.init(opts);
2558
+ return client;
2559
+ }
2560
+ var browserEnv = {
2561
+ getSourceIp: function () { return undefined; },
2562
+ describeClient: function () { return ({
2563
+ referer: document.referrer,
2564
+ url: window.location.href,
2565
+ page_title: document.title,
2566
+ doc_path: document.location.pathname,
2567
+ doc_host: document.location.hostname,
2568
+ doc_search: window.location.search,
2569
+ screen_resolution: screen.width + "x" + screen.height,
2570
+ vp_size: Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0) +
2571
+ "x" +
2572
+ Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0),
2573
+ user_agent: navigator.userAgent,
2574
+ user_language: navigator.language,
2575
+ doc_encoding: document.characterSet,
2576
+ }); },
2577
+ getAnonymousId: function (_a) {
2578
+ var name = _a.name, domain = _a.domain;
2579
+ expireNonRootCookies(name);
2580
+ var idCookie = getCookie(name);
2581
+ if (idCookie) {
2582
+ getLogger().debug("Existing user id", idCookie);
2583
+ return idCookie;
2584
+ }
2585
+ var newId = generateId();
2586
+ getLogger().debug("New user id", newId);
2587
+ setCookie(name, newId, {
2588
+ domain: domain,
2589
+ secure: document.location.protocol !== "http:",
2590
+ maxAge: MAX_AGE_TEN_YEARS,
2591
+ });
2592
+ return newId;
2593
+ },
2594
+ };
2595
+ function ensurePrefix(prefix, str) {
2596
+ if (!str) {
2597
+ return str;
2598
+ }
2599
+ return (str === null || str === void 0 ? void 0 : str.length) > 0 && str.indexOf(prefix) !== 0 ? prefix + str : str;
2600
+ }
2601
+ function cutPostfix(postfixes, str) {
2602
+ for (var _i = 0, _a = typeof postfixes === "string"
2603
+ ? [postfixes]
2604
+ : postfixes; _i < _a.length; _i++) {
2605
+ var postfix = _a[_i];
2606
+ while (str && str.length > 0 && str.charAt(str.length - 1) === postfix) {
2607
+ str = str.substring(0, str.length - 1);
2608
+ }
2609
+ }
2610
+ return str;
2611
+ }
2612
+ function fetchApi(req, res, opts) {
2613
+ if (opts === void 0) { opts = {}; }
2614
+ return {
2615
+ getAnonymousId: function (_a) {
2616
+ var name = _a.name, domain = _a.domain;
2617
+ if (opts === null || opts === void 0 ? void 0 : opts.disableCookies) {
2618
+ return "";
2619
+ }
2620
+ var cookie = parseCookieString(req.headers["cookie"])[name];
2621
+ if (!cookie) {
2622
+ var cookieOpts = {
2623
+ maxAge: 31622400 * 10,
2624
+ httpOnly: false,
2625
+ };
2626
+ if (domain) {
2627
+ cookieOpts.domain = domain;
2628
+ }
2629
+ var newId = generateId();
2630
+ res.headers.set("Set-Cookie", serializeCookie(name, newId, cookieOpts));
2631
+ return newId;
2632
+ }
2633
+ else {
2634
+ return cookie;
2635
+ }
2636
+ },
2637
+ getSourceIp: function () {
2638
+ var ip = req.headers["x-forwarded-for"] || req.headers["x-real-ip"] || req["ip"];
2639
+ return ip && ip.split(",")[0].trim();
2640
+ },
2641
+ describeClient: function () {
2642
+ var requestHost = req.headers.get("host") || req.headers.get("host");
2643
+ var proto = cutPostfix([":", "/"], req.headers["x-forwarded-proto"] || req["nextUrl"]["protocol"] || "http");
2644
+ while (proto && proto.length > 0 && proto.charAt(proto.length - 1)) {
2645
+ proto = proto.substring(0, proto.length - 1);
2646
+ }
2647
+ var reqUrl = req.url || "/";
2648
+ var queryPos = reqUrl.indexOf("?");
2649
+ var path, query;
2650
+ if (queryPos >= 0) {
2651
+ path = reqUrl.substring(0, queryPos);
2652
+ query = reqUrl.substring(queryPos + 1);
2653
+ }
2654
+ else {
2655
+ path = reqUrl;
2656
+ query = undefined;
2657
+ }
2658
+ query = ensurePrefix(query, "?");
2659
+ path = ensurePrefix(path, "/");
2660
+ return {
2661
+ doc_encoding: "",
2662
+ doc_host: requestHost,
2663
+ doc_path: reqUrl,
2664
+ doc_search: query,
2665
+ page_title: "",
2666
+ referer: req.headers["referrer"],
2667
+ screen_resolution: "",
2668
+ url: "".concat(proto, "://").concat(requestHost).concat(path || "").concat(query || ""),
2669
+ user_agent: req.headers["user-agent"],
2670
+ user_language: req.headers["accept-language"] &&
2671
+ req.headers["accept-language"].split(",")[0],
2672
+ vp_size: "",
2673
+ };
2674
+ },
2675
+ };
2676
+ }
2677
+ function httpApi(req, res, opts) {
2678
+ if (opts === void 0) { opts = {}; }
2679
+ var header = function (req, name) {
2680
+ var vals = req.headers[name.toLowerCase()];
2681
+ if (!vals) {
2682
+ return undefined;
2683
+ }
2684
+ if (typeof vals === "string") {
2685
+ return vals;
2686
+ }
2687
+ else if (vals.length > 0) {
2688
+ return vals.join(",");
2689
+ }
2690
+ };
2691
+ return {
2692
+ getAnonymousId: function (_a) {
2693
+ var name = _a.name, domain = _a.domain;
2694
+ if (opts === null || opts === void 0 ? void 0 : opts.disableCookies) {
2695
+ return "";
2696
+ }
2697
+ var cookie = parseCookieString(req.headers["cookie"])[name];
2698
+ if (!cookie) {
2699
+ var cookieOpts = {
2700
+ maxAge: 31622400 * 10,
2701
+ httpOnly: false,
2702
+ };
2703
+ if (domain) {
2704
+ cookieOpts.domain = domain;
2705
+ }
2706
+ var newId = generateId();
2707
+ res.setHeader("Set-Cookie", serializeCookie(name, newId, cookieOpts));
2708
+ return newId;
2709
+ }
2710
+ else {
2711
+ return cookie;
2712
+ }
2713
+ },
2714
+ getSourceIp: function () {
2715
+ var ip = header(req, "x-forwarded-for") ||
2716
+ header(req, "x-real-ip") ||
2717
+ req.socket.remoteAddress;
2718
+ return ip && ip.split(",")[0].trim();
2719
+ },
2720
+ describeClient: function () {
2721
+ var url = req.url
2722
+ ? new URL(req.url, req.url.startsWith("http") ? undefined : "http://localhost")
2723
+ : {};
2724
+ var requestHost = header(req, "x-forwarded-host") || header(req, "host") || url.hostname;
2725
+ var proto = cutPostfix([":", "/"], header(req, "x-forwarded-proto") || url.protocol);
2726
+ var query = ensurePrefix("?", url.search);
2727
+ var path = ensurePrefix("/", url.pathname);
2728
+ return {
2729
+ doc_encoding: "",
2730
+ doc_host: requestHost,
2731
+ doc_path: req.url,
2732
+ doc_search: query,
2733
+ page_title: "",
2734
+ referer: header(req, "referrer"),
2735
+ screen_resolution: "",
2736
+ url: "".concat(proto, "://").concat(requestHost).concat(path || "").concat(query || ""),
2737
+ user_agent: req.headers["user-agent"],
2738
+ user_language: req.headers["accept-language"] &&
2739
+ req.headers["accept-language"].split(",")[0],
2740
+ vp_size: "",
2741
+ };
2742
+ },
2743
+ };
2744
+ }
2745
+ var emptyEnv = {
2746
+ getSourceIp: function () { return undefined; },
2747
+ describeClient: function () { return ({}); },
2748
+ getAnonymousId: function () { return ""; },
2749
+ };
2750
+ /**
2751
+ * Dictionary of supported environments
2752
+ */
2753
+ var envs = {
2754
+ httpApi: httpApi,
2755
+ nextjsApi: httpApi,
2756
+ // fetchApi: fetchApi,
2757
+ // nextjsMiddleware: fetchApi,
2758
+ browser: function () { return browserEnv; },
2759
+ express: httpApi,
2760
+ empty: function () { return emptyEnv; },
2761
+ };
2762
+ var xmlHttpTransport = function (url, jsonPayload, additionalHeaders, handler) {
2763
+ if (handler === void 0) { handler = function (code, body) { }; }
2764
+ var req = new window.XMLHttpRequest();
2765
+ return new Promise(function (resolve, reject) {
2766
+ req.onerror = function (e) {
2767
+ getLogger().error("Failed to send", jsonPayload, e);
2768
+ handler(-1, {});
2769
+ reject(new Error("Failed to send JSON. See console logs"));
2770
+ };
2771
+ req.onload = function () {
2772
+ if (req.status !== 200) {
2773
+ handler(req.status, {});
2774
+ getLogger().warn("Failed to send data to ".concat(url, " (#").concat(req.status, " - ").concat(req.statusText, ")"), jsonPayload);
2775
+ reject(new Error("Failed to send JSON. Error code: ".concat(req.status, ". See logs for details")));
2776
+ }
2777
+ else {
2778
+ handler(req.status, req.responseText);
2779
+ }
2780
+ resolve();
2781
+ };
2782
+ req.open("POST", url);
2783
+ req.setRequestHeader("Content-Type", "application/json");
2784
+ Object.entries(additionalHeaders || {}).forEach(function (_a) {
2785
+ var key = _a[0], val = _a[1];
2786
+ return req.setRequestHeader(key, val);
2787
+ });
2788
+ req.send(jsonPayload);
2789
+ getLogger().debug("sending json", jsonPayload);
2790
+ });
2791
+ };
2792
+ var fetchTransport = function (fetch) {
2793
+ return function (url, jsonPayload, additionalHeaders, handler) {
2794
+ if (handler === void 0) { handler = function (code, body) { }; }
2795
+ return __awaiter(void 0, void 0, void 0, function () {
2796
+ var res, e_1, resJson;
2797
+ return __generator(this, function (_a) {
2798
+ switch (_a.label) {
2799
+ case 0:
2800
+ _a.trys.push([0, 2, , 3]);
2801
+ return [4 /*yield*/, fetch(url, {
2802
+ method: "POST",
2803
+ headers: __assign({ Accept: "application/json", "Content-Type": "application/json" }, (additionalHeaders || {})),
2804
+ body: jsonPayload,
2805
+ })];
2806
+ case 1:
2807
+ res = _a.sent();
2808
+ return [3 /*break*/, 3];
2809
+ case 2:
2810
+ e_1 = _a.sent();
2811
+ getLogger().error("Failed to send", jsonPayload, e_1);
2812
+ handler(-1, {});
2813
+ throw new Error("Failed to send JSON. See console logs");
2814
+ case 3:
2815
+ if (res.status !== 200) {
2816
+ getLogger().warn("Failed to send data to ".concat(url, " (#").concat(res.status, " - ").concat(res.statusText, ")"), jsonPayload);
2817
+ throw new Error("Failed to send JSON. Error code: ".concat(res.status, ". See logs for details"));
2818
+ }
2819
+ return [4 /*yield*/, res.json()];
2820
+ case 4:
2821
+ resJson = _a.sent();
2822
+ handler(res.status, resJson);
2823
+ return [2 /*return*/];
2824
+ }
2825
+ });
2826
+ });
2827
+ };
2828
+ };
2829
+ var UsermavenClientImpl = /** @class */ (function () {
2830
+ function UsermavenClientImpl() {
2831
+ this.userProperties = {};
2832
+ this.permanentProperties = {
2833
+ globalProps: {},
2834
+ propsPerEvent: {},
2835
+ };
2836
+ this.cookieDomain = "";
2837
+ this.trackingHost = "";
2838
+ this.idCookieName = "";
2839
+ this.randomizeUrl = false;
2840
+ this.apiKey = "";
2841
+ this.initialized = false;
1824
2842
  this._3pCookies = {};
1825
- this.cookiePolicy = 'keep';
1826
- this.ipPolicy = 'keep';
2843
+ this.cookiePolicy = "keep";
2844
+ this.ipPolicy = "keep";
1827
2845
  this.beaconApi = false;
1828
- }
2846
+ this.transport = xmlHttpTransport;
2847
+ this.customHeaders = function () { return ({}); };
2848
+ this.__autocapture_enabled = false;
2849
+ }
2850
+ // private anonymousId: string = '';
2851
+ // Used for session + autocapture
2852
+ UsermavenClientImpl.prototype.get_config = function (prop_name) {
2853
+ return this.config ? this.config[prop_name] : null;
2854
+ };
1829
2855
  UsermavenClientImpl.prototype.id = function (props, doNotSendEvent) {
1830
2856
  this.userProperties = __assign(__assign({}, this.userProperties), props);
1831
- getLogger().debug('Usermaven user identified', props);
2857
+ getLogger().debug("Usermaven user identified", props);
1832
2858
  if (this.userIdPersistence) {
1833
2859
  this.userIdPersistence.save(props);
1834
2860
  }
1835
2861
  else {
1836
- getLogger().warn('Id() is called before initialization');
2862
+ getLogger().warn("Id() is called before initialization");
1837
2863
  }
1838
2864
  if (!doNotSendEvent) {
1839
- return this.track('user_identify', {});
2865
+ return this.track("user_identify", {});
1840
2866
  }
1841
2867
  else {
1842
2868
  return Promise.resolve();
1843
2869
  }
1844
2870
  };
1845
2871
  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;
2872
+ return this.sendJson(payload);
1858
2873
  };
1859
2874
  UsermavenClientImpl.prototype.makeEvent = function (event_type, src, payload) {
1860
2875
  var _a;
2876
+ var env = payload.env, payloadData = __rest(payload, ["env"]);
2877
+ if (!env) {
2878
+ env = isWindowAvailable() ? envs.browser() : envs.empty();
2879
+ }
1861
2880
  this.restoreId();
1862
- var context = this.getCtx();
2881
+ var context = this.getCtx(env);
1863
2882
  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);
2883
+ var base = __assign({ api_key: this.apiKey, src: src, event_type: event_type }, payloadData);
2884
+ var sourceIp = env.getSourceIp();
2885
+ if (sourceIp) {
2886
+ base["source_ip"] = sourceIp;
2887
+ }
2888
+ return this.compatMode
2889
+ ? __assign(__assign(__assign({}, persistentProps), { eventn_ctx: context }), base) : __assign(__assign(__assign({}, persistentProps), context), base);
1866
2890
  };
1867
2891
  UsermavenClientImpl.prototype._send3p = function (sourceType, object, type) {
1868
- var eventType = '3rdparty';
1869
- if (type && type !== '') {
2892
+ var eventType = "3rdparty";
2893
+ if (type && type !== "") {
1870
2894
  eventType = type;
1871
2895
  }
1872
2896
  var e = this.makeEvent(eventType, sourceType, {
1873
- src_payload: object
2897
+ src_payload: object,
1874
2898
  });
1875
2899
  return this.sendJson(e);
1876
2900
  };
1877
2901
  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);
2902
+ var _this = this;
2903
+ var cookiePolicy = this.cookiePolicy !== "keep" ? "&cookie_policy=".concat(this.cookiePolicy) : "";
2904
+ var ipPolicy = this.ipPolicy !== "keep" ? "&ip_policy=".concat(this.ipPolicy) : "";
2905
+ var urlPrefix = isWindowAvailable() ? "/api/v1/event" : "/api/v1/s2s/event";
2906
+ var url = "".concat(this.trackingHost).concat(urlPrefix, "?token=").concat(this.apiKey).concat(cookiePolicy).concat(ipPolicy);
1881
2907
  if (this.randomizeUrl) {
1882
2908
  url = "".concat(this.trackingHost, "/api.").concat(generateRandom(), "?p_").concat(generateRandom(), "=").concat(this.apiKey).concat(cookiePolicy).concat(ipPolicy);
1883
2909
  }
1884
2910
  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);
2911
+ getLogger().debug("Sending payload to ".concat(url), jsonString);
2912
+ return this.transport(url, jsonString, this.customHeaders(), function (code, body) {
2913
+ return _this.postHandle(code, body);
1913
2914
  });
1914
2915
  };
1915
2916
  UsermavenClientImpl.prototype.postHandle = function (status, response) {
1916
- if (this.cookiePolicy === 'strict' || this.cookiePolicy === 'comply') {
2917
+ if (this.cookiePolicy === "strict" || this.cookiePolicy === "comply") {
1917
2918
  if (status === 200) {
1918
2919
  var data = response;
1919
- if (typeof response === 'string') {
2920
+ if (typeof response === "string") {
1920
2921
  data = JSON.parse(response);
1921
2922
  }
1922
- if (!data['delete_cookie']) {
2923
+ if (!data["delete_cookie"]) {
1923
2924
  return;
1924
2925
  }
1925
2926
  }
@@ -1927,15 +2928,45 @@ var UsermavenClientImpl = /** @class */ (function () {
1927
2928
  this.propsPersistance.delete();
1928
2929
  deleteCookie(this.idCookieName);
1929
2930
  }
2931
+ if (status === 200) {
2932
+ var data = response;
2933
+ if (typeof response === "string" && response.length > 0) {
2934
+ data = JSON.parse(response);
2935
+ var extras = data["jitsu_sdk_extras"];
2936
+ if (extras && extras.length > 0) {
2937
+ var isWindow = isWindowAvailable();
2938
+ if (!isWindow) {
2939
+ getLogger().error("Tags destination supported only in browser environment");
2940
+ }
2941
+ else {
2942
+ for (var _i = 0, extras_1 = extras; _i < extras_1.length; _i++) {
2943
+ var _a = extras_1[_i], type = _a.type, id = _a.id, value = _a.value;
2944
+ if (type === "tag") {
2945
+ var tag = document.createElement("div");
2946
+ tag.id = id;
2947
+ insertAndExecute(tag, value);
2948
+ if (tag.childElementCount > 0) {
2949
+ document.body.appendChild(tag);
2950
+ }
2951
+ }
2952
+ }
2953
+ }
2954
+ }
2955
+ }
2956
+ }
1930
2957
  };
1931
- UsermavenClientImpl.prototype.getCtx = function () {
2958
+ UsermavenClientImpl.prototype.getCtx = function (env) {
1932
2959
  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()));
2960
+ var props = env.describeClient() || {};
2961
+ var _a = this.sessionManager.getSessionAndWindowId(), session_id = _a.session_id, window_id = _a.window_id;
2962
+ var company = this.userProperties['company'] || {};
2963
+ delete this.userProperties['company'];
2964
+ var payload = __assign(__assign({ event_id: "", session_id: session_id, window_id: window_id, user: __assign({ anonymous_id: this.cookiePolicy !== "strict"
2965
+ ? env.getAnonymousId({
2966
+ name: this.idCookieName,
2967
+ domain: this.cookieDomain,
2968
+ })
2969
+ : "" }, this.userProperties), ids: this._getIds(), utc_time: reformatDate(now.toISOString()), local_tz_offset: now.getTimezoneOffset() }, props), getDataFromParams(parseQuery(props.doc_search)));
1939
2970
  // id and name attributes will be checked on backend
1940
2971
  if (Object.keys(company).length) {
1941
2972
  payload['company'] = company;
@@ -1943,74 +2974,104 @@ var UsermavenClientImpl = /** @class */ (function () {
1943
2974
  return payload;
1944
2975
  };
1945
2976
  UsermavenClientImpl.prototype._getIds = function () {
2977
+ if (!isWindowAvailable()) {
2978
+ return {};
2979
+ }
1946
2980
  var cookies = getCookies(false);
1947
2981
  var res = {};
1948
2982
  for (var _i = 0, _a = Object.entries(cookies); _i < _a.length; _i++) {
1949
2983
  var _b = _a[_i], key = _b[0], value = _b[1];
1950
2984
  if (this._3pCookies[key]) {
1951
- res[key.charAt(0) == '_' ?
1952
- key.substr(1) :
1953
- key] = value;
2985
+ res[key.charAt(0) == "_" ? key.substr(1) : key] = value;
1954
2986
  }
1955
2987
  }
1956
2988
  return res;
1957
2989
  };
1958
2990
  UsermavenClientImpl.prototype.track = function (type, payload) {
1959
2991
  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 || {});
2992
+ getLogger().debug("track event of type", type, data);
2993
+ var e = this.makeEvent(type, this.compatMode ? "eventn" : "usermaven", payload || {});
1964
2994
  return this.sendJson(e);
1965
2995
  };
1966
2996
  UsermavenClientImpl.prototype.init = function (options) {
1967
2997
  var _this = this;
1968
2998
  var _a, _b;
2999
+ if (isWindowAvailable() && !options.force_use_fetch) {
3000
+ if (options.fetch) {
3001
+ getLogger().warn("Custom fetch implementation is provided to Usermaven. However, it will be ignored since Usermaven runs in browser");
3002
+ }
3003
+ this.transport = this.beaconApi ? beaconTransport : xmlHttpTransport;
3004
+ }
3005
+ else {
3006
+ if (!options.fetch && !globalThis.fetch) {
3007
+ throw new Error("Usermaven runs in Node environment. However, neither UsermavenOptions.fetch is provided, nor global fetch function is defined. \n" +
3008
+ "Please, provide custom fetch implementation. You can get it via node-fetch package");
3009
+ }
3010
+ this.transport = fetchTransport(options.fetch || globalThis.fetch);
3011
+ }
3012
+ if (options.custom_headers &&
3013
+ typeof options.custom_headers === "function") {
3014
+ this.customHeaders = options.custom_headers;
3015
+ }
3016
+ else if (options.custom_headers) {
3017
+ this.customHeaders = function () {
3018
+ return options.custom_headers;
3019
+ };
3020
+ }
3021
+ if (options.tracking_host === "echo") {
3022
+ getLogger().warn('jitsuClient is configured with "echo" transport. Outgoing requests will be written to console');
3023
+ this.transport = echoTransport;
3024
+ }
1969
3025
  if (options.ip_policy) {
1970
3026
  this.ipPolicy = options.ip_policy;
1971
3027
  }
1972
3028
  if (options.cookie_policy) {
1973
3029
  this.cookiePolicy = options.cookie_policy;
1974
3030
  }
1975
- if (options.privacy_policy === 'strict') {
1976
- this.ipPolicy = 'strict';
1977
- this.cookiePolicy = 'strict';
3031
+ if (options.privacy_policy === "strict") {
3032
+ this.ipPolicy = "strict";
3033
+ this.cookiePolicy = "strict";
1978
3034
  }
1979
3035
  if (options.use_beacon_api && navigator.sendBeacon) {
1980
3036
  this.beaconApi = true;
1981
3037
  }
1982
3038
  //can't handle delete cookie response when beacon api
1983
- if (this.cookiePolicy === 'comply' && this.beaconApi) {
1984
- this.cookiePolicy = 'strict';
3039
+ if (this.cookiePolicy === "comply" && this.beaconApi) {
3040
+ this.cookiePolicy = "strict";
1985
3041
  }
1986
3042
  if (options.log_level) {
1987
3043
  setRootLogLevel(options.log_level);
1988
3044
  }
1989
3045
  this.initialOptions = options;
1990
- getLogger().debug('Initializing Usermaven Tracker tracker', options, USERMAVEN_VERSION);
3046
+ getLogger().debug("Initializing Usemaven Tracker tracker", options, USERMAVEN_VERSION);
1991
3047
  if (!options.key) {
1992
- getLogger().error('Can\'t initialize Usermaven, key property is not set');
3048
+ getLogger().error("Can't initialize Usemaven, key property is not set");
1993
3049
  return;
1994
3050
  }
1995
- this.compatMode = options.compat_mode === undefined ?
1996
- defaultCompatMode :
1997
- !!options.compat_mode;
3051
+ this.compatMode =
3052
+ options.compat_mode === undefined
3053
+ ? defaultCompatMode
3054
+ : !!options.compat_mode;
1998
3055
  this.cookieDomain = options.cookie_domain || getCookieDomain();
1999
- this.trackingHost = getHostWithProtocol(options['tracking_host'] || 't.usermaven.com');
3056
+ this.trackingHost = getHostWithProtocol(options["tracking_host"] || "t.usermaven.com");
2000
3057
  this.randomizeUrl = options.randomize_url || false;
2001
- this.idCookieName = options.cookie_name || '__eventn_id';
3058
+ this.idCookieName = options.cookie_name || "__eventn_id";
2002
3059
  this.apiKey = options.key;
2003
- if (this.cookiePolicy === 'strict') {
3060
+ if (this.cookiePolicy === "strict") {
2004
3061
  this.propsPersistance = new NoPersistence();
2005
3062
  }
2006
3063
  else {
2007
- this.propsPersistance = new CookiePersistence(this.cookieDomain, this.idCookieName + '_props');
3064
+ this.propsPersistance = isWindowAvailable()
3065
+ ? new CookiePersistence(this.cookieDomain, this.idCookieName + "_props")
3066
+ : new NoPersistence();
2008
3067
  }
2009
- if (this.cookiePolicy === 'strict') {
3068
+ if (this.cookiePolicy === "strict") {
2010
3069
  this.userIdPersistence = new NoPersistence();
2011
3070
  }
2012
3071
  else {
2013
- this.userIdPersistence = new CookiePersistence(this.cookieDomain, this.idCookieName + '_usr');
3072
+ this.userIdPersistence = isWindowAvailable()
3073
+ ? new CookiePersistence(this.cookieDomain, this.idCookieName + "_usr")
3074
+ : new NoPersistence();
2014
3075
  }
2015
3076
  if (this.propsPersistance) {
2016
3077
  var restored = this.propsPersistance.restore();
@@ -2019,26 +3080,45 @@ var UsermavenClientImpl = /** @class */ (function () {
2019
3080
  this.permanentProperties.globalProps = (_a = restored.globalProps) !== null && _a !== void 0 ? _a : {};
2020
3081
  this.permanentProperties.propsPerEvent = (_b = restored.propsPerEvent) !== null && _b !== void 0 ? _b : {};
2021
3082
  }
2022
- getLogger().debug('Restored persistent properties', this.permanentProperties);
3083
+ getLogger().debug("Restored persistent properties", this.permanentProperties);
2023
3084
  }
2024
- this.manageSession(options);
3085
+ // Added these configuration for session management + autocapture
3086
+ var defaultConfig = {
3087
+ persistence: 'cookie',
3088
+ persistence_name: 'session',
3089
+ autocapture: false,
3090
+ capture_pageview: true,
3091
+ store_google: false,
3092
+ save_referrer: false,
3093
+ properties_string_max_length: null,
3094
+ property_blacklist: [],
3095
+ sanitize_properties: null
3096
+ };
3097
+ this.config = _.extend({}, defaultConfig, options || {}, this.config || {}, { token: this.apiKey });
3098
+ getLogger().debug('Default Configuration', this.config);
3099
+ this.manageSession(this.config);
3100
+ this.manageAutoCapture(this.config);
2025
3101
  if (options.capture_3rd_party_cookies === false) {
2026
3102
  this._3pCookies = {};
2027
3103
  }
2028
3104
  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; });
3105
+ (options.capture_3rd_party_cookies || [
3106
+ "_ga",
3107
+ "_fbp",
3108
+ "_ym_uid",
3109
+ "ajs_user_id",
3110
+ "ajs_anonymous_id",
3111
+ ]).forEach(function (name) { return (_this._3pCookies[name] = true); });
2031
3112
  }
2032
3113
  if (options.ga_hook) {
2033
- getLogger().warn('GA event interceptor isn\'t supported anymore');
3114
+ getLogger().warn("GA event interceptor isn't supported anymore");
2034
3115
  }
2035
3116
  if (options.segment_hook) {
2036
3117
  interceptSegmentCalls(this);
2037
3118
  }
2038
- if (this.cookiePolicy !== 'strict') {
2039
- this.anonymousId = this.getAnonymousId();
2040
- }
2041
3119
  this.initialized = true;
3120
+ // Set up the window close event handler "unload"
3121
+ window.addEventListener && window.addEventListener('unload', this._handle_unload.bind(this));
2042
3122
  };
2043
3123
  UsermavenClientImpl.prototype.interceptAnalytics = function (analytics) {
2044
3124
  var _this = this;
@@ -2046,11 +3126,13 @@ var UsermavenClientImpl = /** @class */ (function () {
2046
3126
  var _a;
2047
3127
  try {
2048
3128
  var payload = __assign({}, chain.payload);
2049
- getLogger().debug('Intercepted segment payload', payload.obj);
2050
- var integration = chain.integrations['Segment.io'];
3129
+ getLogger().debug("Intercepted segment payload", payload.obj);
3130
+ var integration = chain.integrations["Segment.io"];
2051
3131
  if (integration && integration.analytics) {
2052
3132
  var analyticsOriginal = integration.analytics;
2053
- if (typeof analyticsOriginal.user === 'function' && analyticsOriginal.user() && typeof analyticsOriginal.user().id === 'function') {
3133
+ if (typeof analyticsOriginal.user === "function" &&
3134
+ analyticsOriginal.user() &&
3135
+ typeof analyticsOriginal.user().id === "function") {
2054
3136
  payload.obj.userId = analyticsOriginal.user().id();
2055
3137
  }
2056
3138
  }
@@ -2058,26 +3140,26 @@ var UsermavenClientImpl = /** @class */ (function () {
2058
3140
  payload.obj.sentAt = payload.obj.timestamp;
2059
3141
  }
2060
3142
  var type = chain.payload.type();
2061
- if (type === 'track') {
3143
+ if (type === "track") {
2062
3144
  type = chain.payload.event();
2063
3145
  }
2064
- _this._send3p('ajs', payload, type);
3146
+ _this._send3p("ajs", payload, type);
2065
3147
  }
2066
3148
  catch (e) {
2067
- getLogger().warn('Failed to send an event', e);
3149
+ getLogger().warn("Failed to send an event", e);
2068
3150
  }
2069
3151
  chain.next(chain.payload);
2070
3152
  };
2071
- if (typeof analytics.addSourceMiddleware === 'function') {
3153
+ if (typeof analytics.addSourceMiddleware === "function") {
2072
3154
  //analytics is fully initialized
2073
- getLogger().debug('Analytics.js is initialized, calling addSourceMiddleware');
3155
+ getLogger().debug("Analytics.js is initialized, calling addSourceMiddleware");
2074
3156
  analytics.addSourceMiddleware(interceptor);
2075
3157
  }
2076
3158
  else {
2077
- getLogger().debug('Analytics.js is not initialized, pushing addSourceMiddleware to callstack');
2078
- analytics.push(['addSourceMiddleware', interceptor]);
3159
+ getLogger().debug("Analytics.js is not initialized, pushing addSourceMiddleware to callstack");
3160
+ analytics.push(["addSourceMiddleware", interceptor]);
2079
3161
  }
2080
- analytics['__en_intercepted'] = true;
3162
+ analytics["__en_intercepted"] = true;
2081
3163
  };
2082
3164
  UsermavenClientImpl.prototype.restoreId = function () {
2083
3165
  if (this.userIdPersistence) {
@@ -2103,6 +3185,7 @@ var UsermavenClientImpl = /** @class */ (function () {
2103
3185
  }
2104
3186
  };
2105
3187
  UsermavenClientImpl.prototype.unset = function (propertyName, opts) {
3188
+ requireWindow();
2106
3189
  var eventType = opts === null || opts === void 0 ? void 0 : opts.eventType;
2107
3190
  var persist = (opts === null || opts === void 0 ? void 0 : opts.persist) === undefined || (opts === null || opts === void 0 ? void 0 : opts.persist);
2108
3191
  if (!eventType) {
@@ -2114,15 +3197,13 @@ var UsermavenClientImpl = /** @class */ (function () {
2114
3197
  if (this.propsPersistance && persist) {
2115
3198
  this.propsPersistance.save(this.permanentProperties);
2116
3199
  }
2117
- if (this.sessionManager) {
2118
- this.sessionManager.resetSessionId();
2119
- }
2120
3200
  };
2121
3201
  /**
2122
3202
  * Manage session capability
2123
3203
  * @param options
2124
3204
  */
2125
3205
  UsermavenClientImpl.prototype.manageSession = function (options) {
3206
+ getLogger().debug('Options', options);
2126
3207
  options = options || {};
2127
3208
  getLogger().debug('Options', options);
2128
3209
  // cross_subdomain_cookie: whether to keep cookie across domains and subdomains
@@ -2141,6 +3222,139 @@ var UsermavenClientImpl = /** @class */ (function () {
2141
3222
  this.sessionManager = new SessionIdManager(this.config, this.persistence);
2142
3223
  getLogger().debug('Session Configuration', this.sessionManager);
2143
3224
  };
3225
+ /**
3226
+ * Manage auto-capturing
3227
+ * @param options
3228
+ */
3229
+ UsermavenClientImpl.prototype.manageAutoCapture = function (options) {
3230
+ getLogger().debug("Auto Capture Status: ", this.config['autocapture']);
3231
+ this.__autocapture_enabled = this.config['autocapture'];
3232
+ if (!this.__autocapture_enabled) {
3233
+ return;
3234
+ }
3235
+ var num_buckets = 100;
3236
+ var num_enabled_buckets = 100;
3237
+ if (!autocapture.enabledForProject(this.apiKey, num_buckets, num_enabled_buckets)) {
3238
+ this.config['autocapture'] = false;
3239
+ console.log('Not in active bucket: disabling Automatic Event Collection.');
3240
+ }
3241
+ else if (!autocapture.isBrowserSupported()) {
3242
+ this.config['autocapture'] = false;
3243
+ console.log('Disabling Automatic Event Collection because this browser is not supported');
3244
+ }
3245
+ else {
3246
+ autocapture.init(this);
3247
+ }
3248
+ };
3249
+ /**
3250
+ * Capture an event. This is the most important and
3251
+ * frequently used usermaven function.
3252
+ *
3253
+ * ### Usage:
3254
+ *
3255
+ * // capture an event named 'Registered'
3256
+ * usermaven.capture('Registered', {'Gender': 'Male', 'Age': 21});
3257
+ *
3258
+ * // capture an event using navigator.sendBeacon
3259
+ * usermaven.capture('Left page', {'duration_seconds': 35}, {transport: 'sendBeacon'});
3260
+ *
3261
+ * @param {String} event_name The name of the event. This can be anything the user does - 'Button Click', 'Sign Up', 'Item Purchased', etc.
3262
+ * @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.
3263
+ * @param {Object} [options] Optional configuration for this capture request.
3264
+ * @param {String} [options.transport] Transport method for network request ('XHR' or 'sendBeacon').
3265
+ */
3266
+ UsermavenClientImpl.prototype.capture = function (event_name, properties) {
3267
+ var _a, _b;
3268
+ if (properties === void 0) { properties = {}; }
3269
+ if (!this.initialized) {
3270
+ console.error('Trying to capture event before initialization');
3271
+ return;
3272
+ }
3273
+ if (_.isUndefined(event_name) || typeof event_name !== 'string') {
3274
+ console.error('No event name provided to posthog.capture');
3275
+ return;
3276
+ }
3277
+ if (_.isBlockedUA(userAgent)) {
3278
+ return;
3279
+ }
3280
+ var start_timestamp = this['persistence'].remove_event_timer(event_name);
3281
+ // update persistence
3282
+ this['persistence'].update_search_keyword(document.referrer);
3283
+ if (this.get_config('store_google')) {
3284
+ this['persistence'].update_campaign_params();
3285
+ }
3286
+ if (this.get_config('save_referrer')) {
3287
+ this['persistence'].update_referrer_info(document.referrer);
3288
+ }
3289
+ var data = {
3290
+ event: event_name + (properties['$event_type'] ? '_' + properties['$event_type'] : ''),
3291
+ properties: this._calculate_event_properties(event_name, properties, start_timestamp),
3292
+ };
3293
+ data = _.copyAndTruncateStrings(data, this.get_config('properties_string_max_length'));
3294
+ // send evnet if there is a tagname available
3295
+ if ((_b = (_a = data.properties) === null || _a === void 0 ? void 0 : _a.autocapture_attributes) === null || _b === void 0 ? void 0 : _b.tag_name) {
3296
+ this.track("$autocapture", data.properties);
3297
+ // this.track(data.event, data.properties)
3298
+ }
3299
+ };
3300
+ UsermavenClientImpl.prototype._calculate_event_properties = function (event_name, event_properties, start_timestamp) {
3301
+ var _a, _b;
3302
+ // set defaults
3303
+ var properties = event_properties || {};
3304
+ if (event_name === '$snapshot') {
3305
+ return properties;
3306
+ }
3307
+ // set $duration if time_event was previously called for this event
3308
+ if (!_.isUndefined(start_timestamp)) {
3309
+ var duration_in_ms = new Date().getTime() - start_timestamp;
3310
+ properties['$duration'] = parseFloat((duration_in_ms / 1000).toFixed(3));
3311
+ }
3312
+ // note: extend writes to the first object, so lets make sure we
3313
+ // don't write to the persistence properties object and info
3314
+ // properties object by passing in a new object
3315
+ // update properties with pageview info and super-properties
3316
+ // exlude , _.info.properties()
3317
+ properties = _.extend({}, this['persistence'].properties(), properties);
3318
+ var property_blacklist = this.get_config('property_blacklist');
3319
+ if (_.isArray(property_blacklist)) {
3320
+ _.each(property_blacklist, function (blacklisted_prop) {
3321
+ delete properties[blacklisted_prop];
3322
+ });
3323
+ }
3324
+ else {
3325
+ console.error('Invalid value for property_blacklist config: ' + property_blacklist);
3326
+ }
3327
+ var sanitize_properties = this.get_config('sanitize_properties');
3328
+ if (sanitize_properties) {
3329
+ properties = sanitize_properties(properties, event_name);
3330
+ }
3331
+ // assign first element from $elements only
3332
+ var attributes = {};
3333
+ var elements = properties['$elements'] || [];
3334
+ if (elements.length) {
3335
+ attributes = elements[0];
3336
+ }
3337
+ properties['autocapture_attributes'] = attributes;
3338
+ properties['autocapture_attributes']["el_text"] = (_a = properties['autocapture_attributes']["$el_text"]) !== null && _a !== void 0 ? _a : "";
3339
+ properties['autocapture_attributes']["event_type"] = (_b = properties["$event_type"]) !== null && _b !== void 0 ? _b : "";
3340
+ delete properties['$ce_version'];
3341
+ delete properties['$event_type'];
3342
+ delete properties['$initial_referrer'];
3343
+ delete properties['$initial_referring_domain'];
3344
+ delete properties['$referrer'];
3345
+ delete properties['$referring_domain'];
3346
+ delete properties['$elements'];
3347
+ // TODO: later remove this from the autotrack code.
3348
+ delete properties['autocapture_attributes']["$el_text"];
3349
+ delete properties['autocapture_attributes']["nth_child"];
3350
+ delete properties['autocapture_attributes']["nth_of_type"];
3351
+ return properties;
3352
+ };
3353
+ UsermavenClientImpl.prototype._handle_unload = function () {
3354
+ if (this.get_config('capture_pageview')) {
3355
+ this.capture('$pageleave');
3356
+ }
3357
+ };
2144
3358
  return UsermavenClientImpl;
2145
3359
  }());
2146
3360
  function interceptSegmentCalls(t) {
@@ -2151,4 +3365,7 @@ function interceptSegmentCalls(t) {
2151
3365
  t.interceptAnalytics(win.analytics);
2152
3366
  }
2153
3367
 
3368
+ exports.envs = envs;
3369
+ exports.fetchApi = fetchApi;
3370
+ exports.httpApi = httpApi;
2154
3371
  exports.usermavenClient = usermavenClient;