@jitsu/js 1.9.3 → 1.9.4

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.
@@ -0,0 +1,31 @@
1
+ <!DOCTYPE html>
2
+
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="utf-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
7
+
8
+ <title>Tracking page</title>
9
+ <script>
10
+ window.testOnload = async j => {
11
+ await j.setAnonymousId("john-doe-id-1");
12
+ await j.identify("john-nondoe", { email: "john@example.com" });
13
+ await j.track("pageLoaded", { trackParam: "trackValue" });
14
+ await j.reset();
15
+ await j.track("pageLoaded", { trackParam: "trackValue" });
16
+ };
17
+ </script>
18
+ <script
19
+ type="text/javascript"
20
+ src="<%=trackingBase%>/p.js"
21
+ data-onload="testOnload"
22
+ data-debug="true"
23
+ data-init-only="true"
24
+ defer
25
+ ></script>
26
+ </head>
27
+
28
+ <body>
29
+ <h1>Test</h1>
30
+ </body>
31
+ </html>
@@ -244,6 +244,41 @@ test("url-bug", async ({ browser }) => {
244
244
  expect(pagePath).toEqual("/");
245
245
  });
246
246
 
247
+ test("reset", async ({ browser }) => {
248
+ clearRequestLog();
249
+ const browserContext = await browser.newContext();
250
+ const { page, uncaughtErrors } = await createLoggingPage(browserContext);
251
+ const [pageResult] = await Promise.all([page.goto(`${server.baseUrl}/reset.html`)]);
252
+ await page.waitForFunction(() => window["jitsu"] !== undefined, undefined, {
253
+ timeout: 1000,
254
+ polling: 100,
255
+ });
256
+ expect(pageResult.status()).toBe(200);
257
+ //wait for some time since the server has an artificial latency of 30ms
258
+ await new Promise(resolve => setTimeout(resolve, 1000));
259
+ expect(uncaughtErrors.length).toEqual(0);
260
+ expect(requestLog.length).toBe(3);
261
+ console.log(
262
+ `📝 Request log size of ${requestLog.length}`,
263
+ requestLog.map(x => describeEvent(x.type, x.body))
264
+ );
265
+ const [identifyEvent, firstTrack, secondTrack] = requestLog;
266
+ expect(firstTrack.body.anonymousId).toEqual("john-doe-id-1");
267
+
268
+ const cookies = await browserContext.cookies();
269
+ // all cookies should be cleared by .reset()
270
+ // but new cookie for new anonymousId should be set
271
+ expect(cookies.length).toBe(1);
272
+ expect(cookies[0].name).toEqual("__eventn_id");
273
+ const newAnonymousId = cookies[0].value;
274
+ console.log(`🍪Cookies`, cookies);
275
+
276
+ expect(secondTrack.body.anonymousId).not.toBeNull();
277
+ expect(secondTrack.body.anonymousId).toBeDefined();
278
+ expect(secondTrack.body.anonymousId).toEqual(newAnonymousId);
279
+ expect(secondTrack.body.anonymousId).not.toEqual("john-doe-id-1");
280
+ });
281
+
247
282
  test("basic", async ({ browser }) => {
248
283
  clearRequestLog();
249
284
  const browserContext = await browser.newContext();
@@ -24,9 +24,7 @@ export type InternalPluginDescriptor = {
24
24
  };
25
25
  export type DeviceOptions = AnalyticsPluginDescriptor | InternalPluginDescriptor;
26
26
  export type JitsuPluginConfig = JitsuOptions & {
27
- storageWrapper?: (persistentStorage: PersistentStorage) => PersistentStorage & {
28
- reset: () => void;
29
- };
27
+ storageWrapper?: (persistentStorage: PersistentStorage) => PersistentStorage;
30
28
  };
31
29
  declare const jitsuAnalyticsPlugin: (pluginConfig?: JitsuPluginConfig) => AnalyticsPlugin;
32
30
  export declare function randomId(hashString?: string | undefined): string;
package/dist/jitsu.cjs.js CHANGED
@@ -71,7 +71,23 @@ function findScript(src) {
71
71
  const scripts = Array.prototype.slice.call(window.document.querySelectorAll("script"));
72
72
  return scripts.find(s => s.src === src);
73
73
  }
74
- function loadScript(src, attributes) {
74
+ function buildScriptSrc(src, options) {
75
+ let result = src;
76
+ if (!result.startsWith("http")) {
77
+ result = `https://${(options === null || options === void 0 ? void 0 : options.www) ? "www." : ""}${result}`;
78
+ }
79
+ if (options === null || options === void 0 ? void 0 : options.min) {
80
+ result = result + ".min.js";
81
+ }
82
+ else if (options === null || options === void 0 ? void 0 : options.js) {
83
+ result = result + ".js";
84
+ }
85
+ if (options === null || options === void 0 ? void 0 : options.query) {
86
+ result += "?" + options.query;
87
+ }
88
+ return result;
89
+ }
90
+ function loadScript(src, options) {
75
91
  const found = findScript(src);
76
92
  if (found !== undefined) {
77
93
  const status = found === null || found === void 0 ? void 0 : found.getAttribute("status");
@@ -86,13 +102,13 @@ function loadScript(src, attributes) {
86
102
  }
87
103
  }
88
104
  return new Promise((resolve, reject) => {
89
- var _a;
105
+ var _a, _b;
90
106
  const script = window.document.createElement("script");
91
107
  script.type = "text/javascript";
92
- script.src = src;
108
+ script.src = buildScriptSrc(src, options);
93
109
  script.async = true;
94
110
  script.setAttribute("status", "loading");
95
- for (const [k, v] of Object.entries(attributes !== null && attributes !== void 0 ? attributes : {})) {
111
+ for (const [k, v] of Object.entries((_a = options === null || options === void 0 ? void 0 : options.attributes) !== null && _a !== void 0 ? _a : {})) {
96
112
  script.setAttribute(k, v);
97
113
  }
98
114
  script.onload = () => {
@@ -106,7 +122,7 @@ function loadScript(src, attributes) {
106
122
  reject(new Error(`Failed to load ${src}`));
107
123
  };
108
124
  const tag = window.document.getElementsByTagName("script")[0];
109
- (_a = tag.parentElement) === null || _a === void 0 ? void 0 : _a.insertBefore(script, tag);
125
+ (_b = tag.parentElement) === null || _b === void 0 ? void 0 : _b.insertBefore(script, tag);
110
126
  });
111
127
  }
112
128
 
@@ -206,6 +222,7 @@ var __awaiter$4 = (undefined && undefined.__awaiter) || function (thisArg, _argu
206
222
  step((generator = generator.apply(thisArg, _arguments || [])).next());
207
223
  });
208
224
  };
225
+ const cdn = "cdn.lr-ingest.io/";
209
226
  const logrocketPlugin = {
210
227
  id: "logrocket",
211
228
  handle(config, payload) {
@@ -256,7 +273,7 @@ function initLogrocketIfNeeded(appId) {
256
273
  return;
257
274
  }
258
275
  setLogRocketState("loading");
259
- loadScript(`https://cdn.lr-ingest.io/LogRocket.min.js`, { crossOrigin: "anonymous" })
276
+ loadScript(`${cdn}LogRocket`, { min: true, attributes: { crossOrigin: "anonymous" } })
260
277
  .then(() => {
261
278
  if (window["LogRocket"]) {
262
279
  try {
@@ -379,8 +396,8 @@ function initGtmIfNeeded(config, payload) {
379
396
  event: "gtm.js",
380
397
  });
381
398
  const dl = l != "dataLayer" ? "&l=" + l : "";
382
- const scriptSrc = "https://www.googletagmanager.com/gtm.js?id=" + i + dl;
383
- loadScript(scriptSrc)
399
+ const scriptSrc = "googletagmanager.com/gtm";
400
+ loadScript(scriptSrc, { www: true, js: true, query: "id=" + i + dl })
384
401
  .then(() => {
385
402
  setGtmState("loaded");
386
403
  })
@@ -401,7 +418,7 @@ var __awaiter$2 = (undefined && undefined.__awaiter) || function (thisArg, _argu
401
418
  step((generator = generator.apply(thisArg, _arguments || [])).next());
402
419
  });
403
420
  };
404
- const defaultScriptSrc = "https://www.googletagmanager.com/gtag/js";
421
+ const defaultScriptSrc = "googletagmanager.com/gtag/js";
405
422
  const ga4Plugin = {
406
423
  id: "ga4-tag",
407
424
  handle(config, payload) {
@@ -463,7 +480,6 @@ function initGa4IfNeeded(config, payload) {
463
480
  const dlParam = dlName !== "dataLayer" ? "&l=" + dlName : "";
464
481
  // to work with both GA4 and GTM
465
482
  const tagId = config.measurementIds;
466
- const scriptSrc = `${defaultScriptSrc}?id=${tagId}${dlParam}`;
467
483
  window[dlName] = window[dlName] || [];
468
484
  const gtag = function () {
469
485
  window[dlName].push(arguments);
@@ -473,7 +489,7 @@ function initGa4IfNeeded(config, payload) {
473
489
  gtag(
474
490
  // @ts-ignore
475
491
  "config", tagId, Object.assign(Object.assign({}, (payload.userId ? { user_id: payload.userId } : {})), (!config.autoPageView ? { send_page_view: false } : {})));
476
- loadScript(scriptSrc)
492
+ loadScript(defaultScriptSrc, { query: `id=${tagId}${dlParam}`, www: true })
477
493
  .then(() => {
478
494
  setGa4State("loaded");
479
495
  })
@@ -1112,8 +1128,15 @@ function getGa4Ids(runtime) {
1112
1128
  return undefined;
1113
1129
  }
1114
1130
  }
1115
- function removeCookie(name) {
1116
- document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:01 GMT;";
1131
+ function removeCookie(name, { domain, secure }) {
1132
+ document.cookie =
1133
+ name +
1134
+ "=;domain=" +
1135
+ domain +
1136
+ ";path=/" +
1137
+ ";expires=Thu, 01 Jan 1970 00:00:01 GMT;SameSite=" +
1138
+ (secure ? "None" : "Lax") +
1139
+ (secure ? ";secure" : "");
1117
1140
  }
1118
1141
  function setCookie(name, val, { domain, secure }) {
1119
1142
  document.cookie =
@@ -1155,7 +1178,18 @@ const cookieStorage = (cookieDomain, key2cookie) => {
1155
1178
  return parse(result);
1156
1179
  },
1157
1180
  removeItem(key) {
1158
- removeCookie(key2cookie[key] || key);
1181
+ removeCookie(key2cookie[key] || key, {
1182
+ domain: cookieDomain,
1183
+ secure: window.location.protocol === "https:",
1184
+ });
1185
+ },
1186
+ reset() {
1187
+ for (const v of Object.values(key2cookie)) {
1188
+ removeCookie(v, {
1189
+ domain: cookieDomain,
1190
+ secure: window.location.protocol === "https:",
1191
+ });
1192
+ }
1159
1193
  },
1160
1194
  };
1161
1195
  };
@@ -1226,6 +1260,9 @@ const emptyRuntime = (config) => ({
1226
1260
  store() {
1227
1261
  const storage = {};
1228
1262
  return {
1263
+ reset() {
1264
+ Object.keys(storage).forEach(key => delete storage[key]);
1265
+ },
1229
1266
  setItem(key, val) {
1230
1267
  if (config.debug) {
1231
1268
  console.log(`[JITSU EMPTY RUNTIME] Set storage item ${key}=${JSON.stringify(val)}`);
@@ -1497,10 +1534,13 @@ function send(method, payload, jitsuConfig, instance, store) {
1497
1534
  console.warn(`[JITSU] ${payload.type} responded with list of ${responseJson.destinations.length} destinations. However, this code is running in server-to-server mode, so destinations will be ignored`, jitsuConfig.debug ? JSON.stringify(responseJson.destinations, null, 2) : undefined);
1498
1535
  }
1499
1536
  else {
1500
- if (jitsuConfig.debug) {
1501
- console.log(`[JITSU] Processing device destinations: `, JSON.stringify(responseJson.destinations, null, 2));
1537
+ //double protection, ingest should not return destinations in s2s mode
1538
+ if (isInBrowser()) {
1539
+ if (jitsuConfig.debug) {
1540
+ console.log(`[JITSU] Processing device destinations: `, JSON.stringify(responseJson.destinations, null, 2));
1541
+ }
1542
+ return processDestinations(responseJson.destinations, method, adjustedPayload, !!jitsuConfig.debug, instance);
1502
1543
  }
1503
- return processDestinations(responseJson.destinations, method, adjustedPayload, !!jitsuConfig.debug, instance);
1504
1544
  }
1505
1545
  }
1506
1546
  return adjustedPayload;
@@ -1540,9 +1580,11 @@ const jitsuAnalyticsPlugin = (pluginConfig = {}) => {
1540
1580
  return send("identify", payload, config, instance, storage);
1541
1581
  },
1542
1582
  reset: args => {
1543
- //clear storage cache
1544
- if (pluginConfig.storageWrapper) {
1545
- pluginConfig.storageWrapper(args.instance.storage).reset();
1583
+ const { config, instance } = args;
1584
+ const storage = pluginConfig.storageWrapper ? pluginConfig.storageWrapper(instance.storage) : instance.storage;
1585
+ storage === null || storage === void 0 ? void 0 : storage.reset();
1586
+ if (config.debug) {
1587
+ console.log("[JITSU DEBUG] Resetting Jitsu plugin storage");
1546
1588
  }
1547
1589
  },
1548
1590
  methods: {
@@ -1654,9 +1696,9 @@ function createUnderlyingAnalyticsInstance(opts, rt, plugins = []) {
1654
1696
  },
1655
1697
  reset() {
1656
1698
  for (const key of [...Object.keys(storageCache)]) {
1657
- storage.removeItem(key);
1658
1699
  delete storageCache[key];
1659
1700
  }
1701
+ storage.reset();
1660
1702
  },
1661
1703
  removeItem(key) {
1662
1704
  if (opts.debug) {
@@ -1713,7 +1755,20 @@ function createUnderlyingAnalyticsInstance(opts, rt, plugins = []) {
1713
1755
  userState.anonymousId = id;
1714
1756
  }
1715
1757
  analytics.setAnonymousId(id);
1716
- }, group(groupId, traits, options, callback) {
1758
+ }, reset() {
1759
+ return __awaiter(this, void 0, void 0, function* () {
1760
+ if (opts.debug) {
1761
+ console.log("[JITSU DEBUG] Called reset(). Storage state", JSON.stringify(analytics.user()));
1762
+ }
1763
+ storage.reset();
1764
+ yield analytics.reset();
1765
+ this.setAnonymousId(uuid());
1766
+ if (opts.debug) {
1767
+ console.log("[JITSU DEBUG] User state after reset", JSON.stringify(analytics.user()));
1768
+ }
1769
+ });
1770
+ },
1771
+ group(groupId, traits, options, callback) {
1717
1772
  return __awaiter(this, void 0, void 0, function* () {
1718
1773
  const results = [];
1719
1774
  for (const plugin of Object.values(analytics.plugins)) {
@@ -1762,6 +1817,15 @@ function jitsuAnalytics(_opts) {
1762
1817
  // result.loaded(createUnderlyingAnalyticsInstance(opts, rt));
1763
1818
  // }
1764
1819
  }
1820
+ function uuid() {
1821
+ var u = "", m = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx", i = 0, rb = (Math.random() * 0xffffffff) | 0;
1822
+ while (i++ < 36) {
1823
+ var c = m[i - 1], r = rb & 0xf, v = c == "x" ? r : (r & 0x3) | 0x8;
1824
+ u += c == "-" || c == "4" ? c : v.toString(16);
1825
+ rb = i % 8 == 0 ? (Math.random() * 0xffffffff) | 0 : rb >> 4;
1826
+ }
1827
+ return u;
1828
+ }
1765
1829
 
1766
1830
  exports.emptyAnalytics = emptyAnalytics;
1767
1831
  exports.emptyRuntime = emptyRuntime;
package/dist/jitsu.d.ts CHANGED
@@ -52,6 +52,7 @@ type PersistentStorage = {
52
52
  getItem: (key: string, options?: any) => any;
53
53
  setItem: (key: string, value: any, options?: any) => void;
54
54
  removeItem: (key: string, options?: any) => void;
55
+ reset: () => void;
55
56
  };
56
57
  type RuntimeFacade = {
57
58
  store(): PersistentStorage;
package/dist/jitsu.es.js CHANGED
@@ -69,7 +69,23 @@ function findScript(src) {
69
69
  const scripts = Array.prototype.slice.call(window.document.querySelectorAll("script"));
70
70
  return scripts.find(s => s.src === src);
71
71
  }
72
- function loadScript(src, attributes) {
72
+ function buildScriptSrc(src, options) {
73
+ let result = src;
74
+ if (!result.startsWith("http")) {
75
+ result = `https://${(options === null || options === void 0 ? void 0 : options.www) ? "www." : ""}${result}`;
76
+ }
77
+ if (options === null || options === void 0 ? void 0 : options.min) {
78
+ result = result + ".min.js";
79
+ }
80
+ else if (options === null || options === void 0 ? void 0 : options.js) {
81
+ result = result + ".js";
82
+ }
83
+ if (options === null || options === void 0 ? void 0 : options.query) {
84
+ result += "?" + options.query;
85
+ }
86
+ return result;
87
+ }
88
+ function loadScript(src, options) {
73
89
  const found = findScript(src);
74
90
  if (found !== undefined) {
75
91
  const status = found === null || found === void 0 ? void 0 : found.getAttribute("status");
@@ -84,13 +100,13 @@ function loadScript(src, attributes) {
84
100
  }
85
101
  }
86
102
  return new Promise((resolve, reject) => {
87
- var _a;
103
+ var _a, _b;
88
104
  const script = window.document.createElement("script");
89
105
  script.type = "text/javascript";
90
- script.src = src;
106
+ script.src = buildScriptSrc(src, options);
91
107
  script.async = true;
92
108
  script.setAttribute("status", "loading");
93
- for (const [k, v] of Object.entries(attributes !== null && attributes !== void 0 ? attributes : {})) {
109
+ for (const [k, v] of Object.entries((_a = options === null || options === void 0 ? void 0 : options.attributes) !== null && _a !== void 0 ? _a : {})) {
94
110
  script.setAttribute(k, v);
95
111
  }
96
112
  script.onload = () => {
@@ -104,7 +120,7 @@ function loadScript(src, attributes) {
104
120
  reject(new Error(`Failed to load ${src}`));
105
121
  };
106
122
  const tag = window.document.getElementsByTagName("script")[0];
107
- (_a = tag.parentElement) === null || _a === void 0 ? void 0 : _a.insertBefore(script, tag);
123
+ (_b = tag.parentElement) === null || _b === void 0 ? void 0 : _b.insertBefore(script, tag);
108
124
  });
109
125
  }
110
126
 
@@ -204,6 +220,7 @@ var __awaiter$4 = (undefined && undefined.__awaiter) || function (thisArg, _argu
204
220
  step((generator = generator.apply(thisArg, _arguments || [])).next());
205
221
  });
206
222
  };
223
+ const cdn = "cdn.lr-ingest.io/";
207
224
  const logrocketPlugin = {
208
225
  id: "logrocket",
209
226
  handle(config, payload) {
@@ -254,7 +271,7 @@ function initLogrocketIfNeeded(appId) {
254
271
  return;
255
272
  }
256
273
  setLogRocketState("loading");
257
- loadScript(`https://cdn.lr-ingest.io/LogRocket.min.js`, { crossOrigin: "anonymous" })
274
+ loadScript(`${cdn}LogRocket`, { min: true, attributes: { crossOrigin: "anonymous" } })
258
275
  .then(() => {
259
276
  if (window["LogRocket"]) {
260
277
  try {
@@ -377,8 +394,8 @@ function initGtmIfNeeded(config, payload) {
377
394
  event: "gtm.js",
378
395
  });
379
396
  const dl = l != "dataLayer" ? "&l=" + l : "";
380
- const scriptSrc = "https://www.googletagmanager.com/gtm.js?id=" + i + dl;
381
- loadScript(scriptSrc)
397
+ const scriptSrc = "googletagmanager.com/gtm";
398
+ loadScript(scriptSrc, { www: true, js: true, query: "id=" + i + dl })
382
399
  .then(() => {
383
400
  setGtmState("loaded");
384
401
  })
@@ -399,7 +416,7 @@ var __awaiter$2 = (undefined && undefined.__awaiter) || function (thisArg, _argu
399
416
  step((generator = generator.apply(thisArg, _arguments || [])).next());
400
417
  });
401
418
  };
402
- const defaultScriptSrc = "https://www.googletagmanager.com/gtag/js";
419
+ const defaultScriptSrc = "googletagmanager.com/gtag/js";
403
420
  const ga4Plugin = {
404
421
  id: "ga4-tag",
405
422
  handle(config, payload) {
@@ -461,7 +478,6 @@ function initGa4IfNeeded(config, payload) {
461
478
  const dlParam = dlName !== "dataLayer" ? "&l=" + dlName : "";
462
479
  // to work with both GA4 and GTM
463
480
  const tagId = config.measurementIds;
464
- const scriptSrc = `${defaultScriptSrc}?id=${tagId}${dlParam}`;
465
481
  window[dlName] = window[dlName] || [];
466
482
  const gtag = function () {
467
483
  window[dlName].push(arguments);
@@ -471,7 +487,7 @@ function initGa4IfNeeded(config, payload) {
471
487
  gtag(
472
488
  // @ts-ignore
473
489
  "config", tagId, Object.assign(Object.assign({}, (payload.userId ? { user_id: payload.userId } : {})), (!config.autoPageView ? { send_page_view: false } : {})));
474
- loadScript(scriptSrc)
490
+ loadScript(defaultScriptSrc, { query: `id=${tagId}${dlParam}`, www: true })
475
491
  .then(() => {
476
492
  setGa4State("loaded");
477
493
  })
@@ -1110,8 +1126,15 @@ function getGa4Ids(runtime) {
1110
1126
  return undefined;
1111
1127
  }
1112
1128
  }
1113
- function removeCookie(name) {
1114
- document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:01 GMT;";
1129
+ function removeCookie(name, { domain, secure }) {
1130
+ document.cookie =
1131
+ name +
1132
+ "=;domain=" +
1133
+ domain +
1134
+ ";path=/" +
1135
+ ";expires=Thu, 01 Jan 1970 00:00:01 GMT;SameSite=" +
1136
+ (secure ? "None" : "Lax") +
1137
+ (secure ? ";secure" : "");
1115
1138
  }
1116
1139
  function setCookie(name, val, { domain, secure }) {
1117
1140
  document.cookie =
@@ -1153,7 +1176,18 @@ const cookieStorage = (cookieDomain, key2cookie) => {
1153
1176
  return parse(result);
1154
1177
  },
1155
1178
  removeItem(key) {
1156
- removeCookie(key2cookie[key] || key);
1179
+ removeCookie(key2cookie[key] || key, {
1180
+ domain: cookieDomain,
1181
+ secure: window.location.protocol === "https:",
1182
+ });
1183
+ },
1184
+ reset() {
1185
+ for (const v of Object.values(key2cookie)) {
1186
+ removeCookie(v, {
1187
+ domain: cookieDomain,
1188
+ secure: window.location.protocol === "https:",
1189
+ });
1190
+ }
1157
1191
  },
1158
1192
  };
1159
1193
  };
@@ -1224,6 +1258,9 @@ const emptyRuntime = (config) => ({
1224
1258
  store() {
1225
1259
  const storage = {};
1226
1260
  return {
1261
+ reset() {
1262
+ Object.keys(storage).forEach(key => delete storage[key]);
1263
+ },
1227
1264
  setItem(key, val) {
1228
1265
  if (config.debug) {
1229
1266
  console.log(`[JITSU EMPTY RUNTIME] Set storage item ${key}=${JSON.stringify(val)}`);
@@ -1495,10 +1532,13 @@ function send(method, payload, jitsuConfig, instance, store) {
1495
1532
  console.warn(`[JITSU] ${payload.type} responded with list of ${responseJson.destinations.length} destinations. However, this code is running in server-to-server mode, so destinations will be ignored`, jitsuConfig.debug ? JSON.stringify(responseJson.destinations, null, 2) : undefined);
1496
1533
  }
1497
1534
  else {
1498
- if (jitsuConfig.debug) {
1499
- console.log(`[JITSU] Processing device destinations: `, JSON.stringify(responseJson.destinations, null, 2));
1535
+ //double protection, ingest should not return destinations in s2s mode
1536
+ if (isInBrowser()) {
1537
+ if (jitsuConfig.debug) {
1538
+ console.log(`[JITSU] Processing device destinations: `, JSON.stringify(responseJson.destinations, null, 2));
1539
+ }
1540
+ return processDestinations(responseJson.destinations, method, adjustedPayload, !!jitsuConfig.debug, instance);
1500
1541
  }
1501
- return processDestinations(responseJson.destinations, method, adjustedPayload, !!jitsuConfig.debug, instance);
1502
1542
  }
1503
1543
  }
1504
1544
  return adjustedPayload;
@@ -1538,9 +1578,11 @@ const jitsuAnalyticsPlugin = (pluginConfig = {}) => {
1538
1578
  return send("identify", payload, config, instance, storage);
1539
1579
  },
1540
1580
  reset: args => {
1541
- //clear storage cache
1542
- if (pluginConfig.storageWrapper) {
1543
- pluginConfig.storageWrapper(args.instance.storage).reset();
1581
+ const { config, instance } = args;
1582
+ const storage = pluginConfig.storageWrapper ? pluginConfig.storageWrapper(instance.storage) : instance.storage;
1583
+ storage === null || storage === void 0 ? void 0 : storage.reset();
1584
+ if (config.debug) {
1585
+ console.log("[JITSU DEBUG] Resetting Jitsu plugin storage");
1544
1586
  }
1545
1587
  },
1546
1588
  methods: {
@@ -1652,9 +1694,9 @@ function createUnderlyingAnalyticsInstance(opts, rt, plugins = []) {
1652
1694
  },
1653
1695
  reset() {
1654
1696
  for (const key of [...Object.keys(storageCache)]) {
1655
- storage.removeItem(key);
1656
1697
  delete storageCache[key];
1657
1698
  }
1699
+ storage.reset();
1658
1700
  },
1659
1701
  removeItem(key) {
1660
1702
  if (opts.debug) {
@@ -1711,7 +1753,20 @@ function createUnderlyingAnalyticsInstance(opts, rt, plugins = []) {
1711
1753
  userState.anonymousId = id;
1712
1754
  }
1713
1755
  analytics.setAnonymousId(id);
1714
- }, group(groupId, traits, options, callback) {
1756
+ }, reset() {
1757
+ return __awaiter(this, void 0, void 0, function* () {
1758
+ if (opts.debug) {
1759
+ console.log("[JITSU DEBUG] Called reset(). Storage state", JSON.stringify(analytics.user()));
1760
+ }
1761
+ storage.reset();
1762
+ yield analytics.reset();
1763
+ this.setAnonymousId(uuid());
1764
+ if (opts.debug) {
1765
+ console.log("[JITSU DEBUG] User state after reset", JSON.stringify(analytics.user()));
1766
+ }
1767
+ });
1768
+ },
1769
+ group(groupId, traits, options, callback) {
1715
1770
  return __awaiter(this, void 0, void 0, function* () {
1716
1771
  const results = [];
1717
1772
  for (const plugin of Object.values(analytics.plugins)) {
@@ -1760,5 +1815,14 @@ function jitsuAnalytics(_opts) {
1760
1815
  // result.loaded(createUnderlyingAnalyticsInstance(opts, rt));
1761
1816
  // }
1762
1817
  }
1818
+ function uuid() {
1819
+ var u = "", m = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx", i = 0, rb = (Math.random() * 0xffffffff) | 0;
1820
+ while (i++ < 36) {
1821
+ var c = m[i - 1], r = rb & 0xf, v = c == "x" ? r : (r & 0x3) | 0x8;
1822
+ u += c == "-" || c == "4" ? c : v.toString(16);
1823
+ rb = i % 8 == 0 ? (Math.random() * 0xffffffff) | 0 : rb >> 4;
1824
+ }
1825
+ return u;
1826
+ }
1763
1827
 
1764
1828
  export { emptyAnalytics, emptyRuntime, isInBrowser, jitsuAnalytics, parseQuery, randomId, windowRuntime };
@@ -1 +1,8 @@
1
- export declare function loadScript(src: string, attributes?: Record<string, string>): Promise<HTMLScriptElement>;
1
+ export type ScriptOptions = {
2
+ attributes?: Record<string, string>;
3
+ www?: boolean;
4
+ js?: boolean;
5
+ min?: boolean;
6
+ query?: string;
7
+ };
8
+ export declare function loadScript(src: string, options?: ScriptOptions): Promise<HTMLScriptElement>;