@tracelog/lib 2.8.5 → 2.9.0-rc.108.13
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.
- package/README.md +7 -1
- package/dist/browser/tracelog-shopify-pixel.iife.js +1 -0
- package/dist/browser/tracelog-shopify-pixel.iife.js.map +1 -0
- package/dist/browser/tracelog.esm.js +1108 -857
- package/dist/browser/tracelog.esm.js.map +1 -1
- package/dist/browser/tracelog.js +2 -2
- package/dist/browser/tracelog.js.map +1 -1
- package/dist/pixel/index.cjs +3 -0
- package/dist/pixel/index.cjs.map +1 -0
- package/dist/pixel/index.d.mts +145 -0
- package/dist/pixel/index.d.ts +145 -0
- package/dist/pixel/index.js +3 -0
- package/dist/pixel/index.js.map +1 -0
- package/dist/public-api.cjs +2 -2
- package/dist/public-api.cjs.map +1 -1
- package/dist/public-api.d.mts +168 -5
- package/dist/public-api.d.ts +168 -5
- package/dist/public-api.js +2 -2
- package/dist/public-api.js.map +1 -1
- package/package.json +8 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
3
|
-
const
|
|
1
|
+
const gr = 9e5;
|
|
2
|
+
const pr = 120, Er = 49152, Sr = 100, Tr = 500, vr = 200;
|
|
3
|
+
const Ir = 1e3, _r = 500, yr = 1e3;
|
|
4
4
|
const b = "data-tlog", bt = [
|
|
5
5
|
"button",
|
|
6
6
|
"a",
|
|
@@ -49,7 +49,7 @@ const b = "data-tlog", bt = [
|
|
|
49
49
|
"code",
|
|
50
50
|
"otp"
|
|
51
51
|
];
|
|
52
|
-
const
|
|
52
|
+
const S = {
|
|
53
53
|
INVALID_SESSION_TIMEOUT: "Session timeout must be between 30000ms (30 seconds) and 86400000ms (24 hours)",
|
|
54
54
|
INVALID_SAMPLING_RATE: "Sampling rate must be between 0 and 1",
|
|
55
55
|
INVALID_ERROR_SAMPLING_RATE: "Error sampling must be between 0 and 1",
|
|
@@ -79,7 +79,7 @@ const E = {
|
|
|
79
79
|
/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi,
|
|
80
80
|
/<embed\b[^>]*>/gi,
|
|
81
81
|
/<object\b[^<]*(?:(?!<\/object>)<[^<]*)*<\/object>/gi
|
|
82
|
-
],
|
|
82
|
+
], I = "tlog", G = `${I}:qa_mode`, ve = `${I}:uid`, rt = "tlog_mode", Ue = "qa", He = "qa_off", Ct = (r) => r ? `${I}:${r}:queue` : `${I}:queue`, Rt = (r) => r ? `${I}:${r}:rate_limit` : `${I}:rate_limit`, Nt = (r) => r ? `${I}:${r}:session` : `${I}:session`, Ot = (r) => r ? `${I}:${r}:broadcast` : `${I}:broadcast`, Fe = (r, e) => `${I}:${r}:session_counts:${e}`, xe = 10080 * 60 * 1e3, $e = `${I}:session_counts_last_cleanup`, Be = 3600 * 1e3, me = (r) => r ? `${I}:${r}:identity` : `${I}:identity`, H = `${I}:pending_identity`;
|
|
83
83
|
var $ = /* @__PURE__ */ ((r) => (r.Localhost = "localhost:8080", r.Fail = "localhost:9999", r))($ || {}), A = /* @__PURE__ */ ((r) => (r.Mobile = "mobile", r.Tablet = "tablet", r.Desktop = "desktop", r.Unknown = "unknown", r))(A || {}), se = /* @__PURE__ */ ((r) => (r.EVENT = "event", r.QUEUE = "queue", r))(se || {});
|
|
84
84
|
class O extends Error {
|
|
85
85
|
constructor(e, t, s) {
|
|
@@ -93,13 +93,13 @@ class re extends Error {
|
|
|
93
93
|
super(e), this.name = "RateLimitError", Error.captureStackTrace && Error.captureStackTrace(this, re);
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
|
-
class
|
|
96
|
+
class ne extends Error {
|
|
97
97
|
constructor(e) {
|
|
98
|
-
super(e), this.name = "TimeoutError", Error.captureStackTrace && Error.captureStackTrace(this,
|
|
98
|
+
super(e), this.name = "TimeoutError", Error.captureStackTrace && Error.captureStackTrace(this, ne);
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
|
-
var u = /* @__PURE__ */ ((r) => (r.PAGE_VIEW = "page_view", r.CLICK = "click", r.SCROLL = "scroll", r.SESSION_START = "session_start", r.CUSTOM = "custom", r.WEB_VITALS = "web_vitals", r.ERROR = "error", r.VIEWPORT_VISIBLE = "viewport_visible", r))(u || {}), Z = /* @__PURE__ */ ((r) => (r.UP = "up", r.DOWN = "down", r))(Z || {}), B = /* @__PURE__ */ ((r) => (r.JS_ERROR = "js_error", r.PROMISE_REJECTION = "promise_rejection", r))(B || {}),
|
|
102
|
-
const
|
|
101
|
+
var u = /* @__PURE__ */ ((r) => (r.PAGE_VIEW = "page_view", r.CLICK = "click", r.SCROLL = "scroll", r.SESSION_START = "session_start", r.CUSTOM = "custom", r.WEB_VITALS = "web_vitals", r.ERROR = "error", r.VIEWPORT_VISIBLE = "viewport_visible", r))(u || {}), Z = /* @__PURE__ */ ((r) => (r.UP = "up", r.DOWN = "down", r))(Z || {}), B = /* @__PURE__ */ ((r) => (r.JS_ERROR = "js_error", r.PROMISE_REJECTION = "promise_rejection", r))(B || {}), ie = /* @__PURE__ */ ((r) => (r.QA = "qa", r))(ie || {});
|
|
102
|
+
const wr = (r) => r.type === u.SCROLL && "scroll_data" in r && r.scroll_data.is_primary === !0, br = (r) => r.type === u.SCROLL && "scroll_data" in r && r.scroll_data.is_primary === !1;
|
|
103
103
|
class j extends Error {
|
|
104
104
|
constructor(e, t, s) {
|
|
105
105
|
super(e), this.errorCode = t, this.layer = s, this.name = this.constructor.name, Error.captureStackTrace && Error.captureStackTrace(this, this.constructor);
|
|
@@ -107,7 +107,7 @@ class j extends Error {
|
|
|
107
107
|
errorCode;
|
|
108
108
|
layer;
|
|
109
109
|
}
|
|
110
|
-
class
|
|
110
|
+
class p extends j {
|
|
111
111
|
constructor(e, t = "config") {
|
|
112
112
|
super(e, "APP_CONFIG_INVALID", t);
|
|
113
113
|
}
|
|
@@ -127,13 +127,13 @@ class N extends j {
|
|
|
127
127
|
super(e, "INTEGRATION_INVALID", t);
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
|
-
class
|
|
130
|
+
class Lr extends j {
|
|
131
131
|
constructor(e, t, s = "runtime") {
|
|
132
132
|
super(e, "INITIALIZATION_TIMEOUT", s), this.timeoutMs = t;
|
|
133
133
|
}
|
|
134
134
|
timeoutMs;
|
|
135
135
|
}
|
|
136
|
-
const
|
|
136
|
+
const nt = "background: #ff9800; color: white; font-weight: bold; padding: 2px 8px; border-radius: 3px;", it = "background: #9e9e9e; color: white; font-weight: bold; padding: 2px 8px; border-radius: 3px;", Dt = "background: #d32f2f; color: white; font-weight: bold; padding: 2px 8px; border-radius: 3px;", kt = (r, e) => {
|
|
137
137
|
if (e) {
|
|
138
138
|
if (e instanceof Error) {
|
|
139
139
|
const t = e.message.replace(/\s+at\s+.*$/gm, "").replace(/\s*\([^()]+:\d+:\d+\)/g, "");
|
|
@@ -156,36 +156,36 @@ const it = "background: #ff9800; color: white; font-weight: bold; padding: 2px 8
|
|
|
156
156
|
if (typeof window > "u" || typeof sessionStorage > "u")
|
|
157
157
|
return !1;
|
|
158
158
|
try {
|
|
159
|
-
return sessionStorage.getItem(
|
|
159
|
+
return sessionStorage.getItem(G) === "true";
|
|
160
160
|
} catch {
|
|
161
161
|
return !1;
|
|
162
162
|
}
|
|
163
163
|
}, a = (r, e, t) => {
|
|
164
|
-
const { error: s, data:
|
|
165
|
-
if (!Ut(l,
|
|
164
|
+
const { error: s, data: n, showToClient: i = !1, style: o, visibility: l } = t ?? {}, d = s ? kt(e, s) : `[TraceLog] ${e}`, c = r === "error" ? "error" : r === "warn" ? "warn" : "log";
|
|
165
|
+
if (!Ut(l, i))
|
|
166
166
|
return;
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
}, Ut = (r, e) => r === "critical" ? !0 : r === "qa" || e ? Vt() : !1,
|
|
170
|
-
const
|
|
171
|
-
s !== void 0 ?
|
|
167
|
+
const m = Ht(l, o), g = n !== void 0 ? Ie(n) : void 0;
|
|
168
|
+
Ft(c, d, m, g);
|
|
169
|
+
}, Ut = (r, e) => r === "critical" ? !0 : r === "qa" || e ? Vt() : !1, Ht = (r, e) => e !== void 0 && e !== "" ? e : r === "critical" ? Dt : "", Ft = (r, e, t, s) => {
|
|
170
|
+
const n = t !== void 0 && t !== "", i = n ? `%c${e}` : e;
|
|
171
|
+
s !== void 0 ? n ? console[r](i, t, s) : console[r](i, s) : n ? console[r](i, t) : console[r](i);
|
|
172
172
|
}, Ie = (r) => {
|
|
173
173
|
const e = {}, t = ["token", "password", "secret", "key", "apikey", "api_key", "sessionid", "session_id"];
|
|
174
|
-
for (const [s,
|
|
175
|
-
const
|
|
176
|
-
if (t.some((o) =>
|
|
174
|
+
for (const [s, n] of Object.entries(r)) {
|
|
175
|
+
const i = s.toLowerCase();
|
|
176
|
+
if (t.some((o) => i.includes(o))) {
|
|
177
177
|
e[s] = "[REDACTED]";
|
|
178
178
|
continue;
|
|
179
179
|
}
|
|
180
|
-
|
|
180
|
+
n !== null && typeof n == "object" && !Array.isArray(n) ? e[s] = Ie(n) : Array.isArray(n) ? e[s] = n.map(
|
|
181
181
|
(o) => o !== null && typeof o == "object" && !Array.isArray(o) ? Ie(o) : o
|
|
182
|
-
) : e[s] =
|
|
182
|
+
) : e[s] = n;
|
|
183
183
|
}
|
|
184
184
|
return e;
|
|
185
185
|
};
|
|
186
|
-
let
|
|
186
|
+
let _e, ot;
|
|
187
187
|
const xt = () => {
|
|
188
|
-
typeof window < "u" && !
|
|
188
|
+
typeof window < "u" && !_e && (_e = window.matchMedia("(pointer: coarse)"), ot = window.matchMedia("(hover: none)"));
|
|
189
189
|
}, oe = "Unknown", $t = (r) => {
|
|
190
190
|
const e = r.userAgentData?.platform;
|
|
191
191
|
if (e != null && e !== "") {
|
|
@@ -201,10 +201,10 @@ const xt = () => {
|
|
|
201
201
|
}, Bt = (r) => {
|
|
202
202
|
const e = r.userAgentData?.brands;
|
|
203
203
|
if (e != null && e.length > 0) {
|
|
204
|
-
const
|
|
205
|
-
if (
|
|
206
|
-
const
|
|
207
|
-
return /google chrome/i.test(
|
|
204
|
+
const n = e.filter((i) => !/not.?a.?brand|chromium/i.test(i.brand))[0];
|
|
205
|
+
if (n != null) {
|
|
206
|
+
const i = n.brand;
|
|
207
|
+
return /google chrome/i.test(i) ? "Chrome" : /microsoft edge/i.test(i) ? "Edge" : /opera/i.test(i) ? "Opera" : i;
|
|
208
208
|
}
|
|
209
209
|
}
|
|
210
210
|
const t = navigator.userAgent;
|
|
@@ -213,16 +213,16 @@ const xt = () => {
|
|
|
213
213
|
try {
|
|
214
214
|
const r = navigator;
|
|
215
215
|
if (r.userAgentData != null && typeof r.userAgentData.mobile == "boolean") {
|
|
216
|
-
const
|
|
217
|
-
return
|
|
216
|
+
const d = r.userAgentData.platform;
|
|
217
|
+
return d != null && d !== "" && /ipad|tablet/i.test(d) ? A.Tablet : r.userAgentData.mobile ? A.Mobile : A.Desktop;
|
|
218
218
|
}
|
|
219
219
|
xt();
|
|
220
|
-
const e = window.innerWidth, t =
|
|
221
|
-
return e <= 767 || o &&
|
|
220
|
+
const e = window.innerWidth, t = _e?.matches ?? !1, s = ot?.matches ?? !1, n = "ontouchstart" in window || navigator.maxTouchPoints > 0, i = navigator.userAgent.toLowerCase(), o = /mobile|android|iphone|ipod|blackberry|iemobile|opera mini/.test(i), l = /tablet|ipad|android(?!.*mobile)/.test(i);
|
|
221
|
+
return e <= 767 || o && n ? A.Mobile : e >= 768 && e <= 1024 || l || t && s && n ? A.Tablet : A.Desktop;
|
|
222
222
|
} catch (r) {
|
|
223
223
|
return a("debug", "Device detection failed, defaulting to desktop", { error: r }), A.Desktop;
|
|
224
224
|
}
|
|
225
|
-
},
|
|
225
|
+
}, Gt = () => {
|
|
226
226
|
try {
|
|
227
227
|
const r = navigator;
|
|
228
228
|
return {
|
|
@@ -254,7 +254,7 @@ const xt = () => {
|
|
|
254
254
|
/:\/\/[^:/]+:([^@]+)@/gi,
|
|
255
255
|
// Sensitive URL query parameters (token=, password=, auth=, secret=, api_key=, etc.)
|
|
256
256
|
/[?&](token|password|passwd|auth|secret|secret_key|private_key|auth_key|api_key|apikey|access_token)=[^&\s]+/gi
|
|
257
|
-
],
|
|
257
|
+
], Ge = 500, Xe = 2e3, je = 5e3, ee = 50, Xt = ee * 2, lt = 1, jt = 1e3, Kt = 10, Ke = 5e3, Qt = 6e4, zt = 64, Ar = {
|
|
258
258
|
LCP: 2500,
|
|
259
259
|
// Good: ≤ 2.5s
|
|
260
260
|
FCP: 1800,
|
|
@@ -266,7 +266,7 @@ const xt = () => {
|
|
|
266
266
|
TTFB: 800,
|
|
267
267
|
// Good: ≤ 800ms
|
|
268
268
|
LONG_TASK: 50
|
|
269
|
-
},
|
|
269
|
+
}, Qe = {
|
|
270
270
|
LCP: 2500,
|
|
271
271
|
// Needs improvement: > 2.5s (same as good boundary)
|
|
272
272
|
FCP: 1800,
|
|
@@ -290,19 +290,19 @@ const xt = () => {
|
|
|
290
290
|
TTFB: 1800,
|
|
291
291
|
// Poor: > 1800ms
|
|
292
292
|
LONG_TASK: 50
|
|
293
|
-
},
|
|
293
|
+
}, ye = "needs-improvement", ze = (r = ye) => {
|
|
294
294
|
switch (r) {
|
|
295
295
|
case "all":
|
|
296
296
|
return { LCP: 0, FCP: 0, CLS: 0, INP: 0, TTFB: 0, LONG_TASK: 0 };
|
|
297
297
|
// Track everything
|
|
298
298
|
case "needs-improvement":
|
|
299
|
-
return
|
|
299
|
+
return Qe;
|
|
300
300
|
case "poor":
|
|
301
301
|
return Yt;
|
|
302
302
|
default:
|
|
303
|
-
return
|
|
303
|
+
return Qe;
|
|
304
304
|
}
|
|
305
|
-
}, qt = 1e3, Jt = 50, Zt = "2.
|
|
305
|
+
}, qt = 1e3, Jt = 50, Zt = "2.9.0", es = Zt, ct = () => typeof window < "u" && typeof sessionStorage < "u", ts = () => {
|
|
306
306
|
try {
|
|
307
307
|
const r = new URLSearchParams(window.location.search);
|
|
308
308
|
r.delete(rt);
|
|
@@ -314,29 +314,29 @@ const xt = () => {
|
|
|
314
314
|
if (!ct())
|
|
315
315
|
return !1;
|
|
316
316
|
try {
|
|
317
|
-
const e = new URLSearchParams(window.location.search).get(rt), t = sessionStorage.getItem(
|
|
317
|
+
const e = new URLSearchParams(window.location.search).get(rt), t = sessionStorage.getItem(G);
|
|
318
318
|
let s = null;
|
|
319
|
-
return e === Ue ? (s = !0, sessionStorage.setItem(
|
|
320
|
-
visibility: "qa",
|
|
321
|
-
style: it
|
|
322
|
-
})) : e === Fe && (s = !1, sessionStorage.setItem(X, "false"), a("info", "QA Mode DISABLED", {
|
|
319
|
+
return e === Ue ? (s = !0, sessionStorage.setItem(G, "true"), a("info", "QA Mode ACTIVE", {
|
|
323
320
|
visibility: "qa",
|
|
324
321
|
style: nt
|
|
325
|
-
}))
|
|
322
|
+
})) : e === He && (s = !1, sessionStorage.setItem(G, "false"), a("info", "QA Mode DISABLED", {
|
|
323
|
+
visibility: "qa",
|
|
324
|
+
style: it
|
|
325
|
+
})), (e === Ue || e === He) && ts(), s ?? t === "true";
|
|
326
326
|
} catch {
|
|
327
327
|
return !1;
|
|
328
328
|
}
|
|
329
329
|
}, rs = (r) => {
|
|
330
330
|
if (ct())
|
|
331
331
|
try {
|
|
332
|
-
sessionStorage.setItem(
|
|
332
|
+
sessionStorage.setItem(G, r ? "true" : "false"), a("info", r ? "QA Mode ACTIVE" : "QA Mode DISABLED", {
|
|
333
333
|
visibility: "qa",
|
|
334
|
-
style: r ?
|
|
334
|
+
style: r ? nt : it
|
|
335
335
|
});
|
|
336
336
|
} catch {
|
|
337
337
|
a("debug", "Cannot set QA mode: sessionStorage unavailable");
|
|
338
338
|
}
|
|
339
|
-
},
|
|
339
|
+
}, ns = [
|
|
340
340
|
"co.uk",
|
|
341
341
|
"org.uk",
|
|
342
342
|
"com.au",
|
|
@@ -353,24 +353,24 @@ const xt = () => {
|
|
|
353
353
|
if (e.length <= 2)
|
|
354
354
|
return r.toLowerCase();
|
|
355
355
|
const t = e.slice(-2).join(".");
|
|
356
|
-
return
|
|
357
|
-
},
|
|
356
|
+
return ns.includes(t) ? e.slice(-3).join(".") : e.slice(-2).join(".");
|
|
357
|
+
}, is = (r, e) => r === e ? !0 : Ye(r) === Ye(e), ge = () => {
|
|
358
358
|
const r = document.referrer;
|
|
359
359
|
if (!r)
|
|
360
360
|
return "Direct";
|
|
361
361
|
try {
|
|
362
362
|
const e = new URL(r).hostname.toLowerCase(), t = window.location.hostname.toLowerCase();
|
|
363
|
-
return
|
|
363
|
+
return is(e, t) ? "Direct" : r;
|
|
364
364
|
} catch (e) {
|
|
365
365
|
return a("debug", "Failed to parse referrer URL, using raw value", { error: e, data: { referrer: r } }), r;
|
|
366
366
|
}
|
|
367
|
-
},
|
|
367
|
+
}, pe = () => {
|
|
368
368
|
const r = new URLSearchParams(window.location.search), e = {};
|
|
369
369
|
return Lt.forEach((s) => {
|
|
370
|
-
const
|
|
371
|
-
if (
|
|
372
|
-
const
|
|
373
|
-
e[
|
|
370
|
+
const n = r.get(s);
|
|
371
|
+
if (n) {
|
|
372
|
+
const i = s.split("utm_")[1];
|
|
373
|
+
e[i] = n;
|
|
374
374
|
}
|
|
375
375
|
}), Object.keys(e).length ? e : void 0;
|
|
376
376
|
}, dt = () => typeof crypto < "u" && crypto.randomUUID ? crypto.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (r) => {
|
|
@@ -386,15 +386,15 @@ const os = () => {
|
|
|
386
386
|
try {
|
|
387
387
|
if (typeof crypto < "u" && crypto.getRandomValues) {
|
|
388
388
|
const s = crypto.getRandomValues(new Uint8Array(3));
|
|
389
|
-
s && (t = Array.from(s, (
|
|
389
|
+
s && (t = Array.from(s, (n) => n.toString(16).padStart(2, "0")).join(""));
|
|
390
390
|
}
|
|
391
391
|
} catch {
|
|
392
392
|
}
|
|
393
393
|
return t || (t = Math.floor(Math.random() * 16777215).toString(16).padStart(6, "0")), `${r}-${e}-${t}`;
|
|
394
394
|
}, ut = (r, e = !1) => {
|
|
395
395
|
try {
|
|
396
|
-
const t = new URL(r), s = t.protocol === "https:",
|
|
397
|
-
return s || e &&
|
|
396
|
+
const t = new URL(r), s = t.protocol === "https:", n = t.protocol === "http:";
|
|
397
|
+
return s || e && n;
|
|
398
398
|
} catch {
|
|
399
399
|
return !1;
|
|
400
400
|
}
|
|
@@ -412,13 +412,13 @@ const os = () => {
|
|
|
412
412
|
throw new Error("Invalid hostname structure");
|
|
413
413
|
if (s.length === 1)
|
|
414
414
|
throw new Error("Single-part domain not supported for SaaS integration");
|
|
415
|
-
let
|
|
416
|
-
if (s.length === 2 ?
|
|
415
|
+
let n;
|
|
416
|
+
if (s.length === 2 ? n = s.join(".") : n = s.slice(-2).join("."), !n || n.split(".").length < 2)
|
|
417
417
|
throw new Error("Invalid domain structure for SaaS");
|
|
418
|
-
const
|
|
419
|
-
if (!ut(
|
|
418
|
+
const i = `https://${r}.${n}/collect`;
|
|
419
|
+
if (!ut(i))
|
|
420
420
|
throw new Error("Generated URL failed validation");
|
|
421
|
-
return
|
|
421
|
+
return i;
|
|
422
422
|
} catch (e) {
|
|
423
423
|
throw new Error(`Invalid SaaS URL configuration: ${e instanceof Error ? e.message : String(e)}`);
|
|
424
424
|
}
|
|
@@ -433,16 +433,16 @@ const os = () => {
|
|
|
433
433
|
e.custom = t;
|
|
434
434
|
}
|
|
435
435
|
return e;
|
|
436
|
-
},
|
|
436
|
+
}, we = (r, e = []) => {
|
|
437
437
|
if (!r || typeof r != "string")
|
|
438
438
|
return a("warn", "Invalid URL provided to normalizeUrl", { data: { type: typeof r } }), r || "";
|
|
439
439
|
try {
|
|
440
|
-
const t = new URL(r), s = t.searchParams,
|
|
441
|
-
let
|
|
440
|
+
const t = new URL(r), s = t.searchParams, n = [.../* @__PURE__ */ new Set([...At, ...e])];
|
|
441
|
+
let i = !1;
|
|
442
442
|
const o = [];
|
|
443
|
-
return
|
|
444
|
-
s.has(
|
|
445
|
-
}), !
|
|
443
|
+
return n.forEach((d) => {
|
|
444
|
+
s.has(d) && (s.delete(d), i = !0, o.push(d));
|
|
445
|
+
}), !i && r.includes("?") ? r : (t.search = s.toString(), t.toString());
|
|
446
446
|
} catch (t) {
|
|
447
447
|
return a("warn", "URL normalization failed, returning original", { error: t, data: { urlLength: r?.length } }), r;
|
|
448
448
|
}
|
|
@@ -452,9 +452,9 @@ const os = () => {
|
|
|
452
452
|
let e = r;
|
|
453
453
|
r.length > 1e3 && (e = r.slice(0, Math.max(0, 1e3)));
|
|
454
454
|
let t = 0;
|
|
455
|
-
for (const
|
|
456
|
-
const
|
|
457
|
-
e = e.replace(
|
|
455
|
+
for (const n of Mt) {
|
|
456
|
+
const i = e;
|
|
457
|
+
e = e.replace(n, ""), i !== e && t++;
|
|
458
458
|
}
|
|
459
459
|
return t > 0 && a("warn", "XSS patterns detected and removed", {
|
|
460
460
|
data: {
|
|
@@ -462,7 +462,7 @@ const os = () => {
|
|
|
462
462
|
valueLength: r.length
|
|
463
463
|
}
|
|
464
464
|
}), e.trim();
|
|
465
|
-
},
|
|
465
|
+
}, be = (r, e = 0) => {
|
|
466
466
|
if (r == null)
|
|
467
467
|
return null;
|
|
468
468
|
if (typeof r == "string")
|
|
@@ -474,14 +474,14 @@ const os = () => {
|
|
|
474
474
|
if (e > 10)
|
|
475
475
|
return null;
|
|
476
476
|
if (Array.isArray(r))
|
|
477
|
-
return r.slice(0, 1e3).map((
|
|
477
|
+
return r.slice(0, 1e3).map((n) => be(n, e + 1)).filter((n) => n !== null);
|
|
478
478
|
if (typeof r == "object") {
|
|
479
|
-
const t = {},
|
|
480
|
-
for (const [
|
|
481
|
-
const l = qe(
|
|
479
|
+
const t = {}, n = Object.entries(r).slice(0, 200);
|
|
480
|
+
for (const [i, o] of n) {
|
|
481
|
+
const l = qe(i);
|
|
482
482
|
if (l) {
|
|
483
|
-
const
|
|
484
|
-
|
|
483
|
+
const d = be(o, e + 1);
|
|
484
|
+
d !== null && (t[l] = d);
|
|
485
485
|
}
|
|
486
486
|
}
|
|
487
487
|
return t;
|
|
@@ -491,7 +491,7 @@ const os = () => {
|
|
|
491
491
|
if (typeof r != "object" || r === null)
|
|
492
492
|
return {};
|
|
493
493
|
try {
|
|
494
|
-
const e =
|
|
494
|
+
const e = be(r);
|
|
495
495
|
return typeof e == "object" && e !== null ? e : {};
|
|
496
496
|
} catch (e) {
|
|
497
497
|
const t = e instanceof Error ? e.message : String(e);
|
|
@@ -499,69 +499,79 @@ const os = () => {
|
|
|
499
499
|
}
|
|
500
500
|
}, ds = (r) => {
|
|
501
501
|
if (r !== void 0 && (r === null || typeof r != "object"))
|
|
502
|
-
throw new
|
|
502
|
+
throw new p("Configuration must be an object", "config");
|
|
503
503
|
if (r) {
|
|
504
504
|
if (r.sessionTimeout !== void 0 && (typeof r.sessionTimeout != "number" || r.sessionTimeout < 3e4 || r.sessionTimeout > 864e5))
|
|
505
|
-
throw new Pt(
|
|
505
|
+
throw new Pt(S.INVALID_SESSION_TIMEOUT, "config");
|
|
506
506
|
if (r.globalMetadata !== void 0 && (typeof r.globalMetadata != "object" || r.globalMetadata === null))
|
|
507
|
-
throw new
|
|
507
|
+
throw new p(S.INVALID_GLOBAL_METADATA, "config");
|
|
508
508
|
if (r.integrations && hs(r.integrations), r.sensitiveQueryParams !== void 0) {
|
|
509
509
|
if (!Array.isArray(r.sensitiveQueryParams))
|
|
510
|
-
throw new
|
|
510
|
+
throw new p(S.INVALID_SENSITIVE_QUERY_PARAMS, "config");
|
|
511
511
|
for (const e of r.sensitiveQueryParams)
|
|
512
512
|
if (typeof e != "string")
|
|
513
|
-
throw new
|
|
513
|
+
throw new p("All sensitive query params must be strings", "config");
|
|
514
514
|
}
|
|
515
515
|
if (r.errorSampling !== void 0 && (typeof r.errorSampling != "number" || r.errorSampling < 0 || r.errorSampling > 1))
|
|
516
|
-
throw new We(
|
|
516
|
+
throw new We(S.INVALID_ERROR_SAMPLING_RATE, "config");
|
|
517
517
|
if (r.samplingRate !== void 0 && (typeof r.samplingRate != "number" || r.samplingRate < 0 || r.samplingRate > 1))
|
|
518
|
-
throw new We(
|
|
518
|
+
throw new We(S.INVALID_SAMPLING_RATE, "config");
|
|
519
519
|
if (r.primaryScrollSelector !== void 0) {
|
|
520
520
|
if (typeof r.primaryScrollSelector != "string" || !r.primaryScrollSelector.trim())
|
|
521
|
-
throw new
|
|
521
|
+
throw new p(S.INVALID_PRIMARY_SCROLL_SELECTOR, "config");
|
|
522
522
|
if (r.primaryScrollSelector !== "window")
|
|
523
523
|
try {
|
|
524
524
|
document.querySelector(r.primaryScrollSelector);
|
|
525
525
|
} catch {
|
|
526
|
-
throw new
|
|
527
|
-
`${
|
|
526
|
+
throw new p(
|
|
527
|
+
`${S.INVALID_PRIMARY_SCROLL_SELECTOR_SYNTAX}: "${r.primaryScrollSelector}"`,
|
|
528
528
|
"config"
|
|
529
529
|
);
|
|
530
530
|
}
|
|
531
531
|
}
|
|
532
532
|
if (r.pageViewThrottleMs !== void 0 && (typeof r.pageViewThrottleMs != "number" || r.pageViewThrottleMs < 0))
|
|
533
|
-
throw new
|
|
533
|
+
throw new p(S.INVALID_PAGE_VIEW_THROTTLE, "config");
|
|
534
534
|
if (r.clickThrottleMs !== void 0 && (typeof r.clickThrottleMs != "number" || r.clickThrottleMs < 0))
|
|
535
|
-
throw new
|
|
535
|
+
throw new p(S.INVALID_CLICK_THROTTLE, "config");
|
|
536
536
|
if (r.maxSameEventPerMinute !== void 0 && (typeof r.maxSameEventPerMinute != "number" || r.maxSameEventPerMinute <= 0))
|
|
537
|
-
throw new
|
|
537
|
+
throw new p(S.INVALID_MAX_SAME_EVENT_PER_MINUTE, "config");
|
|
538
538
|
if (r.sendIntervalMs !== void 0 && (!Number.isFinite(r.sendIntervalMs) || r.sendIntervalMs < 1e3 || r.sendIntervalMs > 6e4))
|
|
539
|
-
throw new
|
|
539
|
+
throw new p(S.INVALID_SEND_INTERVAL, "config");
|
|
540
|
+
if (r.flushOnSpaNavigation !== void 0 && typeof r.flushOnSpaNavigation != "boolean")
|
|
541
|
+
throw new p(
|
|
542
|
+
`Invalid flushOnSpaNavigation type: ${typeof r.flushOnSpaNavigation}. Must be a boolean`,
|
|
543
|
+
"config"
|
|
544
|
+
);
|
|
545
|
+
if (r.flushOnPageHidden !== void 0 && typeof r.flushOnPageHidden != "boolean")
|
|
546
|
+
throw new p(
|
|
547
|
+
`Invalid flushOnPageHidden type: ${typeof r.flushOnPageHidden}. Must be a boolean`,
|
|
548
|
+
"config"
|
|
549
|
+
);
|
|
540
550
|
if (r.viewport !== void 0 && us(r.viewport), r.webVitalsMode !== void 0) {
|
|
541
551
|
if (typeof r.webVitalsMode != "string")
|
|
542
|
-
throw new
|
|
552
|
+
throw new p(
|
|
543
553
|
`Invalid webVitalsMode type: ${typeof r.webVitalsMode}. Must be a string`,
|
|
544
554
|
"config"
|
|
545
555
|
);
|
|
546
556
|
const e = ["all", "needs-improvement", "poor"];
|
|
547
557
|
if (!e.includes(r.webVitalsMode))
|
|
548
|
-
throw new
|
|
558
|
+
throw new p(
|
|
549
559
|
`Invalid webVitalsMode: "${r.webVitalsMode}". Must be one of: ${e.join(", ")}`,
|
|
550
560
|
"config"
|
|
551
561
|
);
|
|
552
562
|
}
|
|
553
563
|
if (r.webVitalsThresholds !== void 0) {
|
|
554
564
|
if (typeof r.webVitalsThresholds != "object" || r.webVitalsThresholds === null || Array.isArray(r.webVitalsThresholds))
|
|
555
|
-
throw new
|
|
565
|
+
throw new p("webVitalsThresholds must be an object", "config");
|
|
556
566
|
const e = ["LCP", "FCP", "CLS", "INP", "TTFB", "LONG_TASK"];
|
|
557
567
|
for (const [t, s] of Object.entries(r.webVitalsThresholds)) {
|
|
558
568
|
if (!e.includes(t))
|
|
559
|
-
throw new
|
|
569
|
+
throw new p(
|
|
560
570
|
`Invalid Web Vitals threshold key: "${t}". Must be one of: ${e.join(", ")}`,
|
|
561
571
|
"config"
|
|
562
572
|
);
|
|
563
573
|
if (typeof s != "number" || !Number.isFinite(s) || s < 0)
|
|
564
|
-
throw new
|
|
574
|
+
throw new p(
|
|
565
575
|
`Invalid Web Vitals threshold value for ${t}: ${s}. Must be a non-negative finite number`,
|
|
566
576
|
"config"
|
|
567
577
|
);
|
|
@@ -570,41 +580,41 @@ const os = () => {
|
|
|
570
580
|
}
|
|
571
581
|
}, us = (r) => {
|
|
572
582
|
if (typeof r != "object" || r === null)
|
|
573
|
-
throw new
|
|
583
|
+
throw new p(S.INVALID_VIEWPORT_CONFIG, "config");
|
|
574
584
|
if (!r.elements || !Array.isArray(r.elements))
|
|
575
|
-
throw new
|
|
585
|
+
throw new p(S.INVALID_VIEWPORT_ELEMENTS, "config");
|
|
576
586
|
if (r.elements.length === 0)
|
|
577
|
-
throw new
|
|
587
|
+
throw new p(S.INVALID_VIEWPORT_ELEMENTS, "config");
|
|
578
588
|
const e = /* @__PURE__ */ new Set();
|
|
579
589
|
for (const t of r.elements) {
|
|
580
590
|
if (!t.selector || typeof t.selector != "string" || !t.selector.trim())
|
|
581
|
-
throw new
|
|
591
|
+
throw new p(S.INVALID_VIEWPORT_ELEMENT, "config");
|
|
582
592
|
const s = t.selector.trim();
|
|
583
593
|
if (e.has(s))
|
|
584
|
-
throw new
|
|
594
|
+
throw new p(
|
|
585
595
|
`Duplicate viewport selector found: "${s}". Each selector should appear only once.`,
|
|
586
596
|
"config"
|
|
587
597
|
);
|
|
588
598
|
if (e.add(s), t.id !== void 0 && (typeof t.id != "string" || !t.id.trim()))
|
|
589
|
-
throw new
|
|
599
|
+
throw new p(S.INVALID_VIEWPORT_ELEMENT_ID, "config");
|
|
590
600
|
if (t.name !== void 0 && (typeof t.name != "string" || !t.name.trim()))
|
|
591
|
-
throw new
|
|
601
|
+
throw new p(S.INVALID_VIEWPORT_ELEMENT_NAME, "config");
|
|
592
602
|
}
|
|
593
603
|
if (r.threshold !== void 0 && (typeof r.threshold != "number" || r.threshold < 0 || r.threshold > 1))
|
|
594
|
-
throw new
|
|
604
|
+
throw new p(S.INVALID_VIEWPORT_THRESHOLD, "config");
|
|
595
605
|
if (r.minDwellTime !== void 0 && (typeof r.minDwellTime != "number" || r.minDwellTime < 0))
|
|
596
|
-
throw new
|
|
606
|
+
throw new p(S.INVALID_VIEWPORT_MIN_DWELL_TIME, "config");
|
|
597
607
|
if (r.cooldownPeriod !== void 0 && (typeof r.cooldownPeriod != "number" || r.cooldownPeriod < 0))
|
|
598
|
-
throw new
|
|
608
|
+
throw new p(S.INVALID_VIEWPORT_COOLDOWN_PERIOD, "config");
|
|
599
609
|
if (r.maxTrackedElements !== void 0 && (typeof r.maxTrackedElements != "number" || r.maxTrackedElements <= 0))
|
|
600
|
-
throw new
|
|
610
|
+
throw new p(S.INVALID_VIEWPORT_MAX_TRACKED_ELEMENTS, "config");
|
|
601
611
|
}, hs = (r) => {
|
|
602
612
|
if (r) {
|
|
603
613
|
if (r.tracelog && (!r.tracelog.projectId || typeof r.tracelog.projectId != "string" || r.tracelog.projectId.trim() === ""))
|
|
604
|
-
throw new N(
|
|
614
|
+
throw new N(S.INVALID_TRACELOG_PROJECT_ID, "config");
|
|
605
615
|
if (r.custom) {
|
|
606
616
|
if (!r.custom.collectApiUrl || typeof r.custom.collectApiUrl != "string" || r.custom.collectApiUrl.trim() === "")
|
|
607
|
-
throw new N(
|
|
617
|
+
throw new N(S.INVALID_CUSTOM_API_URL, "config");
|
|
608
618
|
if (r.custom.allowHttp !== void 0 && typeof r.custom.allowHttp != "boolean")
|
|
609
619
|
throw new N("allowHttp must be a boolean", "config");
|
|
610
620
|
const e = r.custom.collectApiUrl.trim();
|
|
@@ -633,7 +643,9 @@ const os = () => {
|
|
|
633
643
|
pageViewThrottleMs: r?.pageViewThrottleMs ?? 1e3,
|
|
634
644
|
clickThrottleMs: r?.clickThrottleMs ?? 300,
|
|
635
645
|
maxSameEventPerMinute: r?.maxSameEventPerMinute ?? 60,
|
|
636
|
-
sendIntervalMs: r?.sendIntervalMs ?? 1e4
|
|
646
|
+
sendIntervalMs: r?.sendIntervalMs ?? 1e4,
|
|
647
|
+
flushOnSpaNavigation: r?.flushOnSpaNavigation ?? !0,
|
|
648
|
+
flushOnPageHidden: r?.flushOnPageHidden ?? !0
|
|
637
649
|
};
|
|
638
650
|
return e.integrations?.custom && (e.integrations.custom = {
|
|
639
651
|
...e.integrations.custom,
|
|
@@ -645,12 +657,12 @@ const os = () => {
|
|
|
645
657
|
cooldownPeriod: e.viewport.cooldownPeriod ?? 6e4,
|
|
646
658
|
maxTrackedElements: e.viewport.maxTrackedElements ?? 100
|
|
647
659
|
}), e;
|
|
648
|
-
},
|
|
660
|
+
}, Le = (r, e = /* @__PURE__ */ new Set()) => {
|
|
649
661
|
if (r == null)
|
|
650
662
|
return !0;
|
|
651
663
|
const t = typeof r;
|
|
652
|
-
return t === "string" || t === "number" || t === "boolean" ? !0 : t === "function" || t === "symbol" || t === "bigint" || e.has(r) ? !1 : (e.add(r), Array.isArray(r) ? r.every((s) =>
|
|
653
|
-
}, ms = (r) => typeof r != "object" || r === null ? !1 :
|
|
664
|
+
return t === "string" || t === "number" || t === "boolean" ? !0 : t === "function" || t === "symbol" || t === "bigint" || e.has(r) ? !1 : (e.add(r), Array.isArray(r) ? r.every((s) => Le(s, e)) : t === "object" ? Object.values(r).every((s) => Le(s, e)) : !1);
|
|
665
|
+
}, ms = (r) => typeof r != "object" || r === null ? !1 : Le(r), ht = (r) => {
|
|
654
666
|
if (typeof r != "object" || r === null || Array.isArray(r)) return;
|
|
655
667
|
const e = {};
|
|
656
668
|
for (const [t, s] of Object.entries(r))
|
|
@@ -672,49 +684,49 @@ const os = () => {
|
|
|
672
684
|
valid: !1,
|
|
673
685
|
error: "Event name cannot be a reserved word"
|
|
674
686
|
} : { valid: !0 }, Je = (r, e, t) => {
|
|
675
|
-
const s = cs(e),
|
|
687
|
+
const s = cs(e), n = t && t === "customEvent" ? `${t} "${r}" metadata error` : `${r} metadata error`;
|
|
676
688
|
if (!ms(s))
|
|
677
689
|
return {
|
|
678
690
|
valid: !1,
|
|
679
|
-
error: `${
|
|
691
|
+
error: `${n}: object has invalid types. Valid types are string, number, boolean or string arrays.`
|
|
680
692
|
};
|
|
681
|
-
let
|
|
693
|
+
let i;
|
|
682
694
|
try {
|
|
683
|
-
|
|
695
|
+
i = JSON.stringify(s);
|
|
684
696
|
} catch {
|
|
685
697
|
return {
|
|
686
698
|
valid: !1,
|
|
687
|
-
error: `${
|
|
699
|
+
error: `${n}: object contains circular references or cannot be serialized.`
|
|
688
700
|
};
|
|
689
701
|
}
|
|
690
|
-
if (new TextEncoder().encode(
|
|
702
|
+
if (new TextEncoder().encode(i).byteLength > 49152)
|
|
691
703
|
return {
|
|
692
704
|
valid: !1,
|
|
693
|
-
error: `${
|
|
705
|
+
error: `${n}: object is too large (max ${49152 / 1024} KB).`
|
|
694
706
|
};
|
|
695
707
|
if (Object.keys(s).length > 100)
|
|
696
708
|
return {
|
|
697
709
|
valid: !1,
|
|
698
|
-
error: `${
|
|
710
|
+
error: `${n}: object has too many keys (max 100 keys).`
|
|
699
711
|
};
|
|
700
|
-
for (const [
|
|
701
|
-
if (Array.isArray(
|
|
702
|
-
if (
|
|
712
|
+
for (const [d, c] of Object.entries(s)) {
|
|
713
|
+
if (Array.isArray(c)) {
|
|
714
|
+
if (c.length > 500)
|
|
703
715
|
return {
|
|
704
716
|
valid: !1,
|
|
705
|
-
error: `${
|
|
717
|
+
error: `${n}: array property "${d}" is too large (max 500 items).`
|
|
706
718
|
};
|
|
707
|
-
for (const f of
|
|
719
|
+
for (const f of c)
|
|
708
720
|
if (typeof f == "string" && f.length > 500)
|
|
709
721
|
return {
|
|
710
722
|
valid: !1,
|
|
711
|
-
error: `${
|
|
723
|
+
error: `${n}: array property "${d}" contains strings that are too long (max 500 characters).`
|
|
712
724
|
};
|
|
713
725
|
}
|
|
714
|
-
if (typeof
|
|
726
|
+
if (typeof c == "string" && c.length > 1e3)
|
|
715
727
|
return {
|
|
716
728
|
valid: !1,
|
|
717
|
-
error: `${
|
|
729
|
+
error: `${n}: property "${d}" is too long (max 1000 characters).`
|
|
718
730
|
};
|
|
719
731
|
}
|
|
720
732
|
return {
|
|
@@ -723,19 +735,19 @@ const os = () => {
|
|
|
723
735
|
};
|
|
724
736
|
}, ft = (r, e, t) => {
|
|
725
737
|
if (Array.isArray(e)) {
|
|
726
|
-
const s = [],
|
|
727
|
-
for (let
|
|
728
|
-
const o = e[
|
|
738
|
+
const s = [], n = t && t === "customEvent" ? `${t} "${r}" metadata error` : `${r} metadata error`;
|
|
739
|
+
for (let i = 0; i < e.length; i++) {
|
|
740
|
+
const o = e[i];
|
|
729
741
|
if (typeof o != "object" || o === null || Array.isArray(o))
|
|
730
742
|
return {
|
|
731
743
|
valid: !1,
|
|
732
|
-
error: `${
|
|
744
|
+
error: `${n}: array item at index ${i} must be an object.`
|
|
733
745
|
};
|
|
734
746
|
const l = Je(r, o, t);
|
|
735
747
|
if (!l.valid)
|
|
736
748
|
return {
|
|
737
749
|
valid: !1,
|
|
738
|
-
error: `${
|
|
750
|
+
error: `${n}: array item at index ${i} is invalid: ${l.error}`
|
|
739
751
|
};
|
|
740
752
|
l.sanitizedMetadata && s.push(l.sanitizedMetadata);
|
|
741
753
|
}
|
|
@@ -745,7 +757,7 @@ const os = () => {
|
|
|
745
757
|
};
|
|
746
758
|
}
|
|
747
759
|
return Je(r, e, t);
|
|
748
|
-
},
|
|
760
|
+
}, ps = (r, e) => {
|
|
749
761
|
const t = gs(r);
|
|
750
762
|
if (!t.valid)
|
|
751
763
|
return a("error", "Event name validation failed", {
|
|
@@ -761,7 +773,7 @@ const os = () => {
|
|
|
761
773
|
}
|
|
762
774
|
}), s;
|
|
763
775
|
};
|
|
764
|
-
class
|
|
776
|
+
class Es {
|
|
765
777
|
listeners = /* @__PURE__ */ new Map();
|
|
766
778
|
/**
|
|
767
779
|
* Subscribes to an event channel
|
|
@@ -814,8 +826,8 @@ class ps {
|
|
|
814
826
|
off(e, t) {
|
|
815
827
|
const s = this.listeners.get(e);
|
|
816
828
|
if (s) {
|
|
817
|
-
const
|
|
818
|
-
|
|
829
|
+
const n = s.indexOf(t);
|
|
830
|
+
n > -1 && s.splice(n, 1);
|
|
819
831
|
}
|
|
820
832
|
}
|
|
821
833
|
/**
|
|
@@ -848,8 +860,8 @@ class ps {
|
|
|
848
860
|
*/
|
|
849
861
|
emit(e, t) {
|
|
850
862
|
const s = this.listeners.get(e);
|
|
851
|
-
s && s.forEach((
|
|
852
|
-
|
|
863
|
+
s && s.forEach((n) => {
|
|
864
|
+
n(t);
|
|
853
865
|
});
|
|
854
866
|
}
|
|
855
867
|
/**
|
|
@@ -1016,10 +1028,10 @@ class Ze extends _ {
|
|
|
1016
1028
|
* @param customHeadersProvider - Optional callback for dynamic headers
|
|
1017
1029
|
* @throws Error if integrationId and apiUrl are not both provided or both undefined
|
|
1018
1030
|
*/
|
|
1019
|
-
constructor(e, t, s,
|
|
1031
|
+
constructor(e, t, s, n = {}, i = {}, o, l = "include") {
|
|
1020
1032
|
if (super(), t && !s || !t && s)
|
|
1021
1033
|
throw new Error("SenderManager: integrationId and apiUrl must either both be provided or both be undefined");
|
|
1022
|
-
this.storeManager = e, this.integrationId = t, this.apiUrl = s, this.transformers =
|
|
1034
|
+
this.storeManager = e, this.integrationId = t, this.apiUrl = s, this.transformers = n, this.staticHeaders = i, this.customHeadersProvider = o, this.fetchCredentials = l, this.rateLimitedUntil = this.loadRateLimitCooldown();
|
|
1023
1035
|
}
|
|
1024
1036
|
/**
|
|
1025
1037
|
* Get the integration ID for this sender
|
|
@@ -1100,8 +1112,8 @@ class Ze extends _ {
|
|
|
1100
1112
|
try {
|
|
1101
1113
|
const s = this.storeManager.getItem(t);
|
|
1102
1114
|
if (s) {
|
|
1103
|
-
const
|
|
1104
|
-
if (Number.isFinite(
|
|
1115
|
+
const n = Number(s);
|
|
1116
|
+
if (Number.isFinite(n) && n >= e)
|
|
1105
1117
|
return;
|
|
1106
1118
|
}
|
|
1107
1119
|
this.storeManager.setItem(t, String(e));
|
|
@@ -1181,8 +1193,8 @@ class Ze extends _ {
|
|
|
1181
1193
|
}
|
|
1182
1194
|
}
|
|
1183
1195
|
);
|
|
1184
|
-
const t = this.ensureBatchMetadata(e), s = this.getPersistedData(),
|
|
1185
|
-
return this.persistEventsWithFailureCount(t,
|
|
1196
|
+
const t = this.ensureBatchMetadata(e), s = this.getPersistedData(), n = typeof s?.recoveryFailures == "number" && Number.isFinite(s.recoveryFailures) ? s.recoveryFailures : 0;
|
|
1197
|
+
return this.persistEventsWithFailureCount(t, n, !0), !1;
|
|
1186
1198
|
}
|
|
1187
1199
|
return this.apiUrl?.includes($.Fail) ? (a(
|
|
1188
1200
|
"warn",
|
|
@@ -1231,10 +1243,10 @@ class Ze extends _ {
|
|
|
1231
1243
|
async sendEventsQueue(e, t) {
|
|
1232
1244
|
const s = this.ensureBatchMetadata(e);
|
|
1233
1245
|
try {
|
|
1234
|
-
const
|
|
1235
|
-
return
|
|
1236
|
-
} catch (
|
|
1237
|
-
return
|
|
1246
|
+
const n = await this.send(s);
|
|
1247
|
+
return n ? (this.clearPersistedEvents(), t?.onSuccess?.(s.events.length, s.events, s)) : (this.persistEvents(s), t?.onFailure?.()), n;
|
|
1248
|
+
} catch (n) {
|
|
1249
|
+
return n instanceof O ? (this.logPermanentError("Permanent error, not retrying", n), this.clearPersistedEvents(), t?.onFailure?.(), !1) : (this.persistEvents(s), t?.onFailure?.(), !1);
|
|
1238
1250
|
}
|
|
1239
1251
|
}
|
|
1240
1252
|
/**
|
|
@@ -1294,13 +1306,13 @@ class Ze extends _ {
|
|
|
1294
1306
|
this.recoveryInProgress = !0;
|
|
1295
1307
|
let t = null, s = 0;
|
|
1296
1308
|
try {
|
|
1297
|
-
const
|
|
1298
|
-
if (!
|
|
1309
|
+
const n = this.getPersistedData();
|
|
1310
|
+
if (!n || !this.isDataRecent(n) || n.events.length === 0) {
|
|
1299
1311
|
this.clearPersistedEvents();
|
|
1300
1312
|
return;
|
|
1301
1313
|
}
|
|
1302
|
-
const
|
|
1303
|
-
if (s = typeof
|
|
1314
|
+
const i = n.recoveryFailures;
|
|
1315
|
+
if (s = typeof i == "number" && Number.isFinite(i) && i >= 0 ? i : 0, s >= 3) {
|
|
1304
1316
|
a(
|
|
1305
1317
|
"debug",
|
|
1306
1318
|
`Discarding persisted events after ${s} failed recovery attempts${this.integrationId ? ` [${this.integrationId}]` : ""}`
|
|
@@ -1317,13 +1329,13 @@ class Ze extends _ {
|
|
|
1317
1329
|
), e?.onFailure?.();
|
|
1318
1330
|
return;
|
|
1319
1331
|
}
|
|
1320
|
-
t = this.ensureBatchMetadata(this.createRecoveryBody(
|
|
1321
|
-
} catch (
|
|
1322
|
-
if (
|
|
1323
|
-
this.logPermanentError("Permanent error during recovery, clearing persisted events",
|
|
1332
|
+
t = this.ensureBatchMetadata(this.createRecoveryBody(n)), await this.send(t) ? (this.clearPersistedEvents(), e?.onSuccess?.(n.events.length, n.events, t)) : (this.persistEventsWithFailureCount(t, s + 1, !0), e?.onFailure?.());
|
|
1333
|
+
} catch (n) {
|
|
1334
|
+
if (n instanceof O) {
|
|
1335
|
+
this.logPermanentError("Permanent error during recovery, clearing persisted events", n), this.clearPersistedEvents(), e?.onFailure?.();
|
|
1324
1336
|
return;
|
|
1325
1337
|
}
|
|
1326
|
-
a("error", "Failed to recover persisted events", { error:
|
|
1338
|
+
a("error", "Failed to recover persisted events", { error: n }), t && this.persistEventsWithFailureCount(t, s + 1, !0), e?.onFailure?.();
|
|
1327
1339
|
} finally {
|
|
1328
1340
|
this.recoveryInProgress = !1;
|
|
1329
1341
|
}
|
|
@@ -1440,8 +1452,8 @@ class Ze extends _ {
|
|
|
1440
1452
|
* @returns Promise that resolves after calculated delay
|
|
1441
1453
|
*/
|
|
1442
1454
|
async backoffDelay(e) {
|
|
1443
|
-
const t = 100 * Math.pow(2, e), s = Math.random() * 100,
|
|
1444
|
-
return new Promise((
|
|
1455
|
+
const t = 100 * Math.pow(2, e), s = Math.random() * 100, n = t + s;
|
|
1456
|
+
return new Promise((i) => setTimeout(i, n));
|
|
1445
1457
|
}
|
|
1446
1458
|
/**
|
|
1447
1459
|
* Sends event queue with automatic retry logic for transient failures.
|
|
@@ -1486,76 +1498,76 @@ class Ze extends _ {
|
|
|
1486
1498
|
const s = this.applyBeforeBatchTransformer(t);
|
|
1487
1499
|
if (!s)
|
|
1488
1500
|
return !0;
|
|
1489
|
-
const
|
|
1501
|
+
const n = this.ensureBatchMetadata(s, e._metadata?.idempotency_token);
|
|
1490
1502
|
if (this.apiUrl?.includes($.Fail))
|
|
1491
1503
|
return a("debug", `Fail mode: simulating network failure${this.integrationId ? ` [${this.integrationId}]` : ""}`, {
|
|
1492
|
-
data: { events:
|
|
1504
|
+
data: { events: n.events.length }
|
|
1493
1505
|
}), !1;
|
|
1494
1506
|
if (this.apiUrl?.includes($.Localhost))
|
|
1495
1507
|
return a("debug", `Success mode: simulating successful send${this.integrationId ? ` [${this.integrationId}]` : ""}`, {
|
|
1496
|
-
data: { events:
|
|
1508
|
+
data: { events: n.events.length }
|
|
1497
1509
|
}), !0;
|
|
1498
1510
|
if (this.isRateLimited())
|
|
1499
1511
|
return a("debug", `Rate-limit cooldown active, skipping send${this.integrationId ? ` [${this.integrationId}]` : ""}`, {
|
|
1500
1512
|
data: {
|
|
1501
1513
|
cooldownRemainingMs: this.rateLimitedUntil - Date.now(),
|
|
1502
|
-
events:
|
|
1514
|
+
events: n.events.length
|
|
1503
1515
|
}
|
|
1504
1516
|
}), !1;
|
|
1505
1517
|
if (this.consecutiveNetworkFailures >= 3) {
|
|
1506
|
-
const
|
|
1507
|
-
if (
|
|
1518
|
+
const c = Date.now() - this.circuitOpenedAt;
|
|
1519
|
+
if (c < 12e4)
|
|
1508
1520
|
return a("debug", `Network circuit open, skipping send${this.integrationId ? ` [${this.integrationId}]` : ""}`, {
|
|
1509
1521
|
data: {
|
|
1510
1522
|
consecutiveNetworkFailures: this.consecutiveNetworkFailures,
|
|
1511
|
-
cooldownRemainingMs: 12e4 -
|
|
1523
|
+
cooldownRemainingMs: 12e4 - c
|
|
1512
1524
|
}
|
|
1513
1525
|
}), !1;
|
|
1514
1526
|
}
|
|
1515
|
-
const { url:
|
|
1516
|
-
let l = !0,
|
|
1517
|
-
for (let
|
|
1527
|
+
const { url: i, payload: o } = this.prepareRequest(n);
|
|
1528
|
+
let l = !0, d = !1;
|
|
1529
|
+
for (let c = 1; c <= 3; c++)
|
|
1518
1530
|
try {
|
|
1519
|
-
return (await this.sendWithTimeout(
|
|
1531
|
+
return (await this.sendWithTimeout(i, o)).ok ? (c > 1 && a(
|
|
1520
1532
|
"info",
|
|
1521
|
-
`Send succeeded after ${
|
|
1533
|
+
`Send succeeded after ${c - 1} retry attempt(s)${this.integrationId ? ` [${this.integrationId}]` : ""}`,
|
|
1522
1534
|
{
|
|
1523
|
-
data: { events:
|
|
1535
|
+
data: { events: n.events.length, attempt: c }
|
|
1524
1536
|
}
|
|
1525
1537
|
), this.consecutiveNetworkFailures = 0, this.circuitOpenedAt = 0, !0) : !1;
|
|
1526
1538
|
} catch (f) {
|
|
1527
|
-
const
|
|
1539
|
+
const m = c === 3;
|
|
1528
1540
|
if (f instanceof O)
|
|
1529
1541
|
throw this.consecutiveNetworkFailures = 0, this.circuitOpenedAt = 0, f;
|
|
1530
1542
|
if (f instanceof re) {
|
|
1531
|
-
this.consecutiveNetworkFailures = 0, this.circuitOpenedAt = 0, l = !1,
|
|
1532
|
-
data: { events: e.events.length, attempt:
|
|
1543
|
+
this.consecutiveNetworkFailures = 0, this.circuitOpenedAt = 0, l = !1, d = !0, this.armRateLimitCooldown(Date.now() + 6e4), a("warn", `Rate limited, skipping retries${this.integrationId ? ` [${this.integrationId}]` : ""}`, {
|
|
1544
|
+
data: { events: e.events.length, attempt: c, cooldownMs: 6e4 }
|
|
1533
1545
|
});
|
|
1534
1546
|
break;
|
|
1535
1547
|
}
|
|
1536
|
-
if (f instanceof
|
|
1537
|
-
|
|
1538
|
-
`Send attempt ${
|
|
1548
|
+
if (f instanceof ne || (l = !1), f instanceof TypeError || (d = !0), a(
|
|
1549
|
+
m ? "error" : "warn",
|
|
1550
|
+
`Send attempt ${c} failed${this.integrationId ? ` [${this.integrationId}]` : ""}${m ? " (all retries exhausted)" : ", will retry"}`,
|
|
1539
1551
|
{
|
|
1540
1552
|
error: f,
|
|
1541
1553
|
data: {
|
|
1542
1554
|
events: e.events.length,
|
|
1543
|
-
url:
|
|
1544
|
-
attempt:
|
|
1555
|
+
url: i.replace(/\/\/[^/]+/, "//[DOMAIN]"),
|
|
1556
|
+
attempt: c,
|
|
1545
1557
|
maxAttempts: 3
|
|
1546
1558
|
}
|
|
1547
1559
|
}
|
|
1548
|
-
), !
|
|
1549
|
-
await this.backoffDelay(
|
|
1560
|
+
), !m) {
|
|
1561
|
+
await this.backoffDelay(c);
|
|
1550
1562
|
continue;
|
|
1551
1563
|
}
|
|
1552
1564
|
return l ? (a(
|
|
1553
1565
|
"debug",
|
|
1554
1566
|
`All retry attempts timed out, preserving batch for retry${this.integrationId ? ` [${this.integrationId}]` : ""}`,
|
|
1555
1567
|
{
|
|
1556
|
-
data: { events:
|
|
1568
|
+
data: { events: n.events.length }
|
|
1557
1569
|
}
|
|
1558
|
-
), !1) : (
|
|
1570
|
+
), !1) : (d ? (this.consecutiveNetworkFailures = 0, this.circuitOpenedAt = 0) : (this.consecutiveNetworkFailures = Math.min(
|
|
1559
1571
|
this.consecutiveNetworkFailures + 1,
|
|
1560
1572
|
3
|
|
1561
1573
|
), this.consecutiveNetworkFailures >= 3 && (this.circuitOpenedAt = Date.now())), !1);
|
|
@@ -1588,9 +1600,9 @@ class Ze extends _ {
|
|
|
1588
1600
|
async sendWithTimeout(e, t) {
|
|
1589
1601
|
const s = new AbortController();
|
|
1590
1602
|
this.pendingControllers.add(s);
|
|
1591
|
-
let
|
|
1592
|
-
const
|
|
1593
|
-
|
|
1603
|
+
let n = !1;
|
|
1604
|
+
const i = setTimeout(() => {
|
|
1605
|
+
n = !0, s.abort();
|
|
1594
1606
|
}, 15e3);
|
|
1595
1607
|
try {
|
|
1596
1608
|
const o = this.getCustomHeaders(), l = await fetch(e, {
|
|
@@ -1606,16 +1618,16 @@ class Ze extends _ {
|
|
|
1606
1618
|
});
|
|
1607
1619
|
if (!l.ok) {
|
|
1608
1620
|
if (l.status >= 400 && l.status < 500 && l.status !== 408 && l.status !== 429) {
|
|
1609
|
-
const
|
|
1610
|
-
throw new O(f, l.status,
|
|
1621
|
+
const c = await this.readTraceLogErrorCode(l), f = c ? `HTTP ${l.status}: ${l.statusText} (${c})` : `HTTP ${l.status}: ${l.statusText}`;
|
|
1622
|
+
throw new O(f, l.status, c);
|
|
1611
1623
|
}
|
|
1612
1624
|
throw l.status === 429 ? new re(`HTTP 429: ${l.statusText}`) : new Error(`HTTP ${l.status}: ${l.statusText}`);
|
|
1613
1625
|
}
|
|
1614
1626
|
return l;
|
|
1615
1627
|
} catch (o) {
|
|
1616
|
-
throw o instanceof O ? o :
|
|
1628
|
+
throw o instanceof O ? o : n ? new ne("Request timed out") : o;
|
|
1617
1629
|
} finally {
|
|
1618
|
-
clearTimeout(
|
|
1630
|
+
clearTimeout(i), this.pendingControllers.delete(s);
|
|
1619
1631
|
}
|
|
1620
1632
|
}
|
|
1621
1633
|
/**
|
|
@@ -1633,7 +1645,7 @@ class Ze extends _ {
|
|
|
1633
1645
|
async readTraceLogErrorCode(e) {
|
|
1634
1646
|
try {
|
|
1635
1647
|
const t = await e.clone().json();
|
|
1636
|
-
if (typeof t.code == "string" && t.code.length > 0 && t.code.length <=
|
|
1648
|
+
if (typeof t.code == "string" && t.code.length > 0 && t.code.length <= zt)
|
|
1637
1649
|
return t.code;
|
|
1638
1650
|
} catch {
|
|
1639
1651
|
}
|
|
@@ -1662,10 +1674,10 @@ class Ze extends _ {
|
|
|
1662
1674
|
const t = this.ensureBatchMetadata(e), s = this.applyBeforeSendTransformer(t);
|
|
1663
1675
|
if (!s)
|
|
1664
1676
|
return !0;
|
|
1665
|
-
const
|
|
1666
|
-
if (!
|
|
1677
|
+
const n = this.applyBeforeBatchTransformer(s);
|
|
1678
|
+
if (!n)
|
|
1667
1679
|
return !0;
|
|
1668
|
-
const
|
|
1680
|
+
const i = this.ensureBatchMetadata(n, t._metadata?.idempotency_token), { url: o, payload: l } = this.prepareRequest(i);
|
|
1669
1681
|
if (l.length > 65536)
|
|
1670
1682
|
return a(
|
|
1671
1683
|
"warn",
|
|
@@ -1674,21 +1686,21 @@ class Ze extends _ {
|
|
|
1674
1686
|
data: {
|
|
1675
1687
|
size: l.length,
|
|
1676
1688
|
limit: 65536,
|
|
1677
|
-
events:
|
|
1689
|
+
events: i.events.length
|
|
1678
1690
|
}
|
|
1679
1691
|
}
|
|
1680
1692
|
), this.persistEvents(t), !1;
|
|
1681
|
-
const
|
|
1693
|
+
const d = new Blob([l], { type: "application/json" });
|
|
1682
1694
|
if (!this.isSendBeaconAvailable())
|
|
1683
1695
|
return a(
|
|
1684
1696
|
"warn",
|
|
1685
1697
|
`sendBeacon not available, persisting events for recovery${this.integrationId ? ` [${this.integrationId}]` : ""}`
|
|
1686
1698
|
), this.persistEvents(t), !1;
|
|
1687
|
-
const
|
|
1688
|
-
return
|
|
1699
|
+
const c = navigator.sendBeacon(o, d);
|
|
1700
|
+
return c || (a(
|
|
1689
1701
|
"warn",
|
|
1690
1702
|
`sendBeacon rejected request, persisting events for recovery${this.integrationId ? ` [${this.integrationId}]` : ""}`
|
|
1691
|
-
), this.persistEvents(t)),
|
|
1703
|
+
), this.persistEvents(t)), c;
|
|
1692
1704
|
}
|
|
1693
1705
|
/**
|
|
1694
1706
|
* Prepares request by enriching payload with metadata and serializing to JSON.
|
|
@@ -1756,11 +1768,11 @@ class Ze extends _ {
|
|
|
1756
1768
|
* @private
|
|
1757
1769
|
*/
|
|
1758
1770
|
computeContentToken(e) {
|
|
1759
|
-
const t = e.events.map((
|
|
1760
|
-
let
|
|
1761
|
-
for (let
|
|
1762
|
-
|
|
1763
|
-
return
|
|
1771
|
+
const t = e.events.map((i) => i.id).sort().join(","), s = `${e.user_id}|${e.session_id}|${t}`;
|
|
1772
|
+
let n = 2166136261;
|
|
1773
|
+
for (let i = 0; i < s.length; i++)
|
|
1774
|
+
n ^= s.charCodeAt(i), n = Math.imul(n, 16777619) >>> 0;
|
|
1775
|
+
return n.toString(16).padStart(8, "0");
|
|
1764
1776
|
}
|
|
1765
1777
|
/**
|
|
1766
1778
|
* Retrieves persisted events from localStorage with error recovery.
|
|
@@ -1810,8 +1822,8 @@ class Ze extends _ {
|
|
|
1810
1822
|
* @private
|
|
1811
1823
|
*/
|
|
1812
1824
|
createRecoveryBody(e) {
|
|
1813
|
-
const { timestamp: t, recoveryFailures: s, ...
|
|
1814
|
-
return
|
|
1825
|
+
const { timestamp: t, recoveryFailures: s, ...n } = e;
|
|
1826
|
+
return n;
|
|
1815
1827
|
}
|
|
1816
1828
|
/**
|
|
1817
1829
|
* Persists failed events to localStorage for next-page-load recovery.
|
|
@@ -1850,9 +1862,9 @@ class Ze extends _ {
|
|
|
1850
1862
|
*/
|
|
1851
1863
|
persistEventsWithFailureCount(e, t, s = !1) {
|
|
1852
1864
|
try {
|
|
1853
|
-
const
|
|
1854
|
-
if (!s &&
|
|
1855
|
-
const l = Date.now() -
|
|
1865
|
+
const n = this.getPersistedData();
|
|
1866
|
+
if (!s && n && n.timestamp) {
|
|
1867
|
+
const l = Date.now() - n.timestamp;
|
|
1856
1868
|
if (l < 1e3)
|
|
1857
1869
|
return a(
|
|
1858
1870
|
"debug",
|
|
@@ -1862,14 +1874,14 @@ class Ze extends _ {
|
|
|
1862
1874
|
}
|
|
1863
1875
|
), !0;
|
|
1864
1876
|
}
|
|
1865
|
-
const
|
|
1877
|
+
const i = {
|
|
1866
1878
|
...e,
|
|
1867
1879
|
timestamp: Date.now(),
|
|
1868
1880
|
...t > 0 && { recoveryFailures: t }
|
|
1869
1881
|
}, o = this.getQueueStorageKey();
|
|
1870
|
-
return this.storeManager.setItem(o, JSON.stringify(
|
|
1871
|
-
} catch (
|
|
1872
|
-
return a("debug", `Failed to persist events${this.integrationId ? ` [${this.integrationId}]` : ""}`, { error:
|
|
1882
|
+
return this.storeManager.setItem(o, JSON.stringify(i)), !!this.storeManager.getItem(o);
|
|
1883
|
+
} catch (n) {
|
|
1884
|
+
return a("debug", `Failed to persist events${this.integrationId ? ` [${this.integrationId}]` : ""}`, { error: n }), !1;
|
|
1873
1885
|
}
|
|
1874
1886
|
}
|
|
1875
1887
|
clearPersistedEvents() {
|
|
@@ -1893,10 +1905,10 @@ class Ze extends _ {
|
|
|
1893
1905
|
return typeof navigator < "u" && typeof navigator.sendBeacon == "function";
|
|
1894
1906
|
}
|
|
1895
1907
|
logPermanentError(e, t) {
|
|
1896
|
-
const s = Date.now(),
|
|
1897
|
-
(!this.lastPermanentErrorLog || this.lastPermanentErrorLog.key !==
|
|
1908
|
+
const s = Date.now(), n = `${t.statusCode ?? "unknown"}:${t.responseCode ?? ""}`;
|
|
1909
|
+
(!this.lastPermanentErrorLog || this.lastPermanentErrorLog.key !== n || s - this.lastPermanentErrorLog.timestamp >= Qt) && (a("error", `${e}${this.integrationId ? ` [${this.integrationId}]` : ""}`, {
|
|
1898
1910
|
data: { status: t.statusCode, code: t.responseCode, message: t.message }
|
|
1899
|
-
}), this.lastPermanentErrorLog = { key:
|
|
1911
|
+
}), this.lastPermanentErrorLog = { key: n, timestamp: s });
|
|
1900
1912
|
}
|
|
1901
1913
|
}
|
|
1902
1914
|
class Ts extends _ {
|
|
@@ -2026,10 +2038,10 @@ class Ts extends _ {
|
|
|
2026
2038
|
* ```
|
|
2027
2039
|
*/
|
|
2028
2040
|
validateTimestamp(e) {
|
|
2029
|
-
const s = this.now(),
|
|
2030
|
-
return
|
|
2041
|
+
const s = this.now(), n = e - s;
|
|
2042
|
+
return n > 12e4 ? {
|
|
2031
2043
|
valid: !1,
|
|
2032
|
-
error: `Timestamp is ${(
|
|
2044
|
+
error: `Timestamp is ${(n / 1e3 / 60).toFixed(2)} minutes in the future (max allowed: 2 minutes)`
|
|
2033
2045
|
} : { valid: !0 };
|
|
2034
2046
|
}
|
|
2035
2047
|
/**
|
|
@@ -2048,8 +2060,8 @@ class Ts extends _ {
|
|
|
2048
2060
|
};
|
|
2049
2061
|
}
|
|
2050
2062
|
}
|
|
2051
|
-
const
|
|
2052
|
-
class
|
|
2063
|
+
const vs = new Set(Object.values(u));
|
|
2064
|
+
class Is extends _ {
|
|
2053
2065
|
dataSenders;
|
|
2054
2066
|
emitter;
|
|
2055
2067
|
transformers;
|
|
@@ -2064,6 +2076,9 @@ class vs extends _ {
|
|
|
2064
2076
|
rateLimitCounter = 0;
|
|
2065
2077
|
rateLimitWindowStart = 0;
|
|
2066
2078
|
lastSessionId = null;
|
|
2079
|
+
// Set when a sync flush is requested mid-async-send; drained by the async
|
|
2080
|
+
// finally block. See `drainPendingSyncFlush` for the full rationale.
|
|
2081
|
+
pendingSyncFlush = !1;
|
|
2067
2082
|
sessionEventCounts = {
|
|
2068
2083
|
total: 0,
|
|
2069
2084
|
[u.CLICK]: 0,
|
|
@@ -2087,7 +2102,7 @@ class vs extends _ {
|
|
|
2087
2102
|
* @param customHeadersProvider - Optional callback for dynamic headers
|
|
2088
2103
|
* @param fetchCredentials - Fetch credentials mode for custom backend. @default 'include'
|
|
2089
2104
|
*/
|
|
2090
|
-
constructor(e, t = null, s = {},
|
|
2105
|
+
constructor(e, t = null, s = {}, n = {}, i, o = "include") {
|
|
2091
2106
|
super(), this.emitter = t, this.transformers = s, this.timeManager = new Ts(), this.dataSenders = [];
|
|
2092
2107
|
const l = this.get("collectApiUrls");
|
|
2093
2108
|
l?.saas && this.dataSenders.push(new Ze(e, "saas", l.saas, s)), l?.custom && this.dataSenders.push(
|
|
@@ -2096,12 +2111,12 @@ class vs extends _ {
|
|
|
2096
2111
|
"custom",
|
|
2097
2112
|
l.custom,
|
|
2098
2113
|
s,
|
|
2099
|
-
i,
|
|
2100
2114
|
n,
|
|
2115
|
+
i,
|
|
2101
2116
|
o
|
|
2102
2117
|
)
|
|
2103
|
-
), this.saveSessionCountsDebounced = this.debounce((
|
|
2104
|
-
this.saveSessionCounts(
|
|
2118
|
+
), this.saveSessionCountsDebounced = this.debounce((d) => {
|
|
2119
|
+
this.saveSessionCounts(d);
|
|
2105
2120
|
}, 500), this.cleanupExpiredSessionCounts();
|
|
2106
2121
|
}
|
|
2107
2122
|
/**
|
|
@@ -2131,10 +2146,10 @@ class vs extends _ {
|
|
|
2131
2146
|
async recoverPersistedEvents() {
|
|
2132
2147
|
const e = this.dataSenders.map(
|
|
2133
2148
|
async (t) => t.recoverPersistedEvents({
|
|
2134
|
-
onSuccess: (s,
|
|
2135
|
-
if (
|
|
2136
|
-
const o =
|
|
2137
|
-
this.removeProcessedEvents(o),
|
|
2149
|
+
onSuccess: (s, n, i) => {
|
|
2150
|
+
if (n && n.length > 0) {
|
|
2151
|
+
const o = n.map((l) => l.id);
|
|
2152
|
+
this.removeProcessedEvents(o), i && this.emitEventsQueue(i);
|
|
2138
2153
|
}
|
|
2139
2154
|
},
|
|
2140
2155
|
onFailure: () => {
|
|
@@ -2207,68 +2222,68 @@ class vs extends _ {
|
|
|
2207
2222
|
type: e,
|
|
2208
2223
|
page_url: t,
|
|
2209
2224
|
from_page_url: s,
|
|
2210
|
-
scroll_data:
|
|
2211
|
-
click_data:
|
|
2225
|
+
scroll_data: n,
|
|
2226
|
+
click_data: i,
|
|
2212
2227
|
custom_event: o,
|
|
2213
2228
|
web_vitals: l,
|
|
2214
|
-
error_data:
|
|
2215
|
-
viewport_data:
|
|
2229
|
+
error_data: d,
|
|
2230
|
+
viewport_data: c,
|
|
2216
2231
|
page_view: f
|
|
2217
2232
|
}) {
|
|
2218
2233
|
if (!e) {
|
|
2219
2234
|
a("error", "Event type is required - event will be ignored");
|
|
2220
2235
|
return;
|
|
2221
2236
|
}
|
|
2222
|
-
if (!
|
|
2237
|
+
if (!vs.has(e)) {
|
|
2223
2238
|
a("error", "Invalid event type - event will be ignored", {
|
|
2224
2239
|
data: { type: e }
|
|
2225
2240
|
});
|
|
2226
2241
|
return;
|
|
2227
2242
|
}
|
|
2228
|
-
const
|
|
2229
|
-
if (!
|
|
2243
|
+
const m = this.get("sessionId");
|
|
2244
|
+
if (!m) {
|
|
2230
2245
|
this.pendingEventsBuffer.length >= 100 && (this.pendingEventsBuffer.shift(), a("debug", "Pending events buffer full - dropping oldest event", {
|
|
2231
2246
|
data: { maxBufferSize: 100 }
|
|
2232
2247
|
})), this.pendingEventsBuffer.push({
|
|
2233
2248
|
type: e,
|
|
2234
2249
|
page_url: t,
|
|
2235
2250
|
from_page_url: s,
|
|
2236
|
-
scroll_data:
|
|
2237
|
-
click_data:
|
|
2251
|
+
scroll_data: n,
|
|
2252
|
+
click_data: i,
|
|
2238
2253
|
custom_event: o,
|
|
2239
2254
|
web_vitals: l,
|
|
2240
|
-
error_data:
|
|
2241
|
-
viewport_data:
|
|
2255
|
+
error_data: d,
|
|
2256
|
+
viewport_data: c,
|
|
2242
2257
|
page_view: f
|
|
2243
2258
|
});
|
|
2244
2259
|
return;
|
|
2245
2260
|
}
|
|
2246
|
-
this.lastSessionId !==
|
|
2247
|
-
const
|
|
2248
|
-
if (
|
|
2249
|
-
data: { sessionId:
|
|
2250
|
-
}), !
|
|
2261
|
+
this.lastSessionId !== m && (this.lastSessionId = m, this.sessionEventCounts = this.loadSessionCounts(m));
|
|
2262
|
+
const g = e === u.SESSION_START;
|
|
2263
|
+
if (g && a("debug", "Processing SESSION_START event", {
|
|
2264
|
+
data: { sessionId: m }
|
|
2265
|
+
}), !g && !this.checkRateLimit())
|
|
2251
2266
|
return;
|
|
2252
|
-
const
|
|
2253
|
-
if (!
|
|
2267
|
+
const E = e;
|
|
2268
|
+
if (!g) {
|
|
2254
2269
|
if (this.sessionEventCounts.total >= 1e3) {
|
|
2255
2270
|
a("warn", "Session event limit reached", {
|
|
2256
2271
|
data: {
|
|
2257
|
-
type:
|
|
2272
|
+
type: E,
|
|
2258
2273
|
total: this.sessionEventCounts.total,
|
|
2259
2274
|
limit: 1e3
|
|
2260
2275
|
}
|
|
2261
2276
|
});
|
|
2262
2277
|
return;
|
|
2263
2278
|
}
|
|
2264
|
-
const v = this.getTypeLimitForEvent(
|
|
2279
|
+
const v = this.getTypeLimitForEvent(E);
|
|
2265
2280
|
if (v) {
|
|
2266
|
-
const
|
|
2267
|
-
if (
|
|
2281
|
+
const fe = this.sessionEventCounts[E];
|
|
2282
|
+
if (fe !== void 0 && fe >= v) {
|
|
2268
2283
|
a("warn", "Session event type limit reached", {
|
|
2269
2284
|
data: {
|
|
2270
|
-
type:
|
|
2271
|
-
count:
|
|
2285
|
+
type: E,
|
|
2286
|
+
count: fe,
|
|
2272
2287
|
limit: v
|
|
2273
2288
|
}
|
|
2274
2289
|
});
|
|
@@ -2276,25 +2291,25 @@ class vs extends _ {
|
|
|
2276
2291
|
}
|
|
2277
2292
|
}
|
|
2278
2293
|
}
|
|
2279
|
-
if (
|
|
2294
|
+
if (E === u.CUSTOM && o?.name) {
|
|
2280
2295
|
const v = this.get("config")?.maxSameEventPerMinute ?? 60;
|
|
2281
2296
|
if (!this.checkPerEventRateLimit(o.name, v))
|
|
2282
2297
|
return;
|
|
2283
2298
|
}
|
|
2284
|
-
const
|
|
2285
|
-
type:
|
|
2286
|
-
page_url:
|
|
2299
|
+
const he = E === u.SESSION_START, z = t || this.get("pageUrl"), U = this.buildEventPayload({
|
|
2300
|
+
type: E,
|
|
2301
|
+
page_url: z,
|
|
2287
2302
|
from_page_url: s,
|
|
2288
|
-
scroll_data:
|
|
2289
|
-
click_data:
|
|
2303
|
+
scroll_data: n,
|
|
2304
|
+
click_data: i,
|
|
2290
2305
|
custom_event: o,
|
|
2291
2306
|
web_vitals: l,
|
|
2292
|
-
error_data:
|
|
2293
|
-
viewport_data:
|
|
2307
|
+
error_data: d,
|
|
2308
|
+
viewport_data: c,
|
|
2294
2309
|
page_view: f
|
|
2295
2310
|
});
|
|
2296
|
-
if (
|
|
2297
|
-
if (
|
|
2311
|
+
if (U && !(!g && !this.shouldSample())) {
|
|
2312
|
+
if (he) {
|
|
2298
2313
|
const v = this.get("sessionId");
|
|
2299
2314
|
if (!v) {
|
|
2300
2315
|
a("error", "Session start event requires sessionId - event will be ignored");
|
|
@@ -2308,35 +2323,35 @@ class vs extends _ {
|
|
|
2308
2323
|
}
|
|
2309
2324
|
this.set("hasStartSession", !0);
|
|
2310
2325
|
}
|
|
2311
|
-
if (!this.isDuplicateEvent(
|
|
2312
|
-
if (this.get("mode") ===
|
|
2313
|
-
if (
|
|
2326
|
+
if (!this.isDuplicateEvent(U)) {
|
|
2327
|
+
if (this.get("mode") === ie.QA) {
|
|
2328
|
+
if (E === u.CUSTOM && o) {
|
|
2314
2329
|
a("info", `Custom Event: ${o.name}`, {
|
|
2315
2330
|
visibility: "qa",
|
|
2316
2331
|
data: {
|
|
2317
2332
|
name: o.name,
|
|
2318
2333
|
...o.metadata && { metadata: o.metadata }
|
|
2319
2334
|
}
|
|
2320
|
-
}), this.emitEvent(
|
|
2335
|
+
}), this.emitEvent(U);
|
|
2321
2336
|
return;
|
|
2322
2337
|
}
|
|
2323
|
-
if (
|
|
2324
|
-
const v =
|
|
2338
|
+
if (E === u.VIEWPORT_VISIBLE && c) {
|
|
2339
|
+
const v = c.name || c.id || c.selector;
|
|
2325
2340
|
a("info", `Viewport Visible: ${v}`, {
|
|
2326
2341
|
visibility: "qa",
|
|
2327
2342
|
data: {
|
|
2328
|
-
selector:
|
|
2329
|
-
...
|
|
2330
|
-
...
|
|
2331
|
-
visibilityRatio:
|
|
2332
|
-
dwellTime:
|
|
2343
|
+
selector: c.selector,
|
|
2344
|
+
...c.name && { name: c.name },
|
|
2345
|
+
...c.id && { id: c.id },
|
|
2346
|
+
visibilityRatio: c.visibilityRatio,
|
|
2347
|
+
dwellTime: c.dwellTime
|
|
2333
2348
|
}
|
|
2334
|
-
}), this.emitEvent(
|
|
2349
|
+
}), this.emitEvent(U);
|
|
2335
2350
|
return;
|
|
2336
2351
|
}
|
|
2337
2352
|
}
|
|
2338
|
-
if (this.addToQueue(
|
|
2339
|
-
this.sessionEventCounts.total++, this.sessionEventCounts[
|
|
2353
|
+
if (this.addToQueue(U), !g) {
|
|
2354
|
+
this.sessionEventCounts.total++, this.sessionEventCounts[E] !== void 0 && this.sessionEventCounts[E]++;
|
|
2340
2355
|
const v = this.get("sessionId");
|
|
2341
2356
|
v && this.saveSessionCountsDebounced && this.saveSessionCountsDebounced(v);
|
|
2342
2357
|
}
|
|
@@ -2378,7 +2393,7 @@ class vs extends _ {
|
|
|
2378
2393
|
* @see src/managers/README.md (lines 5-75) for cleanup details
|
|
2379
2394
|
*/
|
|
2380
2395
|
stop() {
|
|
2381
|
-
this.clearSendTimeout(), this.sendInProgress = !1, this.consecutiveSendFailures = 0;
|
|
2396
|
+
this.clearSendTimeout(), this.sendInProgress = !1, this.pendingSyncFlush = !1, this.consecutiveSendFailures = 0;
|
|
2382
2397
|
const e = this.get("sessionId");
|
|
2383
2398
|
e && this.saveSessionCounts(e), this.eventsQueue = [], this.pendingEventsBuffer = [], this.recentEventFingerprints.clear(), this.rateLimitCounter = 0, this.rateLimitWindowStart = 0, this.perEventRateLimits.clear(), this.sessionEventCounts = {
|
|
2384
2399
|
total: 0,
|
|
@@ -2465,6 +2480,62 @@ class vs extends _ {
|
|
|
2465
2480
|
flushImmediatelySync() {
|
|
2466
2481
|
return this.flushEvents(!0);
|
|
2467
2482
|
}
|
|
2483
|
+
/**
|
|
2484
|
+
* Sends ONLY the most recently queued event via `navigator.sendBeacon()` in
|
|
2485
|
+
* a dedicated single-event batch.
|
|
2486
|
+
*
|
|
2487
|
+
* **Purpose**: Guarantee delivery of an event that *must* survive an
|
|
2488
|
+
* imminent page unload (purchase confirmation, signup completion, etc.),
|
|
2489
|
+
* independent of the main queue's size or in-flight async send state.
|
|
2490
|
+
*
|
|
2491
|
+
* **Why a dedicated batch**: `flushImmediatelySync()` serialises the entire
|
|
2492
|
+
* queue into one `sendBeacon` call. If the queue is heavy (>64KB) the
|
|
2493
|
+
* beacon fails and the batch is persisted to `localStorage`, which is only
|
|
2494
|
+
* recovered on the next `init()` — useless for one-shot conversion events
|
|
2495
|
+
* where the user never returns.
|
|
2496
|
+
*
|
|
2497
|
+
* **Behaviour**:
|
|
2498
|
+
* - Reads the last entry of `eventsQueue` (the just-tracked event).
|
|
2499
|
+
* - Wraps it in its own `EventsQueue` and dispatches synchronously through
|
|
2500
|
+
* every `SenderManager` via `sendEventsQueueSync()`.
|
|
2501
|
+
* - Leaves the main queue untouched; the same event will be re-delivered by
|
|
2502
|
+
* the next periodic / unload flush. Idempotency is the caller-side
|
|
2503
|
+
* contract: the backend MUST deduplicate by `event.id` (e.g. unique index
|
|
2504
|
+
* on the ingestion collection) — same guarantee the library already
|
|
2505
|
+
* relies on for the persisted-events recovery path.
|
|
2506
|
+
*
|
|
2507
|
+
* **Use it after** `track()` so the event is in the queue. Caller is
|
|
2508
|
+
* responsible for verifying that `track()` actually queued the event
|
|
2509
|
+
* (it can be dropped by rate limiting / sampling / `beforeSend`).
|
|
2510
|
+
*
|
|
2511
|
+
* **Standalone mode** (no senders configured): returns `false` without
|
|
2512
|
+
* emitting. The subsequent main-queue drain (`flushImmediatelySync()`) is
|
|
2513
|
+
* responsible for delivering the event to local listeners — emitting here
|
|
2514
|
+
* too would surface the same event twice to a `tracelog.on('queue', ...)`
|
|
2515
|
+
* subscriber.
|
|
2516
|
+
*
|
|
2517
|
+
* @returns `true` if at least one sender delivered the beacon successfully,
|
|
2518
|
+
* `false` otherwise (including standalone mode — the drain handles it).
|
|
2519
|
+
*/
|
|
2520
|
+
flushLastEventSync() {
|
|
2521
|
+
if (this.dataSenders.length === 0)
|
|
2522
|
+
return !1;
|
|
2523
|
+
const e = this.eventsQueue[this.eventsQueue.length - 1];
|
|
2524
|
+
if (!e)
|
|
2525
|
+
return !1;
|
|
2526
|
+
const { _session_id: t, ...s } = e;
|
|
2527
|
+
if (!t)
|
|
2528
|
+
return a("debug", "flushLastEventSync: last queued event missing _session_id, skipping"), !1;
|
|
2529
|
+
const n = this.get("config")?.globalMetadata, i = this.get("identity"), o = {
|
|
2530
|
+
user_id: this.get("userId"),
|
|
2531
|
+
session_id: t,
|
|
2532
|
+
device: this.get("device"),
|
|
2533
|
+
events: [s],
|
|
2534
|
+
...n && { global_metadata: n },
|
|
2535
|
+
...i && { identify: i }
|
|
2536
|
+
};
|
|
2537
|
+
return this.dataSenders.map((d) => d.sendEventsQueueSync(o)).some(Boolean);
|
|
2538
|
+
}
|
|
2468
2539
|
/**
|
|
2469
2540
|
* Sets the custom headers provider callback for the custom integration.
|
|
2470
2541
|
* Only affects requests to custom backend (not TraceLog SaaS).
|
|
@@ -2514,7 +2585,7 @@ class vs extends _ {
|
|
|
2514
2585
|
* @internal Used by test-bridge.ts for test inspection
|
|
2515
2586
|
*/
|
|
2516
2587
|
getQueueEvents() {
|
|
2517
|
-
return
|
|
2588
|
+
return this.eventsQueue.map(({ _session_id: e, ...t }) => t);
|
|
2518
2589
|
}
|
|
2519
2590
|
/**
|
|
2520
2591
|
* Triggers immediate queue flush (test utility).
|
|
@@ -2597,107 +2668,207 @@ class vs extends _ {
|
|
|
2597
2668
|
isSuccessfulResult(e) {
|
|
2598
2669
|
return e.status === "fulfilled" && e.value === !0;
|
|
2599
2670
|
}
|
|
2671
|
+
/**
|
|
2672
|
+
* Groups the queue by frozen `_session_id`, preserving insertion order.
|
|
2673
|
+
* Single pass — `buildBatchesWithIds()` builds one batch + one eventIds list
|
|
2674
|
+
* per group, so the grouping cost is O(N) per flush regardless of session
|
|
2675
|
+
* count.
|
|
2676
|
+
*
|
|
2677
|
+
* **Self-heal**: any entry missing `_session_id` (an internal invariant
|
|
2678
|
+
* violation — `buildEventPayload` always stamps it) is removed from the
|
|
2679
|
+
* queue rather than left behind, otherwise a single corrupted entry would
|
|
2680
|
+
* keep `eventsQueue.length > 0` forever and re-trigger periodic sends.
|
|
2681
|
+
*/
|
|
2682
|
+
groupQueuedEventsBySession() {
|
|
2683
|
+
const e = /* @__PURE__ */ new Map(), t = [];
|
|
2684
|
+
for (const s of this.eventsQueue) {
|
|
2685
|
+
if (!s._session_id) {
|
|
2686
|
+
a("debug", "Queued event missing _session_id, dropping", {
|
|
2687
|
+
data: { eventId: s.id, type: s.type }
|
|
2688
|
+
}), t.push(s.id);
|
|
2689
|
+
continue;
|
|
2690
|
+
}
|
|
2691
|
+
const n = e.get(s._session_id);
|
|
2692
|
+
n ? n.push(s) : e.set(s._session_id, [s]);
|
|
2693
|
+
}
|
|
2694
|
+
return t.length > 0 && this.removeProcessedEvents(t), e;
|
|
2695
|
+
}
|
|
2696
|
+
/**
|
|
2697
|
+
* Builds a parallel list of `(batch, eventIds)` for sending. The eventIds are
|
|
2698
|
+
* the original `_session_id`-tagged event IDs in the queue that map to this
|
|
2699
|
+
* batch — used for optimistic removal. We can't read them off the wrapper's
|
|
2700
|
+
* `events[]` because dedup may have removed some signatures.
|
|
2701
|
+
*/
|
|
2702
|
+
buildBatchesWithIds() {
|
|
2703
|
+
const e = this.groupQueuedEventsBySession();
|
|
2704
|
+
if (e.size === 0) return [];
|
|
2705
|
+
const t = [];
|
|
2706
|
+
for (const [s, n] of e)
|
|
2707
|
+
t.push({
|
|
2708
|
+
batch: this.buildBatchFromGroup(s, n),
|
|
2709
|
+
eventIds: n.map((i) => i.id)
|
|
2710
|
+
});
|
|
2711
|
+
return t;
|
|
2712
|
+
}
|
|
2600
2713
|
flushEvents(e) {
|
|
2601
2714
|
if (this.eventsQueue.length === 0)
|
|
2602
2715
|
return e ? !0 : Promise.resolve(!0);
|
|
2603
2716
|
if (!e && this.sendInProgress)
|
|
2604
2717
|
return a("debug", "Async flush skipped: send already in progress"), Promise.resolve(!1);
|
|
2605
|
-
const t = this.
|
|
2606
|
-
if (
|
|
2607
|
-
return
|
|
2608
|
-
if (
|
|
2609
|
-
|
|
2610
|
-
|
|
2718
|
+
const t = this.buildBatchesWithIds();
|
|
2719
|
+
if (t.length === 0)
|
|
2720
|
+
return e ? !0 : Promise.resolve(!0);
|
|
2721
|
+
if (this.dataSenders.length === 0) {
|
|
2722
|
+
for (const { batch: s, eventIds: n } of t)
|
|
2723
|
+
this.removeProcessedEvents(n), this.emitEventsQueue(s);
|
|
2724
|
+
return this.clearSendTimeout(), e ? !0 : Promise.resolve(!0);
|
|
2725
|
+
}
|
|
2726
|
+
if (e && this.sendInProgress) {
|
|
2727
|
+
const s = t.reduce((n, i) => n + i.eventIds.length, 0);
|
|
2728
|
+
return this.pendingSyncFlush = !0, a("debug", "Sync flush deferred: async send in-flight, will retry on settle", {
|
|
2729
|
+
data: { eventCount: s }
|
|
2611
2730
|
}), !0;
|
|
2731
|
+
}
|
|
2612
2732
|
if (e) {
|
|
2613
|
-
const
|
|
2614
|
-
return
|
|
2615
|
-
data: { eventCount: i.length }
|
|
2616
|
-
})), o;
|
|
2617
|
-
} else {
|
|
2618
|
-
const n = this.dataSenders.map(
|
|
2619
|
-
async (o) => o.sendEventsQueue(t, {
|
|
2620
|
-
onSuccess: () => {
|
|
2621
|
-
},
|
|
2622
|
-
onFailure: () => {
|
|
2623
|
-
}
|
|
2624
|
-
})
|
|
2625
|
-
);
|
|
2626
|
-
return Promise.allSettled(n).then((o) => {
|
|
2627
|
-
const l = o.some((c) => this.isSuccessfulResult(c));
|
|
2628
|
-
return l ? (this.removeProcessedEvents(i), this.clearSendTimeout(), this.emitEventsQueue(t)) : a("debug", "Async flush complete failure, events kept in queue for retry", {
|
|
2629
|
-
data: { eventCount: s.length }
|
|
2630
|
-
}), l;
|
|
2631
|
-
});
|
|
2733
|
+
const s = t.map(({ batch: n, eventIds: i }) => this.sendBatchSync(n, i));
|
|
2734
|
+
return this.clearSendTimeout(), s.some(Boolean);
|
|
2632
2735
|
}
|
|
2736
|
+
return this.sendInProgress = !0, (async () => {
|
|
2737
|
+
try {
|
|
2738
|
+
const s = await Promise.all(
|
|
2739
|
+
t.map(async ({ batch: n, eventIds: i }) => this.sendBatchAsync(n, i))
|
|
2740
|
+
);
|
|
2741
|
+
return this.clearSendTimeout(), s.some(Boolean);
|
|
2742
|
+
} finally {
|
|
2743
|
+
this.sendInProgress = !1, this.drainPendingSyncFlush();
|
|
2744
|
+
}
|
|
2745
|
+
})();
|
|
2746
|
+
}
|
|
2747
|
+
/**
|
|
2748
|
+
* Re-runs a sync flush that was deferred while an async send was in flight.
|
|
2749
|
+
*
|
|
2750
|
+
* Called from the `finally` blocks of `flushEvents(false)` and
|
|
2751
|
+
* `sendEventsQueue()`. If `pendingSyncFlush` is set, clears the flag and
|
|
2752
|
+
* invokes `flushImmediatelySync()` synchronously so any events that arrived
|
|
2753
|
+
* after the deferred sync call are delivered before the next event loop
|
|
2754
|
+
* tick. Critical for high-stakes events tracked mid-async-send.
|
|
2755
|
+
*/
|
|
2756
|
+
drainPendingSyncFlush() {
|
|
2757
|
+
this.pendingSyncFlush && (this.pendingSyncFlush = !1, this.flushImmediatelySync());
|
|
2758
|
+
}
|
|
2759
|
+
/**
|
|
2760
|
+
* Sends one batch synchronously across all integrations (sendBeacon path).
|
|
2761
|
+
* Optimistic removal: if any integration succeeds, we remove the batch's
|
|
2762
|
+
* events from the queue and emit it locally. Failures persist per-integration.
|
|
2763
|
+
*/
|
|
2764
|
+
sendBatchSync(e, t) {
|
|
2765
|
+
const n = this.dataSenders.map((i) => i.sendEventsQueueSync(e)).some((i) => i);
|
|
2766
|
+
return n ? (this.removeProcessedEvents(t), this.emitEventsQueue(e)) : a("debug", "Sync send complete failure, events kept in queue for retry", {
|
|
2767
|
+
data: { eventCount: t.length, sessionId: e.session_id }
|
|
2768
|
+
}), n;
|
|
2769
|
+
}
|
|
2770
|
+
/**
|
|
2771
|
+
* Sends one batch asynchronously across all integrations (fetch path).
|
|
2772
|
+
*/
|
|
2773
|
+
async sendBatchAsync(e, t) {
|
|
2774
|
+
const s = this.dataSenders.map(
|
|
2775
|
+
async (o) => o.sendEventsQueue(e, {
|
|
2776
|
+
onSuccess: () => {
|
|
2777
|
+
},
|
|
2778
|
+
onFailure: () => {
|
|
2779
|
+
}
|
|
2780
|
+
})
|
|
2781
|
+
), n = await Promise.allSettled(s), i = n.some((o) => this.isSuccessfulResult(o));
|
|
2782
|
+
if (i) {
|
|
2783
|
+
this.removeProcessedEvents(t), this.emitEventsQueue(e);
|
|
2784
|
+
const o = n.filter((l) => !this.isSuccessfulResult(l)).length;
|
|
2785
|
+
o > 0 && a("debug", "Async send completed with some failures, removed from queue and persisted per-integration", {
|
|
2786
|
+
data: { eventCount: t.length, failedCount: o, sessionId: e.session_id }
|
|
2787
|
+
});
|
|
2788
|
+
} else
|
|
2789
|
+
a("debug", "Async send complete failure, events kept in queue for retry", {
|
|
2790
|
+
data: { eventCount: t.length, sessionId: e.session_id }
|
|
2791
|
+
});
|
|
2792
|
+
return i;
|
|
2633
2793
|
}
|
|
2634
2794
|
async sendEventsQueue() {
|
|
2635
|
-
if (!(
|
|
2795
|
+
if (!(this.eventsQueue.length === 0 || this.sendInProgress)) {
|
|
2636
2796
|
this.sendInProgress = !0;
|
|
2637
2797
|
try {
|
|
2638
|
-
const e = this.
|
|
2798
|
+
const e = this.buildBatchesWithIds();
|
|
2799
|
+
if (e.length === 0) return;
|
|
2639
2800
|
if (this.dataSenders.length === 0) {
|
|
2640
|
-
|
|
2801
|
+
for (const { batch: n } of e)
|
|
2802
|
+
this.emitEventsQueue(n);
|
|
2641
2803
|
return;
|
|
2642
2804
|
}
|
|
2643
|
-
|
|
2644
|
-
async (
|
|
2645
|
-
|
|
2646
|
-
},
|
|
2647
|
-
onFailure: () => {
|
|
2648
|
-
}
|
|
2649
|
-
})
|
|
2650
|
-
), n = await Promise.allSettled(i);
|
|
2651
|
-
if (n.some((l) => this.isSuccessfulResult(l))) {
|
|
2652
|
-
this.consecutiveSendFailures = 0, this.removeProcessedEvents(s), this.emitEventsQueue(e);
|
|
2653
|
-
const l = n.filter((c) => !this.isSuccessfulResult(c)).length;
|
|
2654
|
-
l > 0 && a("debug", "Periodic send completed with some failures, removed from queue and persisted per-integration", {
|
|
2655
|
-
data: { eventCount: t.length, failedCount: l }
|
|
2656
|
-
});
|
|
2657
|
-
} else
|
|
2658
|
-
this.consecutiveSendFailures = Math.min(this.consecutiveSendFailures + 1, 5), a("debug", "Periodic send complete failure, events kept in queue for retry", {
|
|
2659
|
-
data: { eventCount: t.length }
|
|
2660
|
-
});
|
|
2661
|
-
this.eventsQueue.length === 0 ? this.clearSendTimeout() : this.scheduleSendTimeout();
|
|
2805
|
+
(await Promise.all(
|
|
2806
|
+
e.map(async ({ batch: n, eventIds: i }) => this.sendBatchAsync(n, i))
|
|
2807
|
+
)).some(Boolean) ? this.consecutiveSendFailures = 0 : this.consecutiveSendFailures = Math.min(this.consecutiveSendFailures + 1, 5), this.eventsQueue.length === 0 ? this.clearSendTimeout() : this.scheduleSendTimeout();
|
|
2662
2808
|
} finally {
|
|
2663
|
-
this.sendInProgress = !1;
|
|
2809
|
+
this.sendInProgress = !1, this.drainPendingSyncFlush();
|
|
2664
2810
|
}
|
|
2665
2811
|
}
|
|
2666
2812
|
}
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2813
|
+
/**
|
|
2814
|
+
* Builds a single batch from a per-session group: dedup by signature,
|
|
2815
|
+
* SESSION_START first, then timestamp order, strip `_session_id`, apply
|
|
2816
|
+
* `beforeBatch` transformer when running standalone.
|
|
2817
|
+
*
|
|
2818
|
+
* **Why N batches per flush**: events freeze their `_session_id` at `track()`
|
|
2819
|
+
* time. If the session was renewed (idle timeout) between two `track()`
|
|
2820
|
+
* calls, the queue contains events from multiple sessions. `buildBatchesWithIds()`
|
|
2821
|
+
* emits one batch per session so the backend's `EventsQueueDto.session_id`
|
|
2822
|
+
* remains the single source of truth and stays consistent with the events it
|
|
2823
|
+
* carries.
|
|
2824
|
+
*
|
|
2825
|
+
* **Strip**: `_session_id` is removed from each event in the wrapper's
|
|
2826
|
+
* `events[]` because the backend uses `forbidNonWhitelisted: true` and would
|
|
2827
|
+
* reject the batch if the field leaked through.
|
|
2828
|
+
*
|
|
2829
|
+
* **Transformer note**: `beforeBatch` is invoked **once per session-batch**,
|
|
2830
|
+
* not once per flush. A queue spanning N sessions triggers N invocations.
|
|
2831
|
+
*/
|
|
2832
|
+
buildBatchFromGroup(e, t) {
|
|
2833
|
+
const s = /* @__PURE__ */ new Map(), n = [];
|
|
2834
|
+
for (const g of t) {
|
|
2835
|
+
const E = this.createEventSignature(g);
|
|
2836
|
+
s.has(E) || n.push(E), s.set(E, g);
|
|
2672
2837
|
}
|
|
2673
|
-
const
|
|
2674
|
-
let
|
|
2838
|
+
const i = n.map((g) => s.get(g)).filter((g) => !!g).sort((g, E) => g.type === u.SESSION_START && E.type !== u.SESSION_START ? -1 : E.type === u.SESSION_START && g.type !== u.SESSION_START ? 1 : g.timestamp - E.timestamp).map(({ _session_id: g, ...E }) => E), o = this.get("config")?.globalMetadata, l = this.get("identity");
|
|
2839
|
+
let d = {
|
|
2675
2840
|
user_id: this.get("userId"),
|
|
2676
|
-
session_id:
|
|
2841
|
+
session_id: e,
|
|
2677
2842
|
device: this.get("device"),
|
|
2678
|
-
events:
|
|
2679
|
-
...
|
|
2680
|
-
...
|
|
2843
|
+
events: i,
|
|
2844
|
+
...o && { global_metadata: o },
|
|
2845
|
+
...l && { identify: l }
|
|
2681
2846
|
};
|
|
2682
|
-
const
|
|
2683
|
-
if (!
|
|
2684
|
-
const
|
|
2685
|
-
|
|
2847
|
+
const c = this.get("collectApiUrls"), f = !!(c?.custom || c?.saas), m = this.transformers.beforeBatch;
|
|
2848
|
+
if (!f && m) {
|
|
2849
|
+
const g = gt(d, m, "EventManager");
|
|
2850
|
+
g !== null && (d = g);
|
|
2686
2851
|
}
|
|
2687
|
-
return
|
|
2852
|
+
return d;
|
|
2688
2853
|
}
|
|
2689
2854
|
buildEventPayload(e) {
|
|
2690
|
-
const t =
|
|
2691
|
-
|
|
2692
|
-
|
|
2855
|
+
const t = this.get("sessionId");
|
|
2856
|
+
if (!t)
|
|
2857
|
+
return a("error", "buildEventPayload reached without sessionId — event dropped", {
|
|
2858
|
+
data: { type: e.type },
|
|
2859
|
+
visibility: "critical"
|
|
2860
|
+
}), null;
|
|
2861
|
+
const s = e.page_url ?? this.get("pageUrl"), n = typeof s == "string" && s.length > 0 ? s : "unknown", i = this.timeManager.now(), o = this.timeManager.validateTimestamp(i);
|
|
2862
|
+
o.valid || a("warn", "Event timestamp validation failed", {
|
|
2863
|
+
data: { type: e.type, error: o.error }
|
|
2693
2864
|
});
|
|
2694
|
-
const
|
|
2695
|
-
let
|
|
2865
|
+
const l = this.get("sessionReferrer"), d = this.get("sessionUtm");
|
|
2866
|
+
let c = {
|
|
2696
2867
|
id: os(),
|
|
2697
2868
|
type: e.type,
|
|
2698
|
-
page_url:
|
|
2699
|
-
timestamp:
|
|
2700
|
-
...
|
|
2869
|
+
page_url: n,
|
|
2870
|
+
timestamp: i,
|
|
2871
|
+
...l && { referrer: l },
|
|
2701
2872
|
...e.from_page_url && { from_page_url: e.from_page_url },
|
|
2702
2873
|
...e.scroll_data && { scroll_data: e.scroll_data },
|
|
2703
2874
|
...e.click_data && { click_data: e.click_data },
|
|
@@ -2706,27 +2877,27 @@ class vs extends _ {
|
|
|
2706
2877
|
...e.error_data && { error_data: e.error_data },
|
|
2707
2878
|
...e.viewport_data && { viewport_data: e.viewport_data },
|
|
2708
2879
|
...e.page_view && { page_view: e.page_view },
|
|
2709
|
-
...
|
|
2880
|
+
...d && { utm: d }
|
|
2710
2881
|
};
|
|
2711
|
-
const
|
|
2712
|
-
if (
|
|
2713
|
-
const
|
|
2714
|
-
if (
|
|
2882
|
+
const f = this.get("collectApiUrls"), m = !!f?.custom, g = !!f?.saas, E = m || g, he = m && g, z = this.transformers.beforeSend;
|
|
2883
|
+
if (z && (!E || m && !he)) {
|
|
2884
|
+
const v = mt(c, z, "EventManager");
|
|
2885
|
+
if (v === null)
|
|
2715
2886
|
return null;
|
|
2716
|
-
|
|
2887
|
+
c = v;
|
|
2717
2888
|
}
|
|
2718
|
-
return
|
|
2889
|
+
return { ...c, _session_id: t };
|
|
2719
2890
|
}
|
|
2720
2891
|
isDuplicateEvent(e) {
|
|
2721
|
-
const t = Date.now(), s = this.createEventFingerprint(e),
|
|
2722
|
-
return
|
|
2892
|
+
const t = Date.now(), s = this.createEventFingerprint(e), n = this.recentEventFingerprints.get(s);
|
|
2893
|
+
return n && t - n < 1e3 ? (this.recentEventFingerprints.set(s, t), !0) : (this.recentEventFingerprints.set(s, t), this.recentEventFingerprints.size > 1500 && this.pruneOldFingerprints(), this.recentEventFingerprints.size > 3e3 && (this.recentEventFingerprints.clear(), this.recentEventFingerprints.set(s, t), a("debug", "Event fingerprint cache exceeded hard limit, cleared", {
|
|
2723
2894
|
data: { hardLimit: 3e3 }
|
|
2724
2895
|
})), !1);
|
|
2725
2896
|
}
|
|
2726
2897
|
pruneOldFingerprints() {
|
|
2727
2898
|
const e = Date.now(), t = 1e3 * 10;
|
|
2728
|
-
for (const [s,
|
|
2729
|
-
e -
|
|
2899
|
+
for (const [s, n] of this.recentEventFingerprints.entries())
|
|
2900
|
+
e - n > t && this.recentEventFingerprints.delete(s);
|
|
2730
2901
|
a("debug", "Pruned old event fingerprints", {
|
|
2731
2902
|
data: {
|
|
2732
2903
|
remaining: this.recentEventFingerprints.size,
|
|
@@ -2737,8 +2908,8 @@ class vs extends _ {
|
|
|
2737
2908
|
createEventFingerprint(e) {
|
|
2738
2909
|
let t = `${e.type}_${e.page_url}`;
|
|
2739
2910
|
if (e.click_data) {
|
|
2740
|
-
const s = Math.round((e.click_data.x || 0) / 10) * 10,
|
|
2741
|
-
t += `_click_${s}_${
|
|
2911
|
+
const s = Math.round((e.click_data.x || 0) / 10) * 10, n = Math.round((e.click_data.y || 0) / 10) * 10;
|
|
2912
|
+
t += `_click_${s}_${n}`;
|
|
2742
2913
|
}
|
|
2743
2914
|
return e.scroll_data && (t += `_scroll_${e.scroll_data.depth}_${e.scroll_data.direction}`), e.custom_event && (t += `_custom_${e.custom_event.name}`, e.custom_event.metadata && (t += `_${this.stableStringify(e.custom_event.metadata)}`)), e.web_vitals && (t += `_vitals_${e.web_vitals.type}`), e.error_data && (t += `_error_${e.error_data.type}_${e.error_data.message}`), t;
|
|
2744
2915
|
}
|
|
@@ -2747,11 +2918,11 @@ class vs extends _ {
|
|
|
2747
2918
|
}
|
|
2748
2919
|
/** Deterministic JSON string with sorted keys to ensure consistent fingerprints regardless of property insertion order */
|
|
2749
2920
|
stableStringify(e) {
|
|
2750
|
-
return JSON.stringify(e, (t, s) => s && typeof s == "object" && !Array.isArray(s) ? Object.keys(s).sort().reduce((
|
|
2921
|
+
return JSON.stringify(e, (t, s) => s && typeof s == "object" && !Array.isArray(s) ? Object.keys(s).sort().reduce((n, i) => (n[i] = s[i], n), {}) : s);
|
|
2751
2922
|
}
|
|
2752
2923
|
addToQueue(e) {
|
|
2753
2924
|
if (this.emitEvent(e), this.eventsQueue.push(e), this.eventsQueue.length > 100) {
|
|
2754
|
-
const t = this.eventsQueue.findIndex((
|
|
2925
|
+
const t = this.eventsQueue.findIndex((n) => n.type !== u.SESSION_START), s = t >= 0 ? this.eventsQueue.splice(t, 1)[0] : this.eventsQueue.shift();
|
|
2755
2926
|
a("warn", "Event queue overflow, oldest non-critical event removed", {
|
|
2756
2927
|
data: {
|
|
2757
2928
|
maxLength: 100,
|
|
@@ -2785,14 +2956,14 @@ class vs extends _ {
|
|
|
2785
2956
|
return e - this.rateLimitWindowStart > 1e3 && (this.rateLimitCounter = 0, this.rateLimitWindowStart = e), this.rateLimitCounter >= 50 ? !1 : (this.rateLimitCounter++, !0);
|
|
2786
2957
|
}
|
|
2787
2958
|
checkPerEventRateLimit(e, t) {
|
|
2788
|
-
const s = Date.now(),
|
|
2789
|
-
return
|
|
2959
|
+
const s = Date.now(), i = (this.perEventRateLimits.get(e) ?? []).filter((o) => s - o < 6e4);
|
|
2960
|
+
return i.length >= t ? (a("warn", "Per-event rate limit exceeded for custom event", {
|
|
2790
2961
|
data: {
|
|
2791
2962
|
eventName: e,
|
|
2792
2963
|
limit: t,
|
|
2793
2964
|
window: `${6e4 / 1e3}s`
|
|
2794
2965
|
}
|
|
2795
|
-
}), !1) : (
|
|
2966
|
+
}), !1) : (i.push(s), this.perEventRateLimits.set(e, i), !0);
|
|
2796
2967
|
}
|
|
2797
2968
|
getTypeLimitForEvent(e) {
|
|
2798
2969
|
return {
|
|
@@ -2808,7 +2979,10 @@ class vs extends _ {
|
|
|
2808
2979
|
this.eventsQueue = this.eventsQueue.filter((s) => !t.has(s.id));
|
|
2809
2980
|
}
|
|
2810
2981
|
emitEvent(e) {
|
|
2811
|
-
|
|
2982
|
+
if (this.emitter) {
|
|
2983
|
+
const { _session_id: t, ...s } = e;
|
|
2984
|
+
this.emitter.emit(se.EVENT, s);
|
|
2985
|
+
}
|
|
2812
2986
|
}
|
|
2813
2987
|
emitEventsQueue(e) {
|
|
2814
2988
|
this.emitter && this.emitter.emit(se.QUEUE, e);
|
|
@@ -2835,9 +3009,9 @@ class vs extends _ {
|
|
|
2835
3009
|
*/
|
|
2836
3010
|
debounce(e, t) {
|
|
2837
3011
|
let s = null;
|
|
2838
|
-
return ((...
|
|
3012
|
+
return ((...n) => {
|
|
2839
3013
|
s !== null && clearTimeout(s), s = setTimeout(() => {
|
|
2840
|
-
e(...
|
|
3014
|
+
e(...n), s = null;
|
|
2841
3015
|
}, t);
|
|
2842
3016
|
});
|
|
2843
3017
|
}
|
|
@@ -2887,29 +3061,29 @@ class vs extends _ {
|
|
|
2887
3061
|
loadSessionCounts(e) {
|
|
2888
3062
|
if (typeof window > "u" || typeof localStorage > "u")
|
|
2889
3063
|
return this.getInitialCounts();
|
|
2890
|
-
const t = this.get("userId") || "anonymous", s =
|
|
3064
|
+
const t = this.get("userId") || "anonymous", s = Fe(t, e);
|
|
2891
3065
|
try {
|
|
2892
|
-
const
|
|
2893
|
-
if (!
|
|
3066
|
+
const n = localStorage.getItem(s);
|
|
3067
|
+
if (!n)
|
|
2894
3068
|
return this.getInitialCounts();
|
|
2895
|
-
const
|
|
2896
|
-
return
|
|
2897
|
-
data: { sessionId: e, age: Date.now() -
|
|
2898
|
-
}), localStorage.removeItem(s), this.getInitialCounts()) : typeof
|
|
2899
|
-
total:
|
|
2900
|
-
[u.CLICK]:
|
|
2901
|
-
[u.PAGE_VIEW]:
|
|
2902
|
-
[u.CUSTOM]:
|
|
2903
|
-
[u.VIEWPORT_VISIBLE]:
|
|
2904
|
-
[u.SCROLL]:
|
|
3069
|
+
const i = JSON.parse(n);
|
|
3070
|
+
return i._timestamp && Date.now() - i._timestamp > xe ? (a("debug", "Session counts expired, clearing", {
|
|
3071
|
+
data: { sessionId: e, age: Date.now() - i._timestamp }
|
|
3072
|
+
}), localStorage.removeItem(s), this.getInitialCounts()) : typeof i.total == "number" && typeof i[u.CLICK] == "number" && typeof i[u.PAGE_VIEW] == "number" && typeof i[u.CUSTOM] == "number" && typeof i[u.VIEWPORT_VISIBLE] == "number" && typeof i[u.SCROLL] == "number" ? {
|
|
3073
|
+
total: i.total,
|
|
3074
|
+
[u.CLICK]: i[u.CLICK],
|
|
3075
|
+
[u.PAGE_VIEW]: i[u.PAGE_VIEW],
|
|
3076
|
+
[u.CUSTOM]: i[u.CUSTOM],
|
|
3077
|
+
[u.VIEWPORT_VISIBLE]: i[u.VIEWPORT_VISIBLE],
|
|
3078
|
+
[u.SCROLL]: i[u.SCROLL]
|
|
2905
3079
|
} : (a("warn", "Invalid session counts structure in localStorage, resetting", {
|
|
2906
|
-
data: { sessionId: e, parsed:
|
|
3080
|
+
data: { sessionId: e, parsed: i }
|
|
2907
3081
|
}), localStorage.removeItem(s), a("debug", "Session counts removed due to invalid/corrupted data", {
|
|
2908
|
-
data: { sessionId: e, parsed:
|
|
3082
|
+
data: { sessionId: e, parsed: i }
|
|
2909
3083
|
}), this.getInitialCounts());
|
|
2910
|
-
} catch (
|
|
3084
|
+
} catch (n) {
|
|
2911
3085
|
return a("warn", "Failed to load session counts from localStorage", {
|
|
2912
|
-
error:
|
|
3086
|
+
error: n,
|
|
2913
3087
|
data: { sessionId: e }
|
|
2914
3088
|
}), this.getInitialCounts();
|
|
2915
3089
|
}
|
|
@@ -2940,30 +3114,30 @@ class vs extends _ {
|
|
|
2940
3114
|
try {
|
|
2941
3115
|
const e = localStorage.getItem($e);
|
|
2942
3116
|
if (e) {
|
|
2943
|
-
const
|
|
2944
|
-
if (
|
|
3117
|
+
const i = Date.now() - parseInt(e, 10);
|
|
3118
|
+
if (i < Be) {
|
|
2945
3119
|
a("debug", "Skipping session counts cleanup (throttled)", {
|
|
2946
|
-
data: { timeSinceLastCleanup:
|
|
3120
|
+
data: { timeSinceLastCleanup: i, throttleMs: Be }
|
|
2947
3121
|
});
|
|
2948
3122
|
return;
|
|
2949
3123
|
}
|
|
2950
3124
|
}
|
|
2951
|
-
const t = this.get("userId") || "anonymous", s = `${
|
|
2952
|
-
for (let
|
|
2953
|
-
const o = localStorage.key(
|
|
3125
|
+
const t = this.get("userId") || "anonymous", s = `${I}:${t}:session_counts:`, n = [];
|
|
3126
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
3127
|
+
const o = localStorage.key(i);
|
|
2954
3128
|
if (o?.startsWith(s))
|
|
2955
3129
|
try {
|
|
2956
3130
|
const l = localStorage.getItem(o);
|
|
2957
3131
|
if (l) {
|
|
2958
|
-
const
|
|
2959
|
-
|
|
3132
|
+
const d = JSON.parse(l);
|
|
3133
|
+
d._timestamp && Date.now() - d._timestamp > xe && n.push(o);
|
|
2960
3134
|
}
|
|
2961
3135
|
} catch {
|
|
2962
3136
|
}
|
|
2963
3137
|
}
|
|
2964
|
-
|
|
2965
|
-
localStorage.removeItem(
|
|
2966
|
-
}),
|
|
3138
|
+
n.forEach((i) => {
|
|
3139
|
+
localStorage.removeItem(i), a("debug", "Cleaned up expired session counts", { data: { key: i } });
|
|
3140
|
+
}), n.length > 0 && a("info", `Cleaned up ${n.length} expired session counts entries`), localStorage.setItem($e, Date.now().toString());
|
|
2967
3141
|
} catch (e) {
|
|
2968
3142
|
a("warn", "Failed to cleanup expired session counts", { error: e });
|
|
2969
3143
|
}
|
|
@@ -2997,17 +3171,17 @@ class vs extends _ {
|
|
|
2997
3171
|
* @internal
|
|
2998
3172
|
*/
|
|
2999
3173
|
saveSessionCounts(e) {
|
|
3000
|
-
const t = this.get("userId") || "anonymous", s =
|
|
3174
|
+
const t = this.get("userId") || "anonymous", s = Fe(t, e);
|
|
3001
3175
|
try {
|
|
3002
|
-
const
|
|
3176
|
+
const n = {
|
|
3003
3177
|
...this.sessionEventCounts,
|
|
3004
3178
|
_timestamp: Date.now(),
|
|
3005
3179
|
_version: 1
|
|
3006
3180
|
};
|
|
3007
|
-
localStorage.setItem(s, JSON.stringify(
|
|
3008
|
-
} catch (
|
|
3181
|
+
localStorage.setItem(s, JSON.stringify(n));
|
|
3182
|
+
} catch (n) {
|
|
3009
3183
|
a("warn", "Failed to persist session counts to localStorage", {
|
|
3010
|
-
error:
|
|
3184
|
+
error: n,
|
|
3011
3185
|
data: { sessionId: e }
|
|
3012
3186
|
});
|
|
3013
3187
|
}
|
|
@@ -3031,11 +3205,11 @@ class _s {
|
|
|
3031
3205
|
* @returns Persistent unique user ID (UUID v4 format)
|
|
3032
3206
|
*/
|
|
3033
3207
|
static getId(e) {
|
|
3034
|
-
const t = e.getItem(
|
|
3208
|
+
const t = e.getItem(ve);
|
|
3035
3209
|
if (t)
|
|
3036
3210
|
return t;
|
|
3037
3211
|
const s = dt();
|
|
3038
|
-
return e.setItem(
|
|
3212
|
+
return e.setItem(ve, s), s;
|
|
3039
3213
|
}
|
|
3040
3214
|
}
|
|
3041
3215
|
const ys = /^\d{13}-[a-z0-9]{9}$/;
|
|
@@ -3066,8 +3240,8 @@ class ws extends _ {
|
|
|
3066
3240
|
}
|
|
3067
3241
|
const e = this.getProjectId();
|
|
3068
3242
|
this.broadcastChannel = new BroadcastChannel(Ot(e)), this.broadcastChannel.onmessage = (t) => {
|
|
3069
|
-
const { action: s, sessionId:
|
|
3070
|
-
o === e && (s === "session_start" &&
|
|
3243
|
+
const { action: s, sessionId: n, timestamp: i, projectId: o } = t.data ?? {};
|
|
3244
|
+
o === e && (s === "session_start" && n && typeof i == "number" && i > Date.now() - 5e3 ? (this.set("sessionId", n), this.persistSession(n, i), this.isTracking && this.setupSessionTimeout()) : s && s !== "session_start" && a("debug", "Ignored BroadcastChannel message with unknown action", { data: { action: s } }));
|
|
3071
3245
|
};
|
|
3072
3246
|
}
|
|
3073
3247
|
shareSession(e) {
|
|
@@ -3092,12 +3266,12 @@ class ws extends _ {
|
|
|
3092
3266
|
const t = this.get("config")?.sessionTimeout ?? 9e5;
|
|
3093
3267
|
return Date.now() - e.lastActivity > t ? (this.clearStoredSession(), null) : e.id;
|
|
3094
3268
|
}
|
|
3095
|
-
persistSession(e, t = Date.now(), s,
|
|
3269
|
+
persistSession(e, t = Date.now(), s, n) {
|
|
3096
3270
|
this.saveStoredSession({
|
|
3097
3271
|
id: e,
|
|
3098
3272
|
lastActivity: t,
|
|
3099
3273
|
...s && { referrer: s },
|
|
3100
|
-
...
|
|
3274
|
+
...n && { utm: n }
|
|
3101
3275
|
});
|
|
3102
3276
|
}
|
|
3103
3277
|
clearStoredSession() {
|
|
@@ -3108,18 +3282,18 @@ class ws extends _ {
|
|
|
3108
3282
|
const e = this.getSessionStorageKey(), t = this.storageManager.getItem(e);
|
|
3109
3283
|
if (t !== null)
|
|
3110
3284
|
try {
|
|
3111
|
-
const
|
|
3112
|
-
if (
|
|
3113
|
-
return
|
|
3285
|
+
const n = JSON.parse(t);
|
|
3286
|
+
if (n.id && typeof n.lastActivity == "number")
|
|
3287
|
+
return n;
|
|
3114
3288
|
} catch {
|
|
3115
3289
|
this.storageManager.removeItem(e);
|
|
3116
3290
|
}
|
|
3117
3291
|
const s = this.storageManager.getSessionItem(e);
|
|
3118
3292
|
if (s !== null)
|
|
3119
3293
|
try {
|
|
3120
|
-
const
|
|
3121
|
-
if (
|
|
3122
|
-
return
|
|
3294
|
+
const n = JSON.parse(s);
|
|
3295
|
+
if (n.id && typeof n.lastActivity == "number")
|
|
3296
|
+
return n;
|
|
3123
3297
|
} catch {
|
|
3124
3298
|
this.storageManager.removeSessionItem(e);
|
|
3125
3299
|
}
|
|
@@ -3193,31 +3367,31 @@ class ws extends _ {
|
|
|
3193
3367
|
return;
|
|
3194
3368
|
}
|
|
3195
3369
|
const e = this.recoverSession(), t = e ?? this.generateSessionId();
|
|
3196
|
-
let s,
|
|
3370
|
+
let s, n;
|
|
3197
3371
|
if (e) {
|
|
3198
|
-
const
|
|
3199
|
-
s =
|
|
3372
|
+
const i = this.loadStoredSession();
|
|
3373
|
+
s = i?.referrer ?? ge(), n = i?.utm ?? pe();
|
|
3200
3374
|
} else
|
|
3201
|
-
s =
|
|
3375
|
+
s = ge(), n = pe();
|
|
3202
3376
|
a("debug", "Session tracking initialized", {
|
|
3203
3377
|
data: {
|
|
3204
3378
|
sessionId: t,
|
|
3205
3379
|
wasRecovered: !!e,
|
|
3206
3380
|
willEmitSessionStart: !e,
|
|
3207
3381
|
sessionReferrer: s,
|
|
3208
|
-
hasUtm: !!
|
|
3382
|
+
hasUtm: !!n
|
|
3209
3383
|
}
|
|
3210
3384
|
}), this.isTracking = !0;
|
|
3211
3385
|
try {
|
|
3212
|
-
this.set("sessionId", t), this.set("sessionReferrer", s), this.set("sessionUtm",
|
|
3386
|
+
this.set("sessionId", t), this.set("sessionReferrer", s), this.set("sessionUtm", n), this.persistSession(t, Date.now(), s, n), this.initCrossTabSync(), this.shareSession(t), e ? a("debug", "Session recovered, skipping SESSION_START", {
|
|
3213
3387
|
data: { sessionId: t }
|
|
3214
3388
|
}) : (a("debug", "Emitting SESSION_START event", {
|
|
3215
3389
|
data: { sessionId: t }
|
|
3216
3390
|
}), this.eventManager.track({
|
|
3217
3391
|
type: u.SESSION_START
|
|
3218
3392
|
})), this.setupSessionTimeout(), this.setupActivityListeners(), this.setupLifecycleListeners();
|
|
3219
|
-
} catch (
|
|
3220
|
-
throw this.isTracking = !1, this.clearSessionTimeout(), this.cleanupActivityListeners(), this.cleanupLifecycleListeners(), this.cleanupCrossTabSync(), this.set("sessionId", null),
|
|
3393
|
+
} catch (i) {
|
|
3394
|
+
throw this.isTracking = !1, this.clearSessionTimeout(), this.cleanupActivityListeners(), this.cleanupLifecycleListeners(), this.cleanupCrossTabSync(), this.set("sessionId", null), i;
|
|
3221
3395
|
}
|
|
3222
3396
|
}
|
|
3223
3397
|
generateSessionId() {
|
|
@@ -3249,7 +3423,7 @@ class ws extends _ {
|
|
|
3249
3423
|
*/
|
|
3250
3424
|
renewSession() {
|
|
3251
3425
|
this.needsRenewal = !1;
|
|
3252
|
-
const e = this.generateSessionId(), t =
|
|
3426
|
+
const e = this.generateSessionId(), t = ge(), s = pe();
|
|
3253
3427
|
a("debug", "Renewing session after timeout", {
|
|
3254
3428
|
data: { newSessionId: e }
|
|
3255
3429
|
}), this.set("sessionId", e), this.set("sessionReferrer", t), this.set("sessionUtm", s), this.persistSession(e, Date.now(), t, s), this.cleanupCrossTabSync(), this.initCrossTabSync(), this.shareSession(e), this.eventManager.track({
|
|
@@ -3498,25 +3672,25 @@ class Ls extends _ {
|
|
|
3498
3672
|
};
|
|
3499
3673
|
}
|
|
3500
3674
|
trackCurrentPage = () => {
|
|
3501
|
-
const e = window.location.href, t =
|
|
3675
|
+
const e = window.location.href, t = we(e, this.get("config").sensitiveQueryParams);
|
|
3502
3676
|
if (this.get("pageUrl") === t)
|
|
3503
3677
|
return;
|
|
3504
|
-
const s = Date.now(),
|
|
3505
|
-
if (s - this.lastPageViewTime <
|
|
3678
|
+
const s = Date.now(), n = this.get("config").pageViewThrottleMs ?? 1e3;
|
|
3679
|
+
if (s - this.lastPageViewTime < n)
|
|
3506
3680
|
return;
|
|
3507
3681
|
this.lastPageViewTime = s, this.onTrack();
|
|
3508
|
-
const
|
|
3682
|
+
const i = this.get("pageUrl");
|
|
3509
3683
|
this.set("pageUrl", t);
|
|
3510
3684
|
const o = this.extractPageViewData();
|
|
3511
3685
|
this.eventManager.track({
|
|
3512
3686
|
type: u.PAGE_VIEW,
|
|
3513
3687
|
page_url: this.get("pageUrl"),
|
|
3514
|
-
from_page_url:
|
|
3688
|
+
from_page_url: i,
|
|
3515
3689
|
...o && { page_view: o }
|
|
3516
|
-
});
|
|
3690
|
+
}), this.get("config").flushOnSpaNavigation !== !1 && this.eventManager.flushImmediately();
|
|
3517
3691
|
};
|
|
3518
3692
|
trackInitialPageView() {
|
|
3519
|
-
const e =
|
|
3693
|
+
const e = we(window.location.href, this.get("config").sensitiveQueryParams), t = this.extractPageViewData();
|
|
3520
3694
|
this.lastPageViewTime = Date.now(), this.eventManager.track({
|
|
3521
3695
|
type: u.PAGE_VIEW,
|
|
3522
3696
|
page_url: e,
|
|
@@ -3524,10 +3698,10 @@ class Ls extends _ {
|
|
|
3524
3698
|
}), this.onTrack();
|
|
3525
3699
|
}
|
|
3526
3700
|
extractPageViewData() {
|
|
3527
|
-
const { pathname: e, search: t, hash: s } = window.location, { referrer:
|
|
3528
|
-
return !
|
|
3529
|
-
...
|
|
3530
|
-
...
|
|
3701
|
+
const { pathname: e, search: t, hash: s } = window.location, { referrer: n } = document, { title: i } = document;
|
|
3702
|
+
return !n && !i && !e && !t && !s ? void 0 : {
|
|
3703
|
+
...n && { referrer: n },
|
|
3704
|
+
...i && { title: i },
|
|
3531
3705
|
...e && { pathname: e },
|
|
3532
3706
|
...t && { search: t },
|
|
3533
3707
|
...s && { hash: s }
|
|
@@ -3557,34 +3731,38 @@ class As extends _ {
|
|
|
3557
3731
|
*/
|
|
3558
3732
|
startTracking() {
|
|
3559
3733
|
this.clickHandler || (this.clickHandler = (e) => {
|
|
3560
|
-
const t = e, s = t.target,
|
|
3561
|
-
if (!
|
|
3734
|
+
const t = e, s = t.target, n = typeof HTMLElement < "u" && s instanceof HTMLElement ? s : typeof HTMLElement < "u" && s instanceof Node && s.parentElement instanceof HTMLElement ? s.parentElement : null;
|
|
3735
|
+
if (!n) {
|
|
3562
3736
|
a("debug", "Click target not found or not an element");
|
|
3563
3737
|
return;
|
|
3564
3738
|
}
|
|
3565
|
-
if (this.shouldIgnoreElement(
|
|
3739
|
+
if (this.shouldIgnoreElement(n))
|
|
3566
3740
|
return;
|
|
3567
|
-
const
|
|
3568
|
-
if (
|
|
3741
|
+
const i = this.get("config")?.clickThrottleMs ?? 300;
|
|
3742
|
+
if (i > 0 && !this.checkClickThrottle(n, i))
|
|
3569
3743
|
return;
|
|
3570
|
-
const o = this.findTrackingElement(
|
|
3744
|
+
const o = this.findTrackingElement(n), l = this.getRelevantClickElement(n), d = this.calculateClickCoordinates(t, n);
|
|
3571
3745
|
if (o) {
|
|
3572
3746
|
const f = this.extractTrackingData(o);
|
|
3573
3747
|
if (f) {
|
|
3574
|
-
const
|
|
3748
|
+
const m = this.createCustomEventData(f);
|
|
3575
3749
|
this.eventManager.track({
|
|
3576
3750
|
type: u.CUSTOM,
|
|
3577
3751
|
custom_event: {
|
|
3578
|
-
name:
|
|
3579
|
-
...
|
|
3752
|
+
name: m.name,
|
|
3753
|
+
...m.value && { metadata: { value: m.value } }
|
|
3580
3754
|
}
|
|
3581
3755
|
});
|
|
3582
3756
|
}
|
|
3583
3757
|
}
|
|
3584
|
-
|
|
3758
|
+
if (!d) {
|
|
3759
|
+
a("debug", "Click skipped: invalid coordinates (likely synthetic)");
|
|
3760
|
+
return;
|
|
3761
|
+
}
|
|
3762
|
+
const c = this.generateClickData(n, l, d);
|
|
3585
3763
|
this.eventManager.track({
|
|
3586
3764
|
type: u.CLICK,
|
|
3587
|
-
click_data:
|
|
3765
|
+
click_data: c
|
|
3588
3766
|
});
|
|
3589
3767
|
}, window.addEventListener("click", this.clickHandler, !0));
|
|
3590
3768
|
}
|
|
@@ -3605,15 +3783,15 @@ class As extends _ {
|
|
|
3605
3783
|
* Returns true if the click should be tracked, false if throttled
|
|
3606
3784
|
*/
|
|
3607
3785
|
checkClickThrottle(e, t) {
|
|
3608
|
-
const s = this.getElementSignature(e),
|
|
3609
|
-
this.pruneThrottleCache(
|
|
3610
|
-
const
|
|
3611
|
-
return
|
|
3786
|
+
const s = this.getElementSignature(e), n = Date.now();
|
|
3787
|
+
this.pruneThrottleCache(n);
|
|
3788
|
+
const i = this.lastClickTimes.get(s);
|
|
3789
|
+
return i !== void 0 && n - i < t ? (a("debug", "ClickHandler: Click suppressed by throttle", {
|
|
3612
3790
|
data: {
|
|
3613
3791
|
signature: s,
|
|
3614
|
-
throttleRemaining: t - (
|
|
3792
|
+
throttleRemaining: t - (n - i)
|
|
3615
3793
|
}
|
|
3616
|
-
}), !1) : (this.lastClickTimes.set(s,
|
|
3794
|
+
}), !1) : (this.lastClickTimes.set(s, n), !0);
|
|
3617
3795
|
}
|
|
3618
3796
|
/**
|
|
3619
3797
|
* Prunes stale entries from the throttle cache to prevent memory leaks
|
|
@@ -3625,15 +3803,15 @@ class As extends _ {
|
|
|
3625
3803
|
return;
|
|
3626
3804
|
this.lastPruneTime = e;
|
|
3627
3805
|
const t = e - 3e5;
|
|
3628
|
-
for (const [s,
|
|
3629
|
-
|
|
3806
|
+
for (const [s, n] of this.lastClickTimes.entries())
|
|
3807
|
+
n < t && this.lastClickTimes.delete(s);
|
|
3630
3808
|
if (this.lastClickTimes.size > 1e3) {
|
|
3631
|
-
const s = Array.from(this.lastClickTimes.entries()).sort((o, l) => o[1] - l[1]),
|
|
3632
|
-
for (const [o] of
|
|
3809
|
+
const s = Array.from(this.lastClickTimes.entries()).sort((o, l) => o[1] - l[1]), n = this.lastClickTimes.size - 1e3, i = s.slice(0, n);
|
|
3810
|
+
for (const [o] of i)
|
|
3633
3811
|
this.lastClickTimes.delete(o);
|
|
3634
3812
|
a("debug", "ClickHandler: Pruned throttle cache", {
|
|
3635
3813
|
data: {
|
|
3636
|
-
removed:
|
|
3814
|
+
removed: i.length,
|
|
3637
3815
|
remaining: this.lastClickTimes.size
|
|
3638
3816
|
}
|
|
3639
3817
|
});
|
|
@@ -3659,12 +3837,12 @@ class As extends _ {
|
|
|
3659
3837
|
const t = [];
|
|
3660
3838
|
let s = e;
|
|
3661
3839
|
for (; s && s !== document.body; ) {
|
|
3662
|
-
let
|
|
3840
|
+
let n = s.tagName.toLowerCase();
|
|
3663
3841
|
if (s.className) {
|
|
3664
|
-
const
|
|
3665
|
-
|
|
3842
|
+
const i = s.className.split(" ")[0];
|
|
3843
|
+
i && (n += `.${i}`);
|
|
3666
3844
|
}
|
|
3667
|
-
t.unshift(
|
|
3845
|
+
t.unshift(n), s = s.parentElement;
|
|
3668
3846
|
}
|
|
3669
3847
|
return t.join(">") || "unknown";
|
|
3670
3848
|
}
|
|
@@ -3700,8 +3878,11 @@ class As extends _ {
|
|
|
3700
3878
|
return Math.max(0, Math.min(1, Number(e.toFixed(3))));
|
|
3701
3879
|
}
|
|
3702
3880
|
calculateClickCoordinates(e, t) {
|
|
3703
|
-
const s =
|
|
3704
|
-
|
|
3881
|
+
const s = e.clientX, n = e.clientY;
|
|
3882
|
+
if (typeof s != "number" || typeof n != "number" || !Number.isFinite(s) || !Number.isFinite(n) || s === 0 && n === 0 && !e.isTrusted)
|
|
3883
|
+
return null;
|
|
3884
|
+
const i = t.getBoundingClientRect(), o = i.width > 0 ? this.clamp((s - i.left) / i.width) : 0, l = i.height > 0 ? this.clamp((n - i.top) / i.height) : 0;
|
|
3885
|
+
return { x: s, y: n, relativeX: o, relativeY: l };
|
|
3705
3886
|
}
|
|
3706
3887
|
extractTrackingData(e) {
|
|
3707
3888
|
const t = e.getAttribute(`${b}-name`), s = e.getAttribute(`${b}-value`);
|
|
@@ -3713,22 +3894,22 @@ class As extends _ {
|
|
|
3713
3894
|
};
|
|
3714
3895
|
}
|
|
3715
3896
|
generateClickData(e, t, s) {
|
|
3716
|
-
const { x:
|
|
3897
|
+
const { x: n, y: i, relativeX: o, relativeY: l } = s, d = this.getRelevantText(e, t), c = this.extractElementAttributes(t);
|
|
3717
3898
|
return {
|
|
3718
|
-
x:
|
|
3719
|
-
y:
|
|
3899
|
+
x: n,
|
|
3900
|
+
y: i,
|
|
3720
3901
|
relativeX: o,
|
|
3721
3902
|
relativeY: l,
|
|
3722
3903
|
tag: t.tagName.toLowerCase(),
|
|
3723
3904
|
...t.id && { id: t.id },
|
|
3724
3905
|
...t.className && { class: t.className },
|
|
3725
|
-
...
|
|
3726
|
-
...
|
|
3727
|
-
...
|
|
3728
|
-
...
|
|
3729
|
-
...
|
|
3730
|
-
...
|
|
3731
|
-
...Object.keys(
|
|
3906
|
+
...d && { text: d },
|
|
3907
|
+
...c.href && { href: c.href },
|
|
3908
|
+
...c.title && { title: c.title },
|
|
3909
|
+
...c.alt && { alt: c.alt },
|
|
3910
|
+
...c.role && { role: c.role },
|
|
3911
|
+
...c["aria-label"] && { ariaLabel: c["aria-label"] },
|
|
3912
|
+
...Object.keys(c).length > 0 && { dataAttributes: c }
|
|
3732
3913
|
};
|
|
3733
3914
|
}
|
|
3734
3915
|
/**
|
|
@@ -3753,17 +3934,17 @@ class As extends _ {
|
|
|
3753
3934
|
sanitizeText(e) {
|
|
3754
3935
|
let t = e;
|
|
3755
3936
|
for (const s of at) {
|
|
3756
|
-
const
|
|
3757
|
-
t = t.replace(
|
|
3937
|
+
const n = new RegExp(s.source, s.flags);
|
|
3938
|
+
t = t.replace(n, "[REDACTED]");
|
|
3758
3939
|
}
|
|
3759
3940
|
return t;
|
|
3760
3941
|
}
|
|
3761
3942
|
getRelevantText(e, t) {
|
|
3762
|
-
const s = e.textContent?.trim() ?? "",
|
|
3763
|
-
if (!s && !
|
|
3943
|
+
const s = e.textContent?.trim() ?? "", n = t.textContent?.trim() ?? "";
|
|
3944
|
+
if (!s && !n)
|
|
3764
3945
|
return "";
|
|
3765
|
-
let
|
|
3766
|
-
return s && s.length <= 255 ?
|
|
3946
|
+
let i = "";
|
|
3947
|
+
return s && s.length <= 255 ? i = s : n.length <= 255 ? i = n : i = n.slice(0, 252) + "...", this.sanitizeText(i);
|
|
3767
3948
|
}
|
|
3768
3949
|
extractElementAttributes(e) {
|
|
3769
3950
|
const t = [
|
|
@@ -3778,9 +3959,9 @@ class As extends _ {
|
|
|
3778
3959
|
"alt",
|
|
3779
3960
|
"role"
|
|
3780
3961
|
], s = {};
|
|
3781
|
-
for (const
|
|
3782
|
-
const
|
|
3783
|
-
|
|
3962
|
+
for (const n of t) {
|
|
3963
|
+
const i = e.getAttribute(n);
|
|
3964
|
+
i && (s[n] = i);
|
|
3784
3965
|
}
|
|
3785
3966
|
return s;
|
|
3786
3967
|
}
|
|
@@ -3838,8 +4019,8 @@ class Ms extends _ {
|
|
|
3838
4019
|
const t = this.findScrollableElements();
|
|
3839
4020
|
if (this.isWindowScrollable() && this.setupScrollContainer(window, "window"), t.length > 0) {
|
|
3840
4021
|
for (const s of t) {
|
|
3841
|
-
const
|
|
3842
|
-
this.setupScrollContainer(s,
|
|
4022
|
+
const n = this.getElementSelector(s);
|
|
4023
|
+
this.setupScrollContainer(s, n);
|
|
3843
4024
|
}
|
|
3844
4025
|
this.applyPrimaryScrollSelectorIfConfigured();
|
|
3845
4026
|
return;
|
|
@@ -3860,18 +4041,18 @@ class Ms extends _ {
|
|
|
3860
4041
|
if (!document.body)
|
|
3861
4042
|
return [];
|
|
3862
4043
|
const e = [], t = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, {
|
|
3863
|
-
acceptNode: (
|
|
3864
|
-
const
|
|
3865
|
-
if (!
|
|
4044
|
+
acceptNode: (n) => {
|
|
4045
|
+
const i = n;
|
|
4046
|
+
if (!i.isConnected || !i.offsetParent)
|
|
3866
4047
|
return NodeFilter.FILTER_SKIP;
|
|
3867
|
-
const o = getComputedStyle(
|
|
4048
|
+
const o = getComputedStyle(i);
|
|
3868
4049
|
return o.overflowY === "auto" || o.overflowY === "scroll" || o.overflow === "auto" || o.overflow === "scroll" ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
|
|
3869
4050
|
}
|
|
3870
4051
|
});
|
|
3871
4052
|
let s;
|
|
3872
4053
|
for (; (s = t.nextNode()) && e.length < 10; ) {
|
|
3873
|
-
const
|
|
3874
|
-
this.isElementScrollable(
|
|
4054
|
+
const n = s;
|
|
4055
|
+
this.isElementScrollable(n) && e.push(n);
|
|
3875
4056
|
}
|
|
3876
4057
|
return e;
|
|
3877
4058
|
}
|
|
@@ -3882,7 +4063,7 @@ class Ms extends _ {
|
|
|
3882
4063
|
if (t.id)
|
|
3883
4064
|
return `#${t.id}`;
|
|
3884
4065
|
if (t.className && typeof t.className == "string") {
|
|
3885
|
-
const s = t.className.split(" ").filter((
|
|
4066
|
+
const s = t.className.split(" ").filter((n) => n.trim())[0];
|
|
3886
4067
|
if (s)
|
|
3887
4068
|
return `.${s}`;
|
|
3888
4069
|
}
|
|
@@ -3892,42 +4073,42 @@ class Ms extends _ {
|
|
|
3892
4073
|
return this.isWindowScrollable() ? e === window : this.containers.length === 0;
|
|
3893
4074
|
}
|
|
3894
4075
|
setupScrollContainer(e, t) {
|
|
3895
|
-
if (this.containers.some((
|
|
4076
|
+
if (this.containers.some((c) => c.element === e) || e !== window && !this.isElementScrollable(e))
|
|
3896
4077
|
return;
|
|
3897
|
-
const
|
|
3898
|
-
|
|
4078
|
+
const n = this.getScrollTop(e), i = this.calculateScrollDepth(
|
|
4079
|
+
n,
|
|
3899
4080
|
this.getScrollHeight(e),
|
|
3900
4081
|
this.getViewportHeight(e)
|
|
3901
4082
|
), o = this.determineIfPrimary(e), l = {
|
|
3902
4083
|
element: e,
|
|
3903
4084
|
selector: t,
|
|
3904
4085
|
isPrimary: o,
|
|
3905
|
-
lastScrollPos:
|
|
3906
|
-
lastDepth:
|
|
4086
|
+
lastScrollPos: n,
|
|
4087
|
+
lastDepth: i,
|
|
3907
4088
|
lastDirection: Z.DOWN,
|
|
3908
4089
|
lastEventTime: 0,
|
|
3909
4090
|
firstScrollEventTime: null,
|
|
3910
|
-
maxDepthReached:
|
|
4091
|
+
maxDepthReached: i,
|
|
3911
4092
|
debounceTimer: null,
|
|
3912
4093
|
listener: null
|
|
3913
|
-
},
|
|
4094
|
+
}, d = () => {
|
|
3914
4095
|
this.get("suppressNextScroll") || (l.firstScrollEventTime === null && (l.firstScrollEventTime = Date.now()), this.clearContainerTimer(l), l.debounceTimer = window.setTimeout(() => {
|
|
3915
|
-
const
|
|
3916
|
-
if (
|
|
4096
|
+
const c = this.calculateScrollData(l);
|
|
4097
|
+
if (c) {
|
|
3917
4098
|
const f = Date.now();
|
|
3918
|
-
this.processScrollEvent(l,
|
|
4099
|
+
this.processScrollEvent(l, c, f);
|
|
3919
4100
|
}
|
|
3920
4101
|
l.debounceTimer = null;
|
|
3921
4102
|
}, 250));
|
|
3922
4103
|
};
|
|
3923
|
-
l.listener =
|
|
4104
|
+
l.listener = d, this.containers.push(l), e === window ? window.addEventListener("scroll", d, { passive: !0 }) : e.addEventListener("scroll", d, { passive: !0 });
|
|
3924
4105
|
}
|
|
3925
4106
|
processScrollEvent(e, t, s) {
|
|
3926
4107
|
if (!this.shouldEmitScrollEvent(e, t, s))
|
|
3927
4108
|
return;
|
|
3928
4109
|
e.lastEventTime = s, e.lastDepth = t.depth, e.lastDirection = t.direction;
|
|
3929
|
-
const
|
|
3930
|
-
this.set("scrollEventCount",
|
|
4110
|
+
const n = this.get("scrollEventCount") ?? 0;
|
|
4111
|
+
this.set("scrollEventCount", n + 1), this.eventManager.track({
|
|
3931
4112
|
type: u.SCROLL,
|
|
3932
4113
|
scroll_data: {
|
|
3933
4114
|
...t,
|
|
@@ -3968,21 +4149,21 @@ class Ms extends _ {
|
|
|
3968
4149
|
calculateScrollDepth(e, t, s) {
|
|
3969
4150
|
if (t <= s)
|
|
3970
4151
|
return 0;
|
|
3971
|
-
const
|
|
3972
|
-
return Math.min(100, Math.max(0, Math.floor(e /
|
|
4152
|
+
const n = t - s;
|
|
4153
|
+
return Math.min(100, Math.max(0, Math.floor(e / n * 100)));
|
|
3973
4154
|
}
|
|
3974
4155
|
calculateScrollData(e) {
|
|
3975
|
-
const { element: t, lastScrollPos: s, lastEventTime:
|
|
4156
|
+
const { element: t, lastScrollPos: s, lastEventTime: n } = e, i = this.getScrollTop(t), o = Date.now(), l = Math.abs(i - s);
|
|
3976
4157
|
if (l < 10 || t === window && !this.isWindowScrollable())
|
|
3977
4158
|
return null;
|
|
3978
|
-
const
|
|
3979
|
-
let
|
|
3980
|
-
|
|
3981
|
-
const
|
|
3982
|
-
return
|
|
3983
|
-
depth:
|
|
4159
|
+
const d = this.getViewportHeight(t), c = this.getScrollHeight(t), f = this.getScrollDirection(i, s), m = this.calculateScrollDepth(i, c, d);
|
|
4160
|
+
let g;
|
|
4161
|
+
n > 0 ? g = o - n : e.firstScrollEventTime !== null ? g = o - e.firstScrollEventTime : g = 250;
|
|
4162
|
+
const E = Math.round(l / g * 1e3);
|
|
4163
|
+
return m > e.maxDepthReached && (e.maxDepthReached = m), e.lastScrollPos = i, {
|
|
4164
|
+
depth: m,
|
|
3984
4165
|
direction: f,
|
|
3985
|
-
velocity:
|
|
4166
|
+
velocity: E,
|
|
3986
4167
|
max_depth_reached: e.maxDepthReached
|
|
3987
4168
|
};
|
|
3988
4169
|
}
|
|
@@ -3996,24 +4177,24 @@ class Ms extends _ {
|
|
|
3996
4177
|
return e === window ? document.documentElement.scrollHeight : e.scrollHeight;
|
|
3997
4178
|
}
|
|
3998
4179
|
isElementScrollable(e) {
|
|
3999
|
-
const t = getComputedStyle(e), s = t.overflowY === "auto" || t.overflowY === "scroll" || t.overflow === "auto" || t.overflow === "scroll",
|
|
4000
|
-
return s &&
|
|
4180
|
+
const t = getComputedStyle(e), s = t.overflowY === "auto" || t.overflowY === "scroll" || t.overflow === "auto" || t.overflow === "scroll", n = e.scrollHeight > e.clientHeight;
|
|
4181
|
+
return s && n;
|
|
4001
4182
|
}
|
|
4002
4183
|
applyPrimaryScrollSelector(e) {
|
|
4003
4184
|
let t;
|
|
4004
4185
|
if (e === "window")
|
|
4005
4186
|
t = window;
|
|
4006
4187
|
else {
|
|
4007
|
-
const
|
|
4008
|
-
if (!(
|
|
4188
|
+
const n = document.querySelector(e);
|
|
4189
|
+
if (!(n instanceof HTMLElement)) {
|
|
4009
4190
|
a("debug", `Selector "${e}" did not match an HTMLElement`);
|
|
4010
4191
|
return;
|
|
4011
4192
|
}
|
|
4012
|
-
t =
|
|
4193
|
+
t = n;
|
|
4013
4194
|
}
|
|
4014
|
-
this.containers.forEach((
|
|
4015
|
-
this.updateContainerPrimary(
|
|
4016
|
-
}), !this.containers.some((
|
|
4195
|
+
this.containers.forEach((n) => {
|
|
4196
|
+
this.updateContainerPrimary(n, n.element === t);
|
|
4197
|
+
}), !this.containers.some((n) => n.element === t) && t instanceof HTMLElement && this.isElementScrollable(t) && this.setupScrollContainer(t, e);
|
|
4017
4198
|
}
|
|
4018
4199
|
updateContainerPrimary(e, t) {
|
|
4019
4200
|
e.isPrimary = t;
|
|
@@ -4071,8 +4252,8 @@ class Cs extends _ {
|
|
|
4071
4252
|
let t = this.trackedElements.size;
|
|
4072
4253
|
for (const s of this.config.elements)
|
|
4073
4254
|
try {
|
|
4074
|
-
const
|
|
4075
|
-
for (const
|
|
4255
|
+
const n = document.querySelectorAll(s.selector);
|
|
4256
|
+
for (const i of Array.from(n)) {
|
|
4076
4257
|
if (t >= e) {
|
|
4077
4258
|
a("debug", "ViewportHandler: Maximum tracked elements reached", {
|
|
4078
4259
|
data: {
|
|
@@ -4083,18 +4264,18 @@ class Cs extends _ {
|
|
|
4083
4264
|
});
|
|
4084
4265
|
return;
|
|
4085
4266
|
}
|
|
4086
|
-
|
|
4087
|
-
element:
|
|
4267
|
+
i.hasAttribute(`${b}-ignore`) || this.trackedElements.has(i) || (this.trackedElements.set(i, {
|
|
4268
|
+
element: i,
|
|
4088
4269
|
selector: s.selector,
|
|
4089
4270
|
id: s.id,
|
|
4090
4271
|
name: s.name,
|
|
4091
4272
|
startTime: null,
|
|
4092
4273
|
timeoutId: null,
|
|
4093
4274
|
lastFiredTime: null
|
|
4094
|
-
}), this.observer?.observe(
|
|
4275
|
+
}), this.observer?.observe(i), t++);
|
|
4095
4276
|
}
|
|
4096
|
-
} catch (
|
|
4097
|
-
a("debug", `ViewportHandler: Invalid selector "${s.selector}"`, { error:
|
|
4277
|
+
} catch (n) {
|
|
4278
|
+
a("debug", `ViewportHandler: Invalid selector "${s.selector}"`, { error: n });
|
|
4098
4279
|
}
|
|
4099
4280
|
a("debug", "ViewportHandler: Elements tracked", {
|
|
4100
4281
|
data: { count: t, limit: e }
|
|
@@ -4107,11 +4288,11 @@ class Cs extends _ {
|
|
|
4107
4288
|
if (!this.config) return;
|
|
4108
4289
|
const t = this.config.minDwellTime ?? 1e3;
|
|
4109
4290
|
for (const s of e) {
|
|
4110
|
-
const
|
|
4111
|
-
|
|
4112
|
-
const
|
|
4113
|
-
this.fireViewportEvent(
|
|
4114
|
-
}, t)) :
|
|
4291
|
+
const n = this.trackedElements.get(s.target);
|
|
4292
|
+
n && (s.isIntersecting ? n.startTime === null && (n.startTime = performance.now(), n.timeoutId = window.setTimeout(() => {
|
|
4293
|
+
const i = Math.round(s.intersectionRatio * 100) / 100;
|
|
4294
|
+
this.fireViewportEvent(n, i);
|
|
4295
|
+
}, t)) : n.startTime !== null && (n.timeoutId !== null && (window.clearTimeout(n.timeoutId), n.timeoutId = null), n.startTime = null));
|
|
4115
4296
|
}
|
|
4116
4297
|
};
|
|
4117
4298
|
/**
|
|
@@ -4122,12 +4303,12 @@ class Cs extends _ {
|
|
|
4122
4303
|
const s = Math.round(performance.now() - e.startTime);
|
|
4123
4304
|
if (e.element.hasAttribute(`${b}-ignore`))
|
|
4124
4305
|
return;
|
|
4125
|
-
const
|
|
4126
|
-
if (e.lastFiredTime !== null &&
|
|
4306
|
+
const n = this.config?.cooldownPeriod ?? 6e4, i = Date.now();
|
|
4307
|
+
if (e.lastFiredTime !== null && i - e.lastFiredTime < n) {
|
|
4127
4308
|
a("debug", "ViewportHandler: Event suppressed by cooldown period", {
|
|
4128
4309
|
data: {
|
|
4129
4310
|
selector: e.selector,
|
|
4130
|
-
cooldownRemaining:
|
|
4311
|
+
cooldownRemaining: n - (i - e.lastFiredTime)
|
|
4131
4312
|
}
|
|
4132
4313
|
}), e.startTime = null, e.timeoutId = null;
|
|
4133
4314
|
return;
|
|
@@ -4142,7 +4323,7 @@ class Cs extends _ {
|
|
|
4142
4323
|
this.eventManager.track({
|
|
4143
4324
|
type: u.VIEWPORT_VISIBLE,
|
|
4144
4325
|
viewport_data: o
|
|
4145
|
-
}), e.startTime = null, e.timeoutId = null, e.lastFiredTime =
|
|
4326
|
+
}), e.startTime = null, e.timeoutId = null, e.lastFiredTime = i;
|
|
4146
4327
|
}
|
|
4147
4328
|
/**
|
|
4148
4329
|
* Sets up MutationObserver to detect dynamically added elements
|
|
@@ -4172,58 +4353,75 @@ class Cs extends _ {
|
|
|
4172
4353
|
cleanupRemovedNodes(e) {
|
|
4173
4354
|
e.forEach((t) => {
|
|
4174
4355
|
if (t.nodeType !== 1) return;
|
|
4175
|
-
const s = t,
|
|
4176
|
-
|
|
4356
|
+
const s = t, n = this.trackedElements.get(s);
|
|
4357
|
+
n && (n.timeoutId !== null && window.clearTimeout(n.timeoutId), this.observer?.unobserve(s), this.trackedElements.delete(s)), Array.from(this.trackedElements.keys()).filter((o) => s.contains(o)).forEach((o) => {
|
|
4177
4358
|
const l = this.trackedElements.get(o);
|
|
4178
4359
|
l && l.timeoutId !== null && window.clearTimeout(l.timeoutId), this.observer?.unobserve(o), this.trackedElements.delete(o);
|
|
4179
4360
|
});
|
|
4180
4361
|
});
|
|
4181
4362
|
}
|
|
4182
4363
|
}
|
|
4183
|
-
const Rs = "tracelog_session_id";
|
|
4184
|
-
class
|
|
4364
|
+
const Rs = "tracelog_session_id", Ns = "tracelog_user_id";
|
|
4365
|
+
class Os extends _ {
|
|
4185
4366
|
visibilityHandler = null;
|
|
4186
|
-
|
|
4367
|
+
pageshowHandler = null;
|
|
4368
|
+
lastSyncedKey = null;
|
|
4187
4369
|
activate() {
|
|
4188
|
-
this.
|
|
4370
|
+
this.cleanupListeners(), this.syncCartAttribute(), this.setupListeners();
|
|
4189
4371
|
}
|
|
4190
4372
|
deactivate() {
|
|
4191
|
-
this.
|
|
4373
|
+
this.cleanupListeners(), this.lastSyncedKey = null;
|
|
4192
4374
|
}
|
|
4193
|
-
/** Re-syncs
|
|
4375
|
+
/** Re-syncs cart attributes when session rotates (called by App on SESSION_START). */
|
|
4194
4376
|
onSessionChange() {
|
|
4195
4377
|
this.syncCartAttribute();
|
|
4196
4378
|
}
|
|
4197
4379
|
syncCartAttribute() {
|
|
4198
4380
|
const e = this.get("sessionId");
|
|
4199
|
-
|
|
4381
|
+
if (!e) return;
|
|
4382
|
+
const t = this.get("userId"), s = typeof t == "string" && t.length > 0 ? t : "", n = `${e}|${s}`;
|
|
4383
|
+
n !== this.lastSyncedKey && (this.lastSyncedKey = n, this.postCartUpdate(e, s));
|
|
4200
4384
|
}
|
|
4201
|
-
postCartUpdate(e) {
|
|
4385
|
+
postCartUpdate(e, t) {
|
|
4386
|
+
const s = { [Rs]: e };
|
|
4387
|
+
t.length > 0 && (s[Ns] = t);
|
|
4202
4388
|
try {
|
|
4203
4389
|
fetch("/cart/update.js", {
|
|
4204
4390
|
method: "POST",
|
|
4205
4391
|
headers: { "Content-Type": "application/json" },
|
|
4206
|
-
body: JSON.stringify({ attributes:
|
|
4392
|
+
body: JSON.stringify({ attributes: s }),
|
|
4207
4393
|
credentials: "same-origin"
|
|
4208
|
-
}).then((
|
|
4209
|
-
|
|
4394
|
+
}).then((n) => {
|
|
4395
|
+
n.ok || (this.lastSyncedKey = null, a("debug", "Shopify cart attribute update failed", { data: { status: n.status } }));
|
|
4210
4396
|
}).catch(() => {
|
|
4211
|
-
this.
|
|
4397
|
+
this.lastSyncedKey = null, a("debug", "Shopify cart attribute update failed");
|
|
4212
4398
|
});
|
|
4213
4399
|
} catch {
|
|
4214
|
-
this.
|
|
4400
|
+
this.lastSyncedKey = null, a("debug", "Shopify cart attribute update failed");
|
|
4215
4401
|
}
|
|
4216
4402
|
}
|
|
4217
|
-
|
|
4403
|
+
/**
|
|
4404
|
+
* Sync triggers (theme-agnostic):
|
|
4405
|
+
* - `visibilitychange`: catches tab refocus (long sessions, OAuth round-trips).
|
|
4406
|
+
* - `pageshow` with `event.persisted === true`: catches bfcache restore so a
|
|
4407
|
+
* user returning from an external checkout / Shop Pay window picks up the
|
|
4408
|
+
* current sessionId before any further interaction.
|
|
4409
|
+
*
|
|
4410
|
+
* Both triggers go through `syncCartAttribute()` which dedupes by
|
|
4411
|
+
* `sessionId|userId`, so spurious calls cost nothing.
|
|
4412
|
+
*/
|
|
4413
|
+
setupListeners() {
|
|
4218
4414
|
this.visibilityHandler = () => {
|
|
4219
4415
|
document.hidden || this.syncCartAttribute();
|
|
4220
|
-
}, document.addEventListener("visibilitychange", this.visibilityHandler)
|
|
4416
|
+
}, document.addEventListener("visibilitychange", this.visibilityHandler), this.pageshowHandler = (e) => {
|
|
4417
|
+
e.persisted && this.syncCartAttribute();
|
|
4418
|
+
}, window.addEventListener("pageshow", this.pageshowHandler);
|
|
4221
4419
|
}
|
|
4222
|
-
|
|
4223
|
-
this.visibilityHandler && (document.removeEventListener("visibilitychange", this.visibilityHandler), this.visibilityHandler = null);
|
|
4420
|
+
cleanupListeners() {
|
|
4421
|
+
this.visibilityHandler && (document.removeEventListener("visibilitychange", this.visibilityHandler), this.visibilityHandler = null), this.pageshowHandler && (window.removeEventListener("pageshow", this.pageshowHandler), this.pageshowHandler = null);
|
|
4224
4422
|
}
|
|
4225
4423
|
}
|
|
4226
|
-
class
|
|
4424
|
+
class Ps {
|
|
4227
4425
|
storage;
|
|
4228
4426
|
sessionStorageRef;
|
|
4229
4427
|
fallbackStorage = /* @__PURE__ */ new Map();
|
|
@@ -4392,19 +4590,19 @@ class Os {
|
|
|
4392
4590
|
return !1;
|
|
4393
4591
|
try {
|
|
4394
4592
|
const e = [], t = [];
|
|
4395
|
-
for (let
|
|
4396
|
-
const o = this.storage.key(
|
|
4593
|
+
for (let i = 0; i < this.storage.length; i++) {
|
|
4594
|
+
const o = this.storage.key(i);
|
|
4397
4595
|
o?.startsWith("tracelog_") && (e.push(o), o.startsWith("tracelog_persisted_events_") && t.push(o));
|
|
4398
4596
|
}
|
|
4399
4597
|
if (t.length > 0)
|
|
4400
|
-
return t.forEach((
|
|
4598
|
+
return t.forEach((i) => {
|
|
4401
4599
|
try {
|
|
4402
|
-
this.storage.removeItem(
|
|
4600
|
+
this.storage.removeItem(i);
|
|
4403
4601
|
} catch {
|
|
4404
4602
|
}
|
|
4405
4603
|
}), !0;
|
|
4406
|
-
const s = ["tracelog_session_", "tracelog_user_id", "tracelog_device_id", "tracelog_config"],
|
|
4407
|
-
return
|
|
4604
|
+
const s = ["tracelog_session_", "tracelog_user_id", "tracelog_device_id", "tracelog_config"], n = e.filter((i) => !s.some((o) => i.startsWith(o)));
|
|
4605
|
+
return n.length > 0 ? (n.slice(0, 5).forEach((o) => {
|
|
4408
4606
|
try {
|
|
4409
4607
|
this.storage.removeItem(o);
|
|
4410
4608
|
} catch {
|
|
@@ -4506,7 +4704,7 @@ class Os {
|
|
|
4506
4704
|
this.fallbackSessionStorage.delete(e);
|
|
4507
4705
|
}
|
|
4508
4706
|
}
|
|
4509
|
-
class
|
|
4707
|
+
class Ds extends _ {
|
|
4510
4708
|
eventManager;
|
|
4511
4709
|
reportedByNav = /* @__PURE__ */ new Map();
|
|
4512
4710
|
navigationHistory = [];
|
|
@@ -4517,7 +4715,7 @@ class Ps extends _ {
|
|
|
4517
4715
|
navigationCounter = 0;
|
|
4518
4716
|
// Counter for handling simultaneous navigations edge case
|
|
4519
4717
|
constructor(e) {
|
|
4520
|
-
super(), this.eventManager = e, this.vitalThresholds =
|
|
4718
|
+
super(), this.eventManager = e, this.vitalThresholds = ze(ye);
|
|
4521
4719
|
}
|
|
4522
4720
|
/**
|
|
4523
4721
|
* Starts tracking Web Vitals and performance metrics.
|
|
@@ -4534,8 +4732,8 @@ class Ps extends _ {
|
|
|
4534
4732
|
* @returns Promise that resolves when tracking is initialized
|
|
4535
4733
|
*/
|
|
4536
4734
|
async startTracking() {
|
|
4537
|
-
const e = this.get("config"), t = e?.webVitalsMode ??
|
|
4538
|
-
this.vitalThresholds =
|
|
4735
|
+
const e = this.get("config"), t = e?.webVitalsMode ?? ye;
|
|
4736
|
+
this.vitalThresholds = ze(t), e?.webVitalsThresholds && (this.vitalThresholds = { ...this.vitalThresholds, ...e.webVitalsThresholds }), await this.initWebVitals(), this.observeLongTasks();
|
|
4539
4737
|
}
|
|
4540
4738
|
/**
|
|
4541
4739
|
* Stops tracking Web Vitals and cleans up resources.
|
|
@@ -4559,8 +4757,8 @@ class Ps extends _ {
|
|
|
4559
4757
|
this.reportTTFB(), this.safeObserve(
|
|
4560
4758
|
"largest-contentful-paint",
|
|
4561
4759
|
(s) => {
|
|
4562
|
-
const
|
|
4563
|
-
|
|
4760
|
+
const n = s.getEntries(), i = n[n.length - 1];
|
|
4761
|
+
i && this.sendVital({ type: "LCP", value: Number(i.startTime.toFixed(2)) });
|
|
4564
4762
|
},
|
|
4565
4763
|
{ type: "largest-contentful-paint", buffered: !0 },
|
|
4566
4764
|
!0
|
|
@@ -4569,10 +4767,10 @@ class Ps extends _ {
|
|
|
4569
4767
|
this.safeObserve(
|
|
4570
4768
|
"layout-shift",
|
|
4571
4769
|
(s) => {
|
|
4572
|
-
const
|
|
4573
|
-
|
|
4574
|
-
const
|
|
4575
|
-
for (const o of
|
|
4770
|
+
const n = this.getNavigationId();
|
|
4771
|
+
n !== t && (e = 0, t = n);
|
|
4772
|
+
const i = s.getEntries();
|
|
4773
|
+
for (const o of i) {
|
|
4576
4774
|
if (o.hadRecentInput === !0)
|
|
4577
4775
|
continue;
|
|
4578
4776
|
const l = typeof o.value == "number" ? o.value : 0;
|
|
@@ -4584,32 +4782,32 @@ class Ps extends _ {
|
|
|
4584
4782
|
), this.safeObserve(
|
|
4585
4783
|
"paint",
|
|
4586
4784
|
(s) => {
|
|
4587
|
-
for (const
|
|
4588
|
-
|
|
4785
|
+
for (const n of s.getEntries())
|
|
4786
|
+
n.name === "first-contentful-paint" && this.sendVital({ type: "FCP", value: Number(n.startTime.toFixed(2)) });
|
|
4589
4787
|
},
|
|
4590
4788
|
{ type: "paint", buffered: !0 },
|
|
4591
4789
|
!0
|
|
4592
4790
|
), this.safeObserve(
|
|
4593
4791
|
"event",
|
|
4594
4792
|
(s) => {
|
|
4595
|
-
let
|
|
4596
|
-
const
|
|
4597
|
-
for (const o of
|
|
4793
|
+
let n = 0;
|
|
4794
|
+
const i = s.getEntries();
|
|
4795
|
+
for (const o of i) {
|
|
4598
4796
|
const l = (o.processingEnd ?? 0) - (o.startTime ?? 0);
|
|
4599
|
-
|
|
4797
|
+
n = Math.max(n, l);
|
|
4600
4798
|
}
|
|
4601
|
-
|
|
4799
|
+
n > 0 && this.sendVital({ type: "INP", value: Number(n.toFixed(2)) });
|
|
4602
4800
|
},
|
|
4603
4801
|
{ type: "event", buffered: !0 }
|
|
4604
4802
|
);
|
|
4605
4803
|
}
|
|
4606
4804
|
async initWebVitals() {
|
|
4607
4805
|
try {
|
|
4608
|
-
const { onLCP: e, onCLS: t, onFCP: s, onTTFB:
|
|
4609
|
-
const
|
|
4610
|
-
this.sendVital({ type: l, value:
|
|
4806
|
+
const { onLCP: e, onCLS: t, onFCP: s, onTTFB: n, onINP: i } = await Promise.resolve().then(() => mr), o = (l) => (d) => {
|
|
4807
|
+
const c = Number(d.value.toFixed(2));
|
|
4808
|
+
this.sendVital({ type: l, value: c });
|
|
4611
4809
|
};
|
|
4612
|
-
e(o("LCP"), { reportAllChanges: !1 }), t(o("CLS"), { reportAllChanges: !1 }), s(o("FCP"), { reportAllChanges: !1 }),
|
|
4810
|
+
e(o("LCP"), { reportAllChanges: !1 }), t(o("CLS"), { reportAllChanges: !1 }), s(o("FCP"), { reportAllChanges: !1 }), n(o("TTFB"), { reportAllChanges: !1 }), i(o("INP"), { reportAllChanges: !1 });
|
|
4613
4811
|
} catch (e) {
|
|
4614
4812
|
a("debug", "Failed to load web-vitals library, using fallback", { error: e }), this.observeWebVitalsFallback();
|
|
4615
4813
|
}
|
|
@@ -4631,8 +4829,8 @@ class Ps extends _ {
|
|
|
4631
4829
|
(e) => {
|
|
4632
4830
|
const t = e.getEntries();
|
|
4633
4831
|
for (const s of t) {
|
|
4634
|
-
const
|
|
4635
|
-
|
|
4832
|
+
const n = Number(s.duration.toFixed(2)), i = Date.now();
|
|
4833
|
+
i - this.lastLongTaskSentAt >= qt && (this.shouldSendVital("LONG_TASK", n) && this.trackWebVital("LONG_TASK", n), this.lastLongTaskSentAt = i);
|
|
4636
4834
|
}
|
|
4637
4835
|
},
|
|
4638
4836
|
{ type: "longtask", buffered: !0 }
|
|
@@ -4649,8 +4847,8 @@ class Ps extends _ {
|
|
|
4649
4847
|
if (s)
|
|
4650
4848
|
s.add(e.type);
|
|
4651
4849
|
else if (this.reportedByNav.set(t, /* @__PURE__ */ new Set([e.type])), this.navigationHistory.push(t), this.navigationHistory.length > Jt) {
|
|
4652
|
-
const
|
|
4653
|
-
|
|
4850
|
+
const i = this.navigationHistory.shift();
|
|
4851
|
+
i && this.reportedByNav.delete(i);
|
|
4654
4852
|
}
|
|
4655
4853
|
}
|
|
4656
4854
|
this.trackWebVital(e.type, e.value);
|
|
@@ -4694,8 +4892,8 @@ class Ps extends _ {
|
|
|
4694
4892
|
const e = performance.getEntriesByType("navigation")[0];
|
|
4695
4893
|
if (!e)
|
|
4696
4894
|
return null;
|
|
4697
|
-
const t = e.startTime || performance.now(), s = ++this.navigationCounter,
|
|
4698
|
-
return s > 1 ? `${
|
|
4895
|
+
const t = e.startTime || performance.now(), s = ++this.navigationCounter, n = `${t.toFixed(2)}_${window.location.pathname}`;
|
|
4896
|
+
return s > 1 ? `${n}_${s}` : n;
|
|
4699
4897
|
} catch (e) {
|
|
4700
4898
|
return a("debug", "Failed to get navigation ID", { error: e }), null;
|
|
4701
4899
|
}
|
|
@@ -4705,29 +4903,29 @@ class Ps extends _ {
|
|
|
4705
4903
|
const t = PerformanceObserver.supportedEntryTypes;
|
|
4706
4904
|
return !t || t.includes(e);
|
|
4707
4905
|
}
|
|
4708
|
-
safeObserve(e, t, s,
|
|
4906
|
+
safeObserve(e, t, s, n = !1) {
|
|
4709
4907
|
try {
|
|
4710
4908
|
if (!this.isObserverSupported(e))
|
|
4711
4909
|
return !1;
|
|
4712
|
-
const
|
|
4910
|
+
const i = new PerformanceObserver((o, l) => {
|
|
4713
4911
|
try {
|
|
4714
4912
|
t(o, l);
|
|
4715
|
-
} catch (
|
|
4913
|
+
} catch (d) {
|
|
4716
4914
|
a("debug", "Observer callback failed", {
|
|
4717
|
-
error:
|
|
4915
|
+
error: d,
|
|
4718
4916
|
data: { type: e }
|
|
4719
4917
|
});
|
|
4720
4918
|
}
|
|
4721
|
-
if (
|
|
4919
|
+
if (n)
|
|
4722
4920
|
try {
|
|
4723
4921
|
l.disconnect();
|
|
4724
4922
|
} catch {
|
|
4725
4923
|
}
|
|
4726
4924
|
});
|
|
4727
|
-
return
|
|
4728
|
-
} catch (
|
|
4925
|
+
return i.observe(s ?? { type: e, buffered: !0 }), n || this.observers.push(i), !0;
|
|
4926
|
+
} catch (i) {
|
|
4729
4927
|
return a("debug", "Failed to create performance observer", {
|
|
4730
|
-
error:
|
|
4928
|
+
error: i,
|
|
4731
4929
|
data: { type: e }
|
|
4732
4930
|
}), !1;
|
|
4733
4931
|
}
|
|
@@ -4775,11 +4973,11 @@ class ae extends _ {
|
|
|
4775
4973
|
const e = Date.now();
|
|
4776
4974
|
if (e < this.burstBackoffUntil)
|
|
4777
4975
|
return !1;
|
|
4778
|
-
if (e - this.burstWindowStart > jt && (this.errorBurstCounter = 0, this.burstWindowStart = e), this.errorBurstCounter++, this.errorBurstCounter >
|
|
4779
|
-
return this.burstBackoffUntil = e +
|
|
4976
|
+
if (e - this.burstWindowStart > jt && (this.errorBurstCounter = 0, this.burstWindowStart = e), this.errorBurstCounter++, this.errorBurstCounter > Kt)
|
|
4977
|
+
return this.burstBackoffUntil = e + Ke, a("debug", "Error burst detected - entering cooldown", {
|
|
4780
4978
|
data: {
|
|
4781
4979
|
errorsInWindow: this.errorBurstCounter,
|
|
4782
|
-
cooldownMs:
|
|
4980
|
+
cooldownMs: Ke
|
|
4783
4981
|
}
|
|
4784
4982
|
}), !1;
|
|
4785
4983
|
const s = this.get("config").errorSampling ?? lt;
|
|
@@ -4791,12 +4989,13 @@ class ae extends _ {
|
|
|
4791
4989
|
const t = this.sanitize(e.message || "Unknown error");
|
|
4792
4990
|
if (this.shouldSuppressError(B.JS_ERROR, t))
|
|
4793
4991
|
return;
|
|
4794
|
-
const s = typeof e.error?.stack == "string" ? this.truncateStack(e.error.stack) : void 0;
|
|
4992
|
+
const s = typeof e.error?.stack == "string" ? this.truncateStack(e.error.stack) : void 0, n = typeof e.error?.name == "string" && e.error.name !== "Error" ? e.error.name : void 0;
|
|
4795
4993
|
this.eventManager.track({
|
|
4796
4994
|
type: u.ERROR,
|
|
4797
4995
|
error_data: {
|
|
4798
4996
|
type: B.JS_ERROR,
|
|
4799
4997
|
message: t,
|
|
4998
|
+
...n !== void 0 && { name: n },
|
|
4800
4999
|
...e.filename !== "" && { filename: e.filename },
|
|
4801
5000
|
...e.lineno !== 0 && { line: e.lineno },
|
|
4802
5001
|
...e.colno !== 0 && { column: e.colno },
|
|
@@ -4810,13 +5009,14 @@ class ae extends _ {
|
|
|
4810
5009
|
const t = this.extractRejectionMessage(e.reason), s = this.sanitize(t);
|
|
4811
5010
|
if (this.shouldSuppressError(B.PROMISE_REJECTION, s))
|
|
4812
5011
|
return;
|
|
4813
|
-
const
|
|
5012
|
+
const n = e.reason instanceof Error && typeof e.reason.stack == "string" ? this.truncateStack(e.reason.stack) : void 0, i = e.reason instanceof Error && e.reason.name !== "Error" ? e.reason.name : void 0;
|
|
4814
5013
|
this.eventManager.track({
|
|
4815
5014
|
type: u.ERROR,
|
|
4816
5015
|
error_data: {
|
|
4817
5016
|
type: B.PROMISE_REJECTION,
|
|
4818
5017
|
message: s,
|
|
4819
|
-
...i !== void 0 && {
|
|
5018
|
+
...i !== void 0 && { name: i },
|
|
5019
|
+
...n !== void 0 && { stack: n }
|
|
4820
5020
|
}
|
|
4821
5021
|
});
|
|
4822
5022
|
};
|
|
@@ -4834,46 +5034,48 @@ class ae extends _ {
|
|
|
4834
5034
|
}
|
|
4835
5035
|
}
|
|
4836
5036
|
sanitize(e) {
|
|
4837
|
-
const t = e.length >
|
|
5037
|
+
const t = e.length > Ge ? e.slice(0, Ge) + "..." : e;
|
|
4838
5038
|
return this.sanitizePii(t);
|
|
4839
5039
|
}
|
|
4840
5040
|
sanitizePii(e) {
|
|
4841
5041
|
let t = e;
|
|
4842
5042
|
for (const s of at) {
|
|
4843
|
-
const
|
|
4844
|
-
t = t.replace(
|
|
5043
|
+
const n = new RegExp(s.source, s.flags);
|
|
5044
|
+
t = t.replace(n, "[REDACTED]");
|
|
4845
5045
|
}
|
|
4846
5046
|
return t;
|
|
4847
5047
|
}
|
|
4848
5048
|
shouldSuppressError(e, t) {
|
|
4849
|
-
const s = Date.now(),
|
|
4850
|
-
return
|
|
5049
|
+
const s = Date.now(), n = `${e}:${t}`, i = this.recentErrors.get(n);
|
|
5050
|
+
return i !== void 0 && s - i < je ? (this.recentErrors.set(n, s), !0) : (this.recentErrors.set(n, s), this.recentErrors.size > Xt ? (this.recentErrors.clear(), this.recentErrors.set(n, s), !1) : (this.recentErrors.size > ee && this.pruneOldErrors(), !1));
|
|
4851
5051
|
}
|
|
4852
5052
|
static TRUNCATION_SUFFIX = `
|
|
4853
5053
|
...truncated`;
|
|
4854
5054
|
truncateStack(e) {
|
|
4855
|
-
if (e.length <=
|
|
4856
|
-
const t =
|
|
5055
|
+
if (e.length <= Xe) return this.sanitizePii(e);
|
|
5056
|
+
const t = Xe - ae.TRUNCATION_SUFFIX.length, s = e.slice(0, t) + ae.TRUNCATION_SUFFIX;
|
|
4857
5057
|
return this.sanitizePii(s);
|
|
4858
5058
|
}
|
|
4859
5059
|
pruneOldErrors() {
|
|
4860
5060
|
const e = Date.now();
|
|
4861
|
-
for (const [
|
|
4862
|
-
e -
|
|
5061
|
+
for (const [n, i] of this.recentErrors.entries())
|
|
5062
|
+
e - i > je && this.recentErrors.delete(n);
|
|
4863
5063
|
if (this.recentErrors.size <= ee)
|
|
4864
5064
|
return;
|
|
4865
|
-
const t = Array.from(this.recentErrors.entries()).sort((
|
|
4866
|
-
for (let
|
|
4867
|
-
const
|
|
4868
|
-
|
|
5065
|
+
const t = Array.from(this.recentErrors.entries()).sort((n, i) => n[1] - i[1]), s = this.recentErrors.size - ee;
|
|
5066
|
+
for (let n = 0; n < s; n += 1) {
|
|
5067
|
+
const i = t[n];
|
|
5068
|
+
i && this.recentErrors.delete(i[0]);
|
|
4869
5069
|
}
|
|
4870
5070
|
}
|
|
4871
5071
|
}
|
|
4872
|
-
class
|
|
5072
|
+
class ks extends _ {
|
|
4873
5073
|
isInitialized = !1;
|
|
4874
5074
|
suppressNextScrollTimer = null;
|
|
4875
5075
|
pageUnloadHandler = null;
|
|
4876
|
-
|
|
5076
|
+
pageShowHandler = null;
|
|
5077
|
+
visibilityFlushHandler = null;
|
|
5078
|
+
emitter = new Es();
|
|
4877
5079
|
transformers = {};
|
|
4878
5080
|
customHeadersProvider;
|
|
4879
5081
|
managers = {};
|
|
@@ -4892,19 +5094,19 @@ class Ds extends _ {
|
|
|
4892
5094
|
async init(e = {}) {
|
|
4893
5095
|
if (this.isInitialized)
|
|
4894
5096
|
return { sessionId: this.get("sessionId") ?? "" };
|
|
4895
|
-
this.managers.storage = new
|
|
5097
|
+
this.managers.storage = new Ps();
|
|
4896
5098
|
try {
|
|
4897
5099
|
this.setupState(e);
|
|
4898
5100
|
const t = e.integrations?.custom?.headers ?? {}, s = e.integrations?.custom?.fetchCredentials ?? "include";
|
|
4899
|
-
return this.managers.event = new
|
|
5101
|
+
return this.managers.event = new Is(
|
|
4900
5102
|
this.managers.storage,
|
|
4901
5103
|
this.emitter,
|
|
4902
5104
|
this.transformers,
|
|
4903
5105
|
t,
|
|
4904
5106
|
this.customHeadersProvider,
|
|
4905
5107
|
s
|
|
4906
|
-
), this.loadPersistedIdentity(), this.initializeHandlers(), this.setupPageLifecycleListeners(), await this.managers.event.recoverPersistedEvents().catch((
|
|
4907
|
-
a("warn", "Failed to recover persisted events", { error:
|
|
5108
|
+
), this.loadPersistedIdentity(), this.initializeHandlers(), this.setupPageLifecycleListeners(), await this.managers.event.recoverPersistedEvents().catch((n) => {
|
|
5109
|
+
a("warn", "Failed to recover persisted events", { error: n });
|
|
4908
5110
|
}), this.isInitialized = !0, { sessionId: this.get("sessionId") ?? "" };
|
|
4909
5111
|
} catch (t) {
|
|
4910
5112
|
this.destroy(!0);
|
|
@@ -4913,33 +5115,74 @@ class Ds extends _ {
|
|
|
4913
5115
|
}
|
|
4914
5116
|
}
|
|
4915
5117
|
/**
|
|
4916
|
-
*
|
|
5118
|
+
* Asynchronously flushes all pending events in the queue.
|
|
5119
|
+
*
|
|
5120
|
+
* Internally calls `EventManager.flushImmediately()` which uses `fetch()` with retries.
|
|
5121
|
+
* Use when you need to force-send buffered events without waiting for the next send interval
|
|
5122
|
+
* (e.g., before a critical user action like sign-out, or before a SPA route teardown).
|
|
5123
|
+
*
|
|
5124
|
+
* @returns Promise<boolean> — `true` if all integrations sent successfully, `false` otherwise
|
|
5125
|
+
* @internal Called from api.flushImmediately()
|
|
5126
|
+
*/
|
|
5127
|
+
async flushImmediately() {
|
|
5128
|
+
return await this.managers.event?.flushImmediately() ?? !1;
|
|
5129
|
+
}
|
|
5130
|
+
/**
|
|
5131
|
+
* Synchronously flushes all pending events using `navigator.sendBeacon()`.
|
|
5132
|
+
*
|
|
5133
|
+
* Use only for page-unload scenarios (or equivalent) where async fetch may be cancelled.
|
|
5134
|
+
* For general flush needs, prefer {@link flushImmediately}.
|
|
5135
|
+
*
|
|
5136
|
+
* @returns `true` if all integrations sent successfully, `false` otherwise
|
|
5137
|
+
* @internal Called from api.flushImmediatelySync()
|
|
5138
|
+
*/
|
|
5139
|
+
flushImmediatelySync() {
|
|
5140
|
+
return this.managers.event?.flushImmediatelySync() ?? !1;
|
|
5141
|
+
}
|
|
5142
|
+
/**
|
|
5143
|
+
* Sends a custom event with optional metadata and options.
|
|
4917
5144
|
*
|
|
4918
5145
|
* @param name - Event name
|
|
4919
5146
|
* @param metadata - Optional metadata
|
|
5147
|
+
* @param options - Optional event options. `{ critical: true }` triggers the
|
|
5148
|
+
* double-write delivery path: (1) the just-tracked event is sent in its
|
|
5149
|
+
* own dedicated single-event `sendBeacon` (immune to the 64KB queue cap),
|
|
5150
|
+
* and (2) the main queue is drained too — deferred to the in-flight
|
|
5151
|
+
* async send's `finally` block when one is running, so events tracked
|
|
5152
|
+
* immediately before the critical one are not stranded. Backend must
|
|
5153
|
+
* deduplicate by `event.id` since both paths may deliver the same event.
|
|
5154
|
+
* No-op for events dropped by rate limiting / sampling / `beforeSend`.
|
|
4920
5155
|
* @internal Called from api.event()
|
|
4921
5156
|
*/
|
|
4922
|
-
sendCustomEvent(e, t) {
|
|
5157
|
+
sendCustomEvent(e, t, s) {
|
|
4923
5158
|
if (!this.managers.event) {
|
|
4924
5159
|
a("warn", "Cannot send custom event: TraceLog not initialized", { data: { name: e } });
|
|
4925
5160
|
return;
|
|
4926
5161
|
}
|
|
4927
|
-
let
|
|
4928
|
-
t && typeof t == "object" && !Array.isArray(t) && Object.getPrototypeOf(t) !== Object.prototype && (
|
|
4929
|
-
const { valid: i, error:
|
|
5162
|
+
let n = t;
|
|
5163
|
+
t && typeof t == "object" && !Array.isArray(t) && Object.getPrototypeOf(t) !== Object.prototype && (n = Object.assign({}, t));
|
|
5164
|
+
const { valid: i, error: o, sanitizedMetadata: l } = ps(e, n);
|
|
4930
5165
|
if (!i) {
|
|
4931
|
-
if (this.get("mode") ===
|
|
4932
|
-
throw new Error(`[TraceLog] Custom event "${e}" validation failed: ${
|
|
4933
|
-
a("warn", `Custom event "${e}" dropped: ${
|
|
5166
|
+
if (this.get("mode") === ie.QA)
|
|
5167
|
+
throw new Error(`[TraceLog] Custom event "${e}" validation failed: ${o}`);
|
|
5168
|
+
a("warn", `Custom event "${e}" dropped: ${o}`);
|
|
4934
5169
|
return;
|
|
4935
5170
|
}
|
|
4936
|
-
this.managers.event.
|
|
5171
|
+
const d = this.managers.event.getQueueLength();
|
|
5172
|
+
if (this.managers.event.track({
|
|
4937
5173
|
type: u.CUSTOM,
|
|
4938
5174
|
custom_event: {
|
|
4939
5175
|
name: e,
|
|
4940
|
-
...
|
|
5176
|
+
...l && { metadata: l }
|
|
4941
5177
|
}
|
|
4942
|
-
})
|
|
5178
|
+
}), s?.critical === !0) {
|
|
5179
|
+
if (!(this.managers.event.getQueueLength() > d)) {
|
|
5180
|
+
a("debug", "Critical event was dropped before queueing — no flush triggered", { data: { name: e } });
|
|
5181
|
+
return;
|
|
5182
|
+
}
|
|
5183
|
+
const f = this.managers.event.flushLastEventSync(), m = this.managers.event.flushImmediatelySync();
|
|
5184
|
+
!f && !m && a("debug", "Critical event: dedicated beacon and queue drain both failed", { data: { name: e } });
|
|
5185
|
+
}
|
|
4943
5186
|
}
|
|
4944
5187
|
on(e, t) {
|
|
4945
5188
|
this.emitter.on(e, t);
|
|
@@ -4992,7 +5235,7 @@ class Ds extends _ {
|
|
|
4992
5235
|
} catch (s) {
|
|
4993
5236
|
a("warn", "Failed to stop tracking", { error: s });
|
|
4994
5237
|
}
|
|
4995
|
-
}), this.suppressNextScrollTimer && (clearTimeout(this.suppressNextScrollTimer), this.suppressNextScrollTimer = null), this.pageUnloadHandler && (window.removeEventListener("pagehide", this.pageUnloadHandler), window.removeEventListener("beforeunload", this.pageUnloadHandler), this.pageUnloadHandler = null), this.managers.event?.flushImmediatelySync(), this.managers.event?.stop(), this.emitter.removeAllListeners(), this.transformers.beforeSend = void 0, this.transformers.beforeBatch = void 0, this.customHeadersProvider = void 0, this.set("suppressNextScroll", !1), this.set("sessionId", null), this.set("identity", void 0), this.clearPersistedIdentity(), this.integrationInstances.shopifyCartLinker?.deactivate(), this.integrationInstances = {}, this.isInitialized = !1, this.handlers = {}, this.managers = {});
|
|
5238
|
+
}), this.suppressNextScrollTimer && (clearTimeout(this.suppressNextScrollTimer), this.suppressNextScrollTimer = null), this.pageUnloadHandler && (window.removeEventListener("pagehide", this.pageUnloadHandler), window.removeEventListener("beforeunload", this.pageUnloadHandler), this.pageUnloadHandler = null), this.pageShowHandler && (window.removeEventListener("pageshow", this.pageShowHandler), this.pageShowHandler = null), this.visibilityFlushHandler && (document.removeEventListener("visibilitychange", this.visibilityFlushHandler), this.visibilityFlushHandler = null), this.managers.event?.flushImmediatelySync(), this.managers.event?.stop(), this.emitter.removeAllListeners(), this.transformers.beforeSend = void 0, this.transformers.beforeBatch = void 0, this.customHeadersProvider = void 0, this.set("suppressNextScroll", !1), this.set("sessionId", null), this.set("identity", void 0), this.clearPersistedIdentity(), this.integrationInstances.shopifyCartLinker?.deactivate(), this.integrationInstances = {}, this.isInitialized = !1, this.handlers = {}, this.managers = {});
|
|
4996
5239
|
}
|
|
4997
5240
|
setupState(e = {}) {
|
|
4998
5241
|
this.set("config", e);
|
|
@@ -5000,10 +5243,10 @@ class Ds extends _ {
|
|
|
5000
5243
|
this.set("userId", t);
|
|
5001
5244
|
const s = ls(e);
|
|
5002
5245
|
this.set("collectApiUrls", s);
|
|
5003
|
-
const
|
|
5004
|
-
this.set("device",
|
|
5005
|
-
const
|
|
5006
|
-
this.set("pageUrl",
|
|
5246
|
+
const n = Gt();
|
|
5247
|
+
this.set("device", n);
|
|
5248
|
+
const i = we(window.location.href, e.sensitiveQueryParams);
|
|
5249
|
+
this.set("pageUrl", i), ss() && this.set("mode", ie.QA);
|
|
5007
5250
|
}
|
|
5008
5251
|
/**
|
|
5009
5252
|
* Returns the current configuration object.
|
|
@@ -5071,11 +5314,11 @@ class Ds extends _ {
|
|
|
5071
5314
|
const t = this.validateGlobalMetadata(e);
|
|
5072
5315
|
if (!t.valid)
|
|
5073
5316
|
throw new Error(`[TraceLog] Invalid global metadata: ${t.error}`);
|
|
5074
|
-
const
|
|
5317
|
+
const n = {
|
|
5075
5318
|
...this.get("config"),
|
|
5076
5319
|
globalMetadata: e
|
|
5077
5320
|
};
|
|
5078
|
-
this.set("config",
|
|
5321
|
+
this.set("config", n), a("debug", "Global metadata updated (replaced)", { data: { keys: Object.keys(e) } });
|
|
5079
5322
|
}
|
|
5080
5323
|
/**
|
|
5081
5324
|
* Merges new metadata with existing global metadata.
|
|
@@ -5088,12 +5331,12 @@ class Ds extends _ {
|
|
|
5088
5331
|
const t = this.validateGlobalMetadata(e);
|
|
5089
5332
|
if (!t.valid)
|
|
5090
5333
|
throw new Error(`[TraceLog] Invalid global metadata: ${t.error}`);
|
|
5091
|
-
const s = this.get("config"),
|
|
5334
|
+
const s = this.get("config"), i = {
|
|
5092
5335
|
...s.globalMetadata ?? {},
|
|
5093
5336
|
...e
|
|
5094
5337
|
}, o = {
|
|
5095
5338
|
...s,
|
|
5096
|
-
globalMetadata:
|
|
5339
|
+
globalMetadata: i
|
|
5097
5340
|
};
|
|
5098
5341
|
this.set("config", o), a("debug", "Global metadata updated (merged)", { data: { keys: Object.keys(e) } });
|
|
5099
5342
|
}
|
|
@@ -5121,12 +5364,12 @@ class Ds extends _ {
|
|
|
5121
5364
|
a("warn", "identify() userId exceeds 256 characters", { data: { length: e.trim().length } });
|
|
5122
5365
|
return;
|
|
5123
5366
|
}
|
|
5124
|
-
const s = e.trim(),
|
|
5367
|
+
const s = e.trim(), n = ht(t), i = {
|
|
5125
5368
|
userId: s,
|
|
5126
|
-
...
|
|
5369
|
+
...n ? { traits: n } : {}
|
|
5127
5370
|
};
|
|
5128
|
-
this.set("identity",
|
|
5129
|
-
data: { userIdLength: s.length, traitKeys:
|
|
5371
|
+
this.set("identity", i), this.persistIdentity(i), a("debug", "Visitor identified", {
|
|
5372
|
+
data: { userIdLength: s.length, traitKeys: n ? Object.keys(n) : [] }
|
|
5130
5373
|
});
|
|
5131
5374
|
}
|
|
5132
5375
|
/**
|
|
@@ -5141,7 +5384,7 @@ class Ds extends _ {
|
|
|
5141
5384
|
async resetIdentity() {
|
|
5142
5385
|
await this.managers.event?.flushImmediately(), this.set("identity", void 0), this.clearPersistedIdentity();
|
|
5143
5386
|
const e = dt();
|
|
5144
|
-
this.managers.storage.setItem(
|
|
5387
|
+
this.managers.storage.setItem(ve, e), this.set("userId", e), this.set("hasStartSession", !1), this.set("sessionId", null), this.handlers.session?.stopTracking(), this.handlers.session?.startTracking(), a("debug", "Identity reset, new UUID generated");
|
|
5145
5388
|
}
|
|
5146
5389
|
/**
|
|
5147
5390
|
* Returns the project ID used for identity storage scoping.
|
|
@@ -5155,7 +5398,7 @@ class Ds extends _ {
|
|
|
5155
5398
|
*/
|
|
5156
5399
|
persistIdentity(e) {
|
|
5157
5400
|
try {
|
|
5158
|
-
const t = this.getProjectId(), s =
|
|
5401
|
+
const t = this.getProjectId(), s = me(t);
|
|
5159
5402
|
this.managers.storage.setItem(s, JSON.stringify(e));
|
|
5160
5403
|
} catch {
|
|
5161
5404
|
a("debug", "Failed to persist identity to localStorage");
|
|
@@ -5166,31 +5409,31 @@ class Ds extends _ {
|
|
|
5166
5409
|
* Also migrates pending identity (set before init) to the project-scoped key.
|
|
5167
5410
|
*/
|
|
5168
5411
|
loadPersistedIdentity() {
|
|
5169
|
-
const e = this.managers.storage, t = this.getProjectId(), s =
|
|
5412
|
+
const e = this.managers.storage, t = this.getProjectId(), s = me(t);
|
|
5170
5413
|
try {
|
|
5171
|
-
const
|
|
5172
|
-
if (
|
|
5173
|
-
const
|
|
5174
|
-
if (e.removeItem(
|
|
5414
|
+
const n = e.getItem(H);
|
|
5415
|
+
if (n) {
|
|
5416
|
+
const i = JSON.parse(n);
|
|
5417
|
+
if (e.removeItem(H), !this.isValidIdentityData(i)) {
|
|
5175
5418
|
a("debug", "Invalid pending identity in localStorage, discarded");
|
|
5176
5419
|
return;
|
|
5177
5420
|
}
|
|
5178
|
-
const o = { ...
|
|
5421
|
+
const o = { ...i, userId: i.userId.trim() };
|
|
5179
5422
|
e.setItem(s, JSON.stringify(o)), this.set("identity", o), a("debug", "Migrated pending identity to project-scoped key");
|
|
5180
5423
|
return;
|
|
5181
5424
|
}
|
|
5182
5425
|
} catch {
|
|
5183
|
-
e.removeItem(
|
|
5426
|
+
e.removeItem(H);
|
|
5184
5427
|
}
|
|
5185
5428
|
try {
|
|
5186
|
-
const
|
|
5187
|
-
if (
|
|
5188
|
-
const
|
|
5189
|
-
if (!this.isValidIdentityData(
|
|
5429
|
+
const n = e.getItem(s);
|
|
5430
|
+
if (n) {
|
|
5431
|
+
const i = JSON.parse(n);
|
|
5432
|
+
if (!this.isValidIdentityData(i)) {
|
|
5190
5433
|
e.removeItem(s), a("debug", "Invalid persisted identity in localStorage, discarded");
|
|
5191
5434
|
return;
|
|
5192
5435
|
}
|
|
5193
|
-
const o = { ...
|
|
5436
|
+
const o = { ...i, userId: i.userId.trim() };
|
|
5194
5437
|
this.set("identity", o), a("debug", "Loaded persisted identity");
|
|
5195
5438
|
}
|
|
5196
5439
|
} catch {
|
|
@@ -5207,8 +5450,8 @@ class Ds extends _ {
|
|
|
5207
5450
|
if (typeof t != "string" || t.trim().length === 0 || t.trim().length > 256) return !1;
|
|
5208
5451
|
if (s !== void 0) {
|
|
5209
5452
|
if (typeof s != "object" || s === null || Array.isArray(s)) return !1;
|
|
5210
|
-
for (const
|
|
5211
|
-
if (typeof
|
|
5453
|
+
for (const n of Object.values(s))
|
|
5454
|
+
if (typeof n != "string") return !1;
|
|
5212
5455
|
}
|
|
5213
5456
|
return !0;
|
|
5214
5457
|
}
|
|
@@ -5218,7 +5461,7 @@ class Ds extends _ {
|
|
|
5218
5461
|
clearPersistedIdentity() {
|
|
5219
5462
|
try {
|
|
5220
5463
|
const e = this.managers.storage, t = this.getProjectId();
|
|
5221
|
-
e.removeItem(
|
|
5464
|
+
e.removeItem(me(t)), e.removeItem(H);
|
|
5222
5465
|
} catch {
|
|
5223
5466
|
a("debug", "Failed to clear persisted identity");
|
|
5224
5467
|
}
|
|
@@ -5226,7 +5469,13 @@ class Ds extends _ {
|
|
|
5226
5469
|
setupPageLifecycleListeners() {
|
|
5227
5470
|
this.pageUnloadHandler = () => {
|
|
5228
5471
|
this.managers.event?.flushImmediatelySync();
|
|
5229
|
-
},
|
|
5472
|
+
}, this.pageShowHandler = (e) => {
|
|
5473
|
+
e.persisted && this.managers.event?.recoverPersistedEvents().catch((t) => {
|
|
5474
|
+
a("warn", "Failed to recover persisted events on bfcache restore", { error: t });
|
|
5475
|
+
});
|
|
5476
|
+
}, this.visibilityFlushHandler = () => {
|
|
5477
|
+
typeof document > "u" || !document.hidden || this.get("config").flushOnPageHidden !== !1 && this.managers.event?.flushImmediatelySync();
|
|
5478
|
+
}, window.addEventListener("pagehide", this.pageUnloadHandler), window.addEventListener("beforeunload", this.pageUnloadHandler), window.addEventListener("pageshow", this.pageShowHandler), document.addEventListener("visibilitychange", this.visibilityFlushHandler);
|
|
5230
5479
|
}
|
|
5231
5480
|
initializeHandlers() {
|
|
5232
5481
|
const e = this.get("config");
|
|
@@ -5239,38 +5488,38 @@ class Ds extends _ {
|
|
|
5239
5488
|
this.set("suppressNextScroll", !1);
|
|
5240
5489
|
}, 500);
|
|
5241
5490
|
};
|
|
5242
|
-
if (this.handlers.pageView = new Ls(this.managers.event, t), this.handlers.pageView.startTracking(), this.handlers.click = new As(this.managers.event), this.handlers.click.startTracking(), this.handlers.scroll = new Ms(this.managers.event), this.handlers.scroll.startTracking(), this.handlers.performance = new
|
|
5491
|
+
if (this.handlers.pageView = new Ls(this.managers.event, t), this.handlers.pageView.startTracking(), this.handlers.click = new As(this.managers.event), this.handlers.click.startTracking(), this.handlers.scroll = new Ms(this.managers.event), this.handlers.scroll.startTracking(), this.handlers.performance = new Ds(this.managers.event), this.handlers.performance.startTracking().catch((s) => {
|
|
5243
5492
|
a("warn", "Failed to start performance tracking", { error: s });
|
|
5244
5493
|
}), this.handlers.error = new ae(this.managers.event), this.handlers.error.startTracking(), e.viewport && (this.handlers.viewport = new Cs(this.managers.event), this.handlers.viewport.startTracking()), e.integrations?.tracelog?.shopify) {
|
|
5245
|
-
const s = new
|
|
5246
|
-
s.activate(), this.integrationInstances.shopifyCartLinker = s, this.emitter.on(se.EVENT, (
|
|
5247
|
-
|
|
5494
|
+
const s = new Os();
|
|
5495
|
+
s.activate(), this.integrationInstances.shopifyCartLinker = s, this.emitter.on(se.EVENT, (n) => {
|
|
5496
|
+
n.type === u.SESSION_START && s.onSessionChange();
|
|
5248
5497
|
});
|
|
5249
5498
|
}
|
|
5250
5499
|
}
|
|
5251
5500
|
}
|
|
5252
5501
|
const k = [], M = [];
|
|
5253
5502
|
let D = null, h = null, R = !1, T = !1, P = null;
|
|
5254
|
-
const
|
|
5503
|
+
const Vs = async (r) => typeof window > "u" || typeof document > "u" ? { sessionId: "" } : (T = !1, window.__traceLogDisabled === !0 ? { sessionId: "" } : h ? { sessionId: h.getSessionId() ?? "" } : (R && P || (R = !0, P = (async () => {
|
|
5255
5504
|
try {
|
|
5256
|
-
const e = fs(r ?? {}), t = new
|
|
5505
|
+
const e = fs(r ?? {}), t = new ks();
|
|
5257
5506
|
try {
|
|
5258
5507
|
k.forEach(({ event: o, callback: l }) => {
|
|
5259
5508
|
t.on(o, l);
|
|
5260
5509
|
}), k.length = 0, M.forEach(({ hook: o, fn: l }) => {
|
|
5261
5510
|
o === "beforeSend" ? t.setTransformer("beforeSend", l) : t.setTransformer("beforeBatch", l);
|
|
5262
5511
|
}), M.length = 0, D && (t.setCustomHeaders(D), D = null);
|
|
5263
|
-
const s = t.init(e),
|
|
5512
|
+
const s = t.init(e), n = new Promise((o, l) => {
|
|
5264
5513
|
setTimeout(() => {
|
|
5265
5514
|
l(new Error("[TraceLog] Initialization timeout after 10000ms"));
|
|
5266
5515
|
}, 1e4);
|
|
5267
|
-
}),
|
|
5268
|
-
return h = t,
|
|
5516
|
+
}), i = await Promise.race([s, n]);
|
|
5517
|
+
return h = t, i;
|
|
5269
5518
|
} catch (s) {
|
|
5270
5519
|
try {
|
|
5271
5520
|
t.destroy(!0);
|
|
5272
|
-
} catch (
|
|
5273
|
-
a("error", "Failed to cleanup partially initialized app", { error:
|
|
5521
|
+
} catch (n) {
|
|
5522
|
+
a("error", "Failed to cleanup partially initialized app", { error: n });
|
|
5274
5523
|
}
|
|
5275
5524
|
throw s;
|
|
5276
5525
|
}
|
|
@@ -5279,15 +5528,15 @@ const ks = async (r) => typeof window > "u" || typeof document > "u" ? { session
|
|
|
5279
5528
|
} finally {
|
|
5280
5529
|
R = !1, P = null;
|
|
5281
5530
|
}
|
|
5282
|
-
})()), P)),
|
|
5531
|
+
})()), P)), Us = (r, e, t) => {
|
|
5283
5532
|
if (!(typeof window > "u" || typeof document > "u")) {
|
|
5284
5533
|
if (!h)
|
|
5285
5534
|
throw new Error("[TraceLog] TraceLog not initialized. Please call init() first.");
|
|
5286
5535
|
if (T)
|
|
5287
5536
|
throw new Error("[TraceLog] Cannot send events while TraceLog is being destroyed");
|
|
5288
|
-
h.sendCustomEvent(r, e);
|
|
5537
|
+
h.sendCustomEvent(r, e, t);
|
|
5289
5538
|
}
|
|
5290
|
-
},
|
|
5539
|
+
}, Hs = async () => typeof window > "u" || typeof document > "u" || !h || T ? !1 : h.flushImmediately(), Fs = () => typeof window > "u" || typeof document > "u" || !h || T ? !1 : h.flushImmediatelySync(), xs = (r, e) => {
|
|
5291
5540
|
if (!(typeof window > "u" || typeof document > "u")) {
|
|
5292
5541
|
if (!h || R) {
|
|
5293
5542
|
k.push({ event: r, callback: e });
|
|
@@ -5295,7 +5544,7 @@ const ks = async (r) => typeof window > "u" || typeof document > "u" ? { session
|
|
|
5295
5544
|
}
|
|
5296
5545
|
h.on(r, e);
|
|
5297
5546
|
}
|
|
5298
|
-
},
|
|
5547
|
+
}, $s = (r, e) => {
|
|
5299
5548
|
if (!(typeof window > "u" || typeof document > "u")) {
|
|
5300
5549
|
if (!h) {
|
|
5301
5550
|
const t = k.findIndex((s) => s.event === r && s.callback === e);
|
|
@@ -5305,7 +5554,7 @@ const ks = async (r) => typeof window > "u" || typeof document > "u" ? { session
|
|
|
5305
5554
|
h.off(r, e);
|
|
5306
5555
|
}
|
|
5307
5556
|
};
|
|
5308
|
-
function
|
|
5557
|
+
function Bs(r, e) {
|
|
5309
5558
|
if (!(typeof window > "u" || typeof document > "u")) {
|
|
5310
5559
|
if (typeof e != "function")
|
|
5311
5560
|
throw new Error(`[TraceLog] Transformer must be a function, received: ${typeof e}`);
|
|
@@ -5319,7 +5568,7 @@ function Hs(r, e) {
|
|
|
5319
5568
|
r === "beforeSend" ? h.setTransformer("beforeSend", e) : h.setTransformer("beforeBatch", e);
|
|
5320
5569
|
}
|
|
5321
5570
|
}
|
|
5322
|
-
const
|
|
5571
|
+
const Ws = (r) => {
|
|
5323
5572
|
if (!(typeof window > "u" || typeof document > "u")) {
|
|
5324
5573
|
if (!h) {
|
|
5325
5574
|
const e = M.findIndex((t) => t.hook === r);
|
|
@@ -5330,7 +5579,7 @@ const xs = (r) => {
|
|
|
5330
5579
|
throw new Error("[TraceLog] Cannot remove transformers while TraceLog is being destroyed");
|
|
5331
5580
|
h.removeTransformer(r);
|
|
5332
5581
|
}
|
|
5333
|
-
},
|
|
5582
|
+
}, Gs = (r) => {
|
|
5334
5583
|
if (!(typeof window > "u" || typeof document > "u")) {
|
|
5335
5584
|
if (typeof r != "function")
|
|
5336
5585
|
throw new Error(`[TraceLog] Custom headers provider must be a function, received: ${typeof r}`);
|
|
@@ -5342,7 +5591,7 @@ const xs = (r) => {
|
|
|
5342
5591
|
throw new Error("[TraceLog] Cannot set custom headers while TraceLog is being destroyed");
|
|
5343
5592
|
h.setCustomHeaders(r);
|
|
5344
5593
|
}
|
|
5345
|
-
},
|
|
5594
|
+
}, Xs = () => {
|
|
5346
5595
|
if (!(typeof window > "u" || typeof document > "u")) {
|
|
5347
5596
|
if (!h) {
|
|
5348
5597
|
D = null;
|
|
@@ -5352,7 +5601,7 @@ const xs = (r) => {
|
|
|
5352
5601
|
throw new Error("[TraceLog] Cannot remove custom headers while TraceLog is being destroyed");
|
|
5353
5602
|
h.removeCustomHeaders();
|
|
5354
5603
|
}
|
|
5355
|
-
},
|
|
5604
|
+
}, js = () => typeof window > "u" || typeof document > "u" ? !1 : h !== null, Ks = () => typeof window > "u" || typeof document > "u" || !h ? null : h.getSessionId(), Qs = () => {
|
|
5356
5605
|
if (!(typeof window > "u" || typeof document > "u")) {
|
|
5357
5606
|
if (T)
|
|
5358
5607
|
throw new Error("[TraceLog] Destroy operation already in progress");
|
|
@@ -5367,9 +5616,9 @@ const xs = (r) => {
|
|
|
5367
5616
|
h = null, R = !1, P = null, k.length = 0, M.length = 0, D = null, T = !1, a("warn", "Error during destroy, forced cleanup completed", { error: r });
|
|
5368
5617
|
}
|
|
5369
5618
|
}
|
|
5370
|
-
}, js = (r) => {
|
|
5371
|
-
typeof window > "u" || typeof document > "u" || rs(r);
|
|
5372
5619
|
}, zs = (r) => {
|
|
5620
|
+
typeof window > "u" || typeof document > "u" || rs(r);
|
|
5621
|
+
}, Ys = (r) => {
|
|
5373
5622
|
if (!(typeof window > "u" || typeof document > "u")) {
|
|
5374
5623
|
if (!h)
|
|
5375
5624
|
throw new Error("[TraceLog] TraceLog not initialized. Please call init() first.");
|
|
@@ -5377,7 +5626,7 @@ const xs = (r) => {
|
|
|
5377
5626
|
throw new Error("[TraceLog] Cannot update metadata while TraceLog is being destroyed");
|
|
5378
5627
|
h.updateGlobalMetadata(r);
|
|
5379
5628
|
}
|
|
5380
|
-
},
|
|
5629
|
+
}, qs = (r) => {
|
|
5381
5630
|
if (!(typeof window > "u" || typeof document > "u")) {
|
|
5382
5631
|
if (!h)
|
|
5383
5632
|
throw new Error("[TraceLog] TraceLog not initialized. Please call init() first.");
|
|
@@ -5385,7 +5634,7 @@ const xs = (r) => {
|
|
|
5385
5634
|
throw new Error("[TraceLog] Cannot update metadata while TraceLog is being destroyed");
|
|
5386
5635
|
h.mergeGlobalMetadata(r);
|
|
5387
5636
|
}
|
|
5388
|
-
},
|
|
5637
|
+
}, Js = (r, e) => {
|
|
5389
5638
|
if (!(typeof window > "u" || typeof document > "u")) {
|
|
5390
5639
|
if (!r || typeof r != "string" || r.trim().length === 0) {
|
|
5391
5640
|
a("warn", "identify() called with invalid userId");
|
|
@@ -5408,16 +5657,16 @@ const xs = (r) => {
|
|
|
5408
5657
|
userId: r.trim(),
|
|
5409
5658
|
...t ? { traits: t } : {}
|
|
5410
5659
|
};
|
|
5411
|
-
localStorage.setItem(
|
|
5660
|
+
localStorage.setItem(H, JSON.stringify(s)), a("debug", "Identity persisted pre-init (will be applied on init)");
|
|
5412
5661
|
} catch {
|
|
5413
5662
|
a("debug", "Failed to persist pre-init identity");
|
|
5414
5663
|
}
|
|
5415
5664
|
}
|
|
5416
|
-
},
|
|
5665
|
+
}, Zs = async () => {
|
|
5417
5666
|
if (!(typeof window > "u" || typeof document > "u")) {
|
|
5418
5667
|
if (!h) {
|
|
5419
5668
|
try {
|
|
5420
|
-
localStorage.removeItem(
|
|
5669
|
+
localStorage.removeItem(H);
|
|
5421
5670
|
} catch {
|
|
5422
5671
|
}
|
|
5423
5672
|
return;
|
|
@@ -5426,43 +5675,45 @@ const xs = (r) => {
|
|
|
5426
5675
|
throw new Error("[TraceLog] Cannot reset identity while TraceLog is being destroyed");
|
|
5427
5676
|
await h.resetIdentity();
|
|
5428
5677
|
}
|
|
5429
|
-
},
|
|
5430
|
-
init:
|
|
5431
|
-
event:
|
|
5432
|
-
on:
|
|
5433
|
-
off:
|
|
5434
|
-
setTransformer:
|
|
5435
|
-
removeTransformer:
|
|
5436
|
-
setCustomHeaders:
|
|
5437
|
-
removeCustomHeaders:
|
|
5438
|
-
isInitialized:
|
|
5439
|
-
getSessionId:
|
|
5440
|
-
destroy:
|
|
5441
|
-
setQaMode:
|
|
5442
|
-
updateGlobalMetadata:
|
|
5443
|
-
mergeGlobalMetadata:
|
|
5444
|
-
identify:
|
|
5445
|
-
resetIdentity:
|
|
5678
|
+
}, Mr = {
|
|
5679
|
+
init: Vs,
|
|
5680
|
+
event: Us,
|
|
5681
|
+
on: xs,
|
|
5682
|
+
off: $s,
|
|
5683
|
+
setTransformer: Bs,
|
|
5684
|
+
removeTransformer: Ws,
|
|
5685
|
+
setCustomHeaders: Gs,
|
|
5686
|
+
removeCustomHeaders: Xs,
|
|
5687
|
+
isInitialized: js,
|
|
5688
|
+
getSessionId: Ks,
|
|
5689
|
+
destroy: Qs,
|
|
5690
|
+
setQaMode: zs,
|
|
5691
|
+
updateGlobalMetadata: Ys,
|
|
5692
|
+
mergeGlobalMetadata: qs,
|
|
5693
|
+
identify: Js,
|
|
5694
|
+
resetIdentity: Zs,
|
|
5695
|
+
flushImmediately: Hs,
|
|
5696
|
+
flushImmediatelySync: Fs
|
|
5446
5697
|
};
|
|
5447
|
-
var
|
|
5698
|
+
var Ae, C, X, pt, le, Et = -1, V = function(r) {
|
|
5448
5699
|
addEventListener("pageshow", (function(e) {
|
|
5449
|
-
e.persisted && (
|
|
5700
|
+
e.persisted && (Et = e.timeStamp, r(e));
|
|
5450
5701
|
}), !0);
|
|
5451
|
-
},
|
|
5702
|
+
}, De = function() {
|
|
5452
5703
|
var r = self.performance && performance.getEntriesByType && performance.getEntriesByType("navigation")[0];
|
|
5453
5704
|
if (r && r.responseStart > 0 && r.responseStart < performance.now()) return r;
|
|
5454
5705
|
}, de = function() {
|
|
5455
|
-
var r =
|
|
5706
|
+
var r = De();
|
|
5456
5707
|
return r && r.activationStart || 0;
|
|
5457
5708
|
}, y = function(r, e) {
|
|
5458
|
-
var t =
|
|
5459
|
-
return
|
|
5460
|
-
},
|
|
5709
|
+
var t = De(), s = "navigate";
|
|
5710
|
+
return Et >= 0 ? s = "back-forward-cache" : t && (document.prerendering || de() > 0 ? s = "prerender" : document.wasDiscarded ? s = "restore" : t.type && (s = t.type.replace(/_/g, "-"))), { name: r, value: e === void 0 ? -1 : e, rating: "good", delta: 0, entries: [], id: "v4-".concat(Date.now(), "-").concat(Math.floor(8999999999999 * Math.random()) + 1e12), navigationType: s };
|
|
5711
|
+
}, x = function(r, e, t) {
|
|
5461
5712
|
try {
|
|
5462
5713
|
if (PerformanceObserver.supportedEntryTypes.includes(r)) {
|
|
5463
|
-
var s = new PerformanceObserver((function(
|
|
5714
|
+
var s = new PerformanceObserver((function(n) {
|
|
5464
5715
|
Promise.resolve().then((function() {
|
|
5465
|
-
e(
|
|
5716
|
+
e(n.getEntries());
|
|
5466
5717
|
}));
|
|
5467
5718
|
}));
|
|
5468
5719
|
return s.observe(Object.assign({ type: r, buffered: !0 }, t || {})), s;
|
|
@@ -5470,19 +5721,19 @@ var Le, C, G, Et, le, pt = -1, V = function(r) {
|
|
|
5470
5721
|
} catch {
|
|
5471
5722
|
}
|
|
5472
5723
|
}, w = function(r, e, t, s) {
|
|
5473
|
-
var
|
|
5724
|
+
var n, i;
|
|
5474
5725
|
return function(o) {
|
|
5475
|
-
e.value >= 0 && (o || s) && ((
|
|
5476
|
-
return l >
|
|
5726
|
+
e.value >= 0 && (o || s) && ((i = e.value - (n || 0)) || n === void 0) && (n = e.value, e.delta = i, e.rating = (function(l, d) {
|
|
5727
|
+
return l > d[1] ? "poor" : l > d[0] ? "needs-improvement" : "good";
|
|
5477
5728
|
})(e.value, t), r(e));
|
|
5478
5729
|
};
|
|
5479
|
-
},
|
|
5730
|
+
}, ke = function(r) {
|
|
5480
5731
|
requestAnimationFrame((function() {
|
|
5481
5732
|
return requestAnimationFrame((function() {
|
|
5482
5733
|
return r();
|
|
5483
5734
|
}));
|
|
5484
5735
|
}));
|
|
5485
|
-
},
|
|
5736
|
+
}, K = function(r) {
|
|
5486
5737
|
document.addEventListener("visibilitychange", (function() {
|
|
5487
5738
|
document.visibilityState === "hidden" && r();
|
|
5488
5739
|
}));
|
|
@@ -5494,12 +5745,12 @@ var Le, C, G, Et, le, pt = -1, V = function(r) {
|
|
|
5494
5745
|
}, F = -1, et = function() {
|
|
5495
5746
|
return document.visibilityState !== "hidden" || document.prerendering ? 1 / 0 : 0;
|
|
5496
5747
|
}, ce = function(r) {
|
|
5497
|
-
document.visibilityState === "hidden" && F > -1 && (F = r.type === "visibilitychange" ? r.timeStamp : 0,
|
|
5748
|
+
document.visibilityState === "hidden" && F > -1 && (F = r.type === "visibilitychange" ? r.timeStamp : 0, er());
|
|
5498
5749
|
}, tt = function() {
|
|
5499
5750
|
addEventListener("visibilitychange", ce, !0), addEventListener("prerenderingchange", ce, !0);
|
|
5500
|
-
},
|
|
5751
|
+
}, er = function() {
|
|
5501
5752
|
removeEventListener("visibilitychange", ce, !0), removeEventListener("prerenderingchange", ce, !0);
|
|
5502
|
-
},
|
|
5753
|
+
}, Ve = function() {
|
|
5503
5754
|
return F < 0 && (F = et(), tt(), V((function() {
|
|
5504
5755
|
setTimeout((function() {
|
|
5505
5756
|
F = et(), tt();
|
|
@@ -5507,55 +5758,55 @@ var Le, C, G, Et, le, pt = -1, V = function(r) {
|
|
|
5507
5758
|
}))), { get firstHiddenTime() {
|
|
5508
5759
|
return F;
|
|
5509
5760
|
} };
|
|
5510
|
-
},
|
|
5761
|
+
}, Q = function(r) {
|
|
5511
5762
|
document.prerendering ? addEventListener("prerenderingchange", (function() {
|
|
5512
5763
|
return r();
|
|
5513
5764
|
}), !0) : r();
|
|
5514
|
-
},
|
|
5515
|
-
e = e || {},
|
|
5516
|
-
var t, s =
|
|
5765
|
+
}, Me = [1800, 3e3], St = function(r, e) {
|
|
5766
|
+
e = e || {}, Q((function() {
|
|
5767
|
+
var t, s = Ve(), n = y("FCP"), i = x("paint", (function(o) {
|
|
5517
5768
|
o.forEach((function(l) {
|
|
5518
|
-
l.name === "first-contentful-paint" && (
|
|
5769
|
+
l.name === "first-contentful-paint" && (i.disconnect(), l.startTime < s.firstHiddenTime && (n.value = Math.max(l.startTime - de(), 0), n.entries.push(l), t(!0)));
|
|
5519
5770
|
}));
|
|
5520
5771
|
}));
|
|
5521
|
-
|
|
5522
|
-
|
|
5523
|
-
|
|
5772
|
+
i && (t = w(r, n, Me, e.reportAllChanges), V((function(o) {
|
|
5773
|
+
n = y("FCP"), t = w(r, n, Me, e.reportAllChanges), ke((function() {
|
|
5774
|
+
n.value = performance.now() - o.timeStamp, t(!0);
|
|
5524
5775
|
}));
|
|
5525
5776
|
})));
|
|
5526
5777
|
}));
|
|
5527
|
-
},
|
|
5778
|
+
}, Ce = [0.1, 0.25], tr = function(r, e) {
|
|
5528
5779
|
e = e || {}, St(ue((function() {
|
|
5529
|
-
var t, s = y("CLS", 0),
|
|
5530
|
-
|
|
5531
|
-
if (!
|
|
5532
|
-
var f =
|
|
5533
|
-
|
|
5780
|
+
var t, s = y("CLS", 0), n = 0, i = [], o = function(d) {
|
|
5781
|
+
d.forEach((function(c) {
|
|
5782
|
+
if (!c.hadRecentInput) {
|
|
5783
|
+
var f = i[0], m = i[i.length - 1];
|
|
5784
|
+
n && c.startTime - m.startTime < 1e3 && c.startTime - f.startTime < 5e3 ? (n += c.value, i.push(c)) : (n = c.value, i = [c]);
|
|
5534
5785
|
}
|
|
5535
|
-
})),
|
|
5536
|
-
}, l =
|
|
5537
|
-
l && (t = w(r, s,
|
|
5786
|
+
})), n > s.value && (s.value = n, s.entries = i, t());
|
|
5787
|
+
}, l = x("layout-shift", o);
|
|
5788
|
+
l && (t = w(r, s, Ce, e.reportAllChanges), K((function() {
|
|
5538
5789
|
o(l.takeRecords()), t(!0);
|
|
5539
5790
|
})), V((function() {
|
|
5540
|
-
|
|
5791
|
+
n = 0, s = y("CLS", 0), t = w(r, s, Ce, e.reportAllChanges), ke((function() {
|
|
5541
5792
|
return t();
|
|
5542
5793
|
}));
|
|
5543
5794
|
})), setTimeout(t, 0));
|
|
5544
5795
|
})));
|
|
5545
|
-
}, Tt = 0,
|
|
5796
|
+
}, Tt = 0, Se = 1 / 0, J = 0, sr = function(r) {
|
|
5546
5797
|
r.forEach((function(e) {
|
|
5547
|
-
e.interactionId && (
|
|
5798
|
+
e.interactionId && (Se = Math.min(Se, e.interactionId), J = Math.max(J, e.interactionId), Tt = J ? (J - Se) / 7 + 1 : 0);
|
|
5548
5799
|
}));
|
|
5549
|
-
},
|
|
5550
|
-
return
|
|
5551
|
-
},
|
|
5552
|
-
"interactionCount" in performance ||
|
|
5553
|
-
}, L = [], te = /* @__PURE__ */ new Map(),
|
|
5554
|
-
var r = Math.min(L.length - 1, Math.floor((
|
|
5800
|
+
}, vt = function() {
|
|
5801
|
+
return Ae ? Tt : performance.interactionCount || 0;
|
|
5802
|
+
}, rr = function() {
|
|
5803
|
+
"interactionCount" in performance || Ae || (Ae = x("event", sr, { type: "event", buffered: !0, durationThreshold: 0 }));
|
|
5804
|
+
}, L = [], te = /* @__PURE__ */ new Map(), It = 0, nr = function() {
|
|
5805
|
+
var r = Math.min(L.length - 1, Math.floor((vt() - It) / 50));
|
|
5555
5806
|
return L[r];
|
|
5556
|
-
},
|
|
5557
|
-
if (
|
|
5558
|
-
return
|
|
5807
|
+
}, ir = [], or = function(r) {
|
|
5808
|
+
if (ir.forEach((function(n) {
|
|
5809
|
+
return n(r);
|
|
5559
5810
|
})), r.interactionId || r.entryType === "first-input") {
|
|
5560
5811
|
var e = L[L.length - 1], t = te.get(r.interactionId);
|
|
5561
5812
|
if (t || L.length < 10 || r.duration > e.latency) {
|
|
@@ -5564,147 +5815,147 @@ var Le, C, G, Et, le, pt = -1, V = function(r) {
|
|
|
5564
5815
|
var s = { id: r.interactionId, latency: r.duration, entries: [r] };
|
|
5565
5816
|
te.set(s.id, s), L.push(s);
|
|
5566
5817
|
}
|
|
5567
|
-
L.sort((function(
|
|
5568
|
-
return
|
|
5569
|
-
})), L.length > 10 && L.splice(10).forEach((function(
|
|
5570
|
-
return te.delete(
|
|
5818
|
+
L.sort((function(n, i) {
|
|
5819
|
+
return i.latency - n.latency;
|
|
5820
|
+
})), L.length > 10 && L.splice(10).forEach((function(n) {
|
|
5821
|
+
return te.delete(n.id);
|
|
5571
5822
|
}));
|
|
5572
5823
|
}
|
|
5573
5824
|
}
|
|
5574
5825
|
}, _t = function(r) {
|
|
5575
5826
|
var e = self.requestIdleCallback || self.setTimeout, t = -1;
|
|
5576
|
-
return r = ue(r), document.visibilityState === "hidden" ? r() : (t = e(r),
|
|
5577
|
-
},
|
|
5578
|
-
"PerformanceEventTiming" in self && "interactionId" in PerformanceEventTiming.prototype && (e = e || {},
|
|
5827
|
+
return r = ue(r), document.visibilityState === "hidden" ? r() : (t = e(r), K(r)), t;
|
|
5828
|
+
}, Re = [200, 500], ar = function(r, e) {
|
|
5829
|
+
"PerformanceEventTiming" in self && "interactionId" in PerformanceEventTiming.prototype && (e = e || {}, Q((function() {
|
|
5579
5830
|
var t;
|
|
5580
|
-
|
|
5581
|
-
var s,
|
|
5831
|
+
rr();
|
|
5832
|
+
var s, n = y("INP"), i = function(l) {
|
|
5582
5833
|
_t((function() {
|
|
5583
|
-
l.forEach(
|
|
5584
|
-
var
|
|
5585
|
-
|
|
5834
|
+
l.forEach(or);
|
|
5835
|
+
var d = nr();
|
|
5836
|
+
d && d.latency !== n.value && (n.value = d.latency, n.entries = d.entries, s());
|
|
5586
5837
|
}));
|
|
5587
|
-
}, o =
|
|
5588
|
-
s = w(r,
|
|
5589
|
-
|
|
5838
|
+
}, o = x("event", i, { durationThreshold: (t = e.durationThreshold) !== null && t !== void 0 ? t : 40 });
|
|
5839
|
+
s = w(r, n, Re, e.reportAllChanges), o && (o.observe({ type: "first-input", buffered: !0 }), K((function() {
|
|
5840
|
+
i(o.takeRecords()), s(!0);
|
|
5590
5841
|
})), V((function() {
|
|
5591
|
-
|
|
5842
|
+
It = vt(), L.length = 0, te.clear(), n = y("INP"), s = w(r, n, Re, e.reportAllChanges);
|
|
5592
5843
|
})));
|
|
5593
5844
|
})));
|
|
5594
|
-
},
|
|
5595
|
-
e = e || {},
|
|
5596
|
-
var t, s =
|
|
5597
|
-
e.reportAllChanges || (
|
|
5598
|
-
|
|
5845
|
+
}, Ne = [2500, 4e3], Te = {}, lr = function(r, e) {
|
|
5846
|
+
e = e || {}, Q((function() {
|
|
5847
|
+
var t, s = Ve(), n = y("LCP"), i = function(d) {
|
|
5848
|
+
e.reportAllChanges || (d = d.slice(-1)), d.forEach((function(c) {
|
|
5849
|
+
c.startTime < s.firstHiddenTime && (n.value = Math.max(c.startTime - de(), 0), n.entries = [c], t());
|
|
5599
5850
|
}));
|
|
5600
|
-
}, o =
|
|
5851
|
+
}, o = x("largest-contentful-paint", i);
|
|
5601
5852
|
if (o) {
|
|
5602
|
-
t = w(r,
|
|
5853
|
+
t = w(r, n, Ne, e.reportAllChanges);
|
|
5603
5854
|
var l = ue((function() {
|
|
5604
|
-
|
|
5855
|
+
Te[n.id] || (i(o.takeRecords()), o.disconnect(), Te[n.id] = !0, t(!0));
|
|
5605
5856
|
}));
|
|
5606
|
-
["keydown", "click"].forEach((function(
|
|
5607
|
-
addEventListener(
|
|
5857
|
+
["keydown", "click"].forEach((function(d) {
|
|
5858
|
+
addEventListener(d, (function() {
|
|
5608
5859
|
return _t(l);
|
|
5609
5860
|
}), { once: !0, capture: !0 });
|
|
5610
|
-
})),
|
|
5611
|
-
|
|
5612
|
-
|
|
5861
|
+
})), K(l), V((function(d) {
|
|
5862
|
+
n = y("LCP"), t = w(r, n, Ne, e.reportAllChanges), ke((function() {
|
|
5863
|
+
n.value = performance.now() - d.timeStamp, Te[n.id] = !0, t(!0);
|
|
5613
5864
|
}));
|
|
5614
5865
|
}));
|
|
5615
5866
|
}
|
|
5616
5867
|
}));
|
|
5617
|
-
},
|
|
5618
|
-
document.prerendering ?
|
|
5868
|
+
}, Oe = [800, 1800], cr = function r(e) {
|
|
5869
|
+
document.prerendering ? Q((function() {
|
|
5619
5870
|
return r(e);
|
|
5620
5871
|
})) : document.readyState !== "complete" ? addEventListener("load", (function() {
|
|
5621
5872
|
return r(e);
|
|
5622
5873
|
}), !0) : setTimeout(e, 0);
|
|
5623
|
-
},
|
|
5874
|
+
}, dr = function(r, e) {
|
|
5624
5875
|
e = e || {};
|
|
5625
|
-
var t = y("TTFB"), s = w(r, t,
|
|
5626
|
-
|
|
5627
|
-
var
|
|
5628
|
-
|
|
5629
|
-
t = y("TTFB", 0), (s = w(r, t,
|
|
5876
|
+
var t = y("TTFB"), s = w(r, t, Oe, e.reportAllChanges);
|
|
5877
|
+
cr((function() {
|
|
5878
|
+
var n = De();
|
|
5879
|
+
n && (t.value = Math.max(n.responseStart - de(), 0), t.entries = [n], s(!0), V((function() {
|
|
5880
|
+
t = y("TTFB", 0), (s = w(r, t, Oe, e.reportAllChanges))(!0);
|
|
5630
5881
|
})));
|
|
5631
5882
|
}));
|
|
5632
|
-
}, W = { passive: !0, capture: !0 },
|
|
5633
|
-
C || (C = e,
|
|
5883
|
+
}, W = { passive: !0, capture: !0 }, ur = /* @__PURE__ */ new Date(), st = function(r, e) {
|
|
5884
|
+
C || (C = e, X = r, pt = /* @__PURE__ */ new Date(), wt(removeEventListener), yt());
|
|
5634
5885
|
}, yt = function() {
|
|
5635
|
-
if (
|
|
5636
|
-
var r = { entryType: "first-input", name: C.type, target: C.target, cancelable: C.cancelable, startTime: C.timeStamp, processingStart: C.timeStamp +
|
|
5886
|
+
if (X >= 0 && X < pt - ur) {
|
|
5887
|
+
var r = { entryType: "first-input", name: C.type, target: C.target, cancelable: C.cancelable, startTime: C.timeStamp, processingStart: C.timeStamp + X };
|
|
5637
5888
|
le.forEach((function(e) {
|
|
5638
5889
|
e(r);
|
|
5639
5890
|
})), le = [];
|
|
5640
5891
|
}
|
|
5641
|
-
},
|
|
5892
|
+
}, hr = function(r) {
|
|
5642
5893
|
if (r.cancelable) {
|
|
5643
5894
|
var e = (r.timeStamp > 1e12 ? /* @__PURE__ */ new Date() : performance.now()) - r.timeStamp;
|
|
5644
5895
|
r.type == "pointerdown" ? (function(t, s) {
|
|
5645
|
-
var
|
|
5896
|
+
var n = function() {
|
|
5646
5897
|
st(t, s), o();
|
|
5647
|
-
},
|
|
5898
|
+
}, i = function() {
|
|
5648
5899
|
o();
|
|
5649
5900
|
}, o = function() {
|
|
5650
|
-
removeEventListener("pointerup",
|
|
5901
|
+
removeEventListener("pointerup", n, W), removeEventListener("pointercancel", i, W);
|
|
5651
5902
|
};
|
|
5652
|
-
addEventListener("pointerup",
|
|
5903
|
+
addEventListener("pointerup", n, W), addEventListener("pointercancel", i, W);
|
|
5653
5904
|
})(e, r) : st(e, r);
|
|
5654
5905
|
}
|
|
5655
5906
|
}, wt = function(r) {
|
|
5656
5907
|
["mousedown", "keydown", "touchstart", "pointerdown"].forEach((function(e) {
|
|
5657
|
-
return r(e,
|
|
5908
|
+
return r(e, hr, W);
|
|
5658
5909
|
}));
|
|
5659
|
-
},
|
|
5660
|
-
e = e || {},
|
|
5661
|
-
var t, s =
|
|
5662
|
-
|
|
5663
|
-
}, o = function(
|
|
5664
|
-
|
|
5665
|
-
}, l =
|
|
5666
|
-
t = w(r,
|
|
5910
|
+
}, Pe = [100, 300], fr = function(r, e) {
|
|
5911
|
+
e = e || {}, Q((function() {
|
|
5912
|
+
var t, s = Ve(), n = y("FID"), i = function(d) {
|
|
5913
|
+
d.startTime < s.firstHiddenTime && (n.value = d.processingStart - d.startTime, n.entries.push(d), t(!0));
|
|
5914
|
+
}, o = function(d) {
|
|
5915
|
+
d.forEach(i);
|
|
5916
|
+
}, l = x("first-input", o);
|
|
5917
|
+
t = w(r, n, Pe, e.reportAllChanges), l && (K(ue((function() {
|
|
5667
5918
|
o(l.takeRecords()), l.disconnect();
|
|
5668
5919
|
}))), V((function() {
|
|
5669
|
-
var
|
|
5670
|
-
|
|
5920
|
+
var d;
|
|
5921
|
+
n = y("FID"), t = w(r, n, Pe, e.reportAllChanges), le = [], X = -1, C = null, wt(addEventListener), d = i, le.push(d), yt();
|
|
5671
5922
|
})));
|
|
5672
5923
|
}));
|
|
5673
5924
|
};
|
|
5674
|
-
const
|
|
5925
|
+
const mr = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
5675
5926
|
__proto__: null,
|
|
5676
|
-
CLSThresholds:
|
|
5677
|
-
FCPThresholds:
|
|
5678
|
-
FIDThresholds:
|
|
5679
|
-
INPThresholds:
|
|
5680
|
-
LCPThresholds:
|
|
5681
|
-
TTFBThresholds:
|
|
5682
|
-
onCLS:
|
|
5927
|
+
CLSThresholds: Ce,
|
|
5928
|
+
FCPThresholds: Me,
|
|
5929
|
+
FIDThresholds: Pe,
|
|
5930
|
+
INPThresholds: Re,
|
|
5931
|
+
LCPThresholds: Ne,
|
|
5932
|
+
TTFBThresholds: Oe,
|
|
5933
|
+
onCLS: tr,
|
|
5683
5934
|
onFCP: St,
|
|
5684
|
-
onFID:
|
|
5685
|
-
onINP:
|
|
5686
|
-
onLCP:
|
|
5687
|
-
onTTFB:
|
|
5935
|
+
onFID: fr,
|
|
5936
|
+
onINP: ar,
|
|
5937
|
+
onLCP: lr,
|
|
5938
|
+
onTTFB: dr
|
|
5688
5939
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
5689
5940
|
export {
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5941
|
+
p as AppConfigValidationError,
|
|
5942
|
+
gr as DEFAULT_SESSION_TIMEOUT,
|
|
5943
|
+
ye as DEFAULT_WEB_VITALS_MODE,
|
|
5693
5944
|
A as DeviceType,
|
|
5694
5945
|
se as EmitterEvent,
|
|
5695
5946
|
B as ErrorType,
|
|
5696
5947
|
u as EventType,
|
|
5697
|
-
|
|
5948
|
+
Lr as InitializationTimeoutError,
|
|
5698
5949
|
N as IntegrationValidationError,
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5950
|
+
yr as MAX_ARRAY_LENGTH,
|
|
5951
|
+
Tr as MAX_CUSTOM_EVENT_ARRAY_SIZE,
|
|
5952
|
+
Sr as MAX_CUSTOM_EVENT_KEYS,
|
|
5953
|
+
pr as MAX_CUSTOM_EVENT_NAME_LENGTH,
|
|
5954
|
+
Er as MAX_CUSTOM_EVENT_STRING_SIZE,
|
|
5955
|
+
vr as MAX_NESTED_OBJECT_KEYS,
|
|
5956
|
+
Ir as MAX_STRING_LENGTH,
|
|
5957
|
+
_r as MAX_STRING_LENGTH_IN_ARRAY,
|
|
5958
|
+
ie as Mode,
|
|
5708
5959
|
at as PII_PATTERNS,
|
|
5709
5960
|
O as PermanentError,
|
|
5710
5961
|
re as RateLimitError,
|
|
@@ -5712,13 +5963,13 @@ export {
|
|
|
5712
5963
|
Z as ScrollDirection,
|
|
5713
5964
|
Pt as SessionTimeoutValidationError,
|
|
5714
5965
|
$ as SpecialApiUrl,
|
|
5715
|
-
|
|
5966
|
+
ne as TimeoutError,
|
|
5716
5967
|
j as TraceLogValidationError,
|
|
5717
|
-
|
|
5718
|
-
|
|
5968
|
+
Ar as WEB_VITALS_GOOD_THRESHOLDS,
|
|
5969
|
+
Qe as WEB_VITALS_NEEDS_IMPROVEMENT_THRESHOLDS,
|
|
5719
5970
|
Yt as WEB_VITALS_POOR_THRESHOLDS,
|
|
5720
|
-
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5971
|
+
ze as getWebVitalsThresholds,
|
|
5972
|
+
wr as isPrimaryScrollEvent,
|
|
5973
|
+
br as isSecondaryScrollEvent,
|
|
5974
|
+
Mr as tracelog
|
|
5724
5975
|
};
|