@levo-so/insights 0.1.65 → 0.1.71
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/dist/S_TwsxGkG8z9.js +857 -0
- package/dist/constants/storageKeys.d.ts +22 -0
- package/dist/index.d.ts +4 -305
- package/dist/index.js +582 -859
- package/dist/legacy/index.d.ts +71 -0
- package/dist/lib/analytics.d.ts +10 -0
- package/dist/lib/insights.d.ts +24 -0
- package/dist/stores/config.d.ts +11 -0
- package/dist/stores/events.d.ts +45 -0
- package/dist/stores/session.d.ts +21 -0
- package/dist/stores.d.ts +8 -0
- package/dist/stores.js +14 -0
- package/dist/tracking/activity.d.ts +21 -0
- package/dist/tracking/bounce.d.ts +24 -0
- package/dist/tracking/clicks.d.ts +9 -0
- package/dist/tracking/clipboard.d.ts +8 -0
- package/dist/tracking/currentTab.d.ts +16 -0
- package/dist/tracking/forms.d.ts +8 -0
- package/dist/tracking/page.d.ts +8 -0
- package/dist/tracking/scrollBehavior.d.ts +21 -0
- package/dist/tracking/textSelection.d.ts +13 -0
- package/dist/types/analytics.d.ts +4 -0
- package/dist/types/identity.d.ts +12 -0
- package/dist/types/options.d.ts +14 -0
- package/dist/utils/autocapture.d.ts +22 -0
- package/dist/utils/checkLocalStorage.d.ts +4 -0
- package/dist/utils/createPlugin.d.ts +66 -0
- package/dist/utils/detectMode.d.ts +10 -0
- package/dist/utils/getAuthHeaders.d.ts +9 -0
- package/dist/utils/getReferrer.d.ts +24 -0
- package/dist/utils/getUserProperties.d.ts +7 -0
- package/dist/utils/isIncognito.d.ts +8 -0
- package/dist/utils/lock.d.ts +20 -0
- package/dist/utils/pingEndpoint.d.ts +4 -0
- package/dist/utils/rageclick.d.ts +20 -0
- package/package.json +14 -8
package/dist/index.js
CHANGED
|
@@ -1,888 +1,585 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
import { p as E, k as H, l as R, $ as U, e as q, m as P, n as C, o as z, u as T, q as G, r as $, s as K, t as W, v as j, w as Q, x as N, y as X, z as Y, d as Z, A as J, B as V, C as ee, D as te, E as ne, F as re } from "./S_TwsxGkG8z9.js";
|
|
2
|
+
import { G as xe } from "./S_TwsxGkG8z9.js";
|
|
3
|
+
import { getVisitorSource as ie } from "@analytics/visitor-source";
|
|
4
|
+
import oe from "get-user-locale";
|
|
5
|
+
import { Analytics as ae } from "analytics";
|
|
6
|
+
const se = 30, ce = 1e3, le = 3;
|
|
7
|
+
let S = [];
|
|
8
|
+
const de = (a, i, e) => {
|
|
9
|
+
const t = S[S.length - 1];
|
|
10
|
+
if (t && Math.abs(a - t.x) + Math.abs(i - t.y) < se && e - t.timestamp < ce) {
|
|
11
|
+
if (S.push({ x: a, y: i, timestamp: e }), S.length >= le)
|
|
12
|
+
return !0;
|
|
13
|
+
} else
|
|
14
|
+
S = [{ x: a, y: i, timestamp: e }];
|
|
15
|
+
return !1;
|
|
16
|
+
}, ue = (a) => {
|
|
17
|
+
let i = a, e = 0;
|
|
18
|
+
for (; i && e < 10; ) {
|
|
19
|
+
const t = i.getAttribute?.("href");
|
|
20
|
+
if (t)
|
|
21
|
+
return t;
|
|
22
|
+
i = i.parentElement, e++;
|
|
17
23
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
return null;
|
|
25
|
+
}, A = (a) => {
|
|
26
|
+
const i = a.closest("a[href]"), e = i?.getAttribute("href") || ue(a);
|
|
27
|
+
if (!e) return { type: null, href: null };
|
|
28
|
+
if (i?.hasAttribute("download"))
|
|
29
|
+
return { type: "download", href: e };
|
|
30
|
+
if (e.startsWith("tel:")) return { type: "tel", href: e };
|
|
31
|
+
if (e.startsWith("mailto:")) return { type: "mailto", href: e };
|
|
32
|
+
if (e.startsWith("#")) return { type: "anchor", href: e };
|
|
33
|
+
try {
|
|
34
|
+
return {
|
|
35
|
+
type: new URL(e, window.location.origin).origin === window.location.origin ? "internal" : "external",
|
|
36
|
+
href: e
|
|
37
|
+
};
|
|
38
|
+
} catch (t) {
|
|
39
|
+
return console.warn("[insights] Failed to classify link", E(t)), { type: "internal", href: e };
|
|
40
|
+
}
|
|
41
|
+
}, fe = (a) => {
|
|
42
|
+
if (typeof window > "u") return () => {
|
|
43
|
+
};
|
|
44
|
+
let i = 0, e = null;
|
|
45
|
+
const t = (s, o = !1) => {
|
|
46
|
+
const l = s.target, h = "clientX" in s ? s.clientX : s.changedTouches?.[0]?.clientX ?? 0, y = "clientY" in s ? s.clientY : s.changedTouches?.[0]?.clientY ?? 0;
|
|
47
|
+
let w = {
|
|
48
|
+
hostname: window.location.hostname,
|
|
49
|
+
pathname: window.location.pathname,
|
|
50
|
+
page_title: document.title,
|
|
51
|
+
url: window.location.href,
|
|
52
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
53
|
+
event_type: o ? "dblclick" : "click",
|
|
54
|
+
button_type: "button" in s ? s.button : 0
|
|
55
|
+
};
|
|
56
|
+
return l instanceof HTMLElement && (w.rage_click = de(h, y, Date.now()), w = {
|
|
57
|
+
...w,
|
|
58
|
+
...H(l)
|
|
59
|
+
}), w;
|
|
60
|
+
}, n = (s, o) => {
|
|
61
|
+
try {
|
|
62
|
+
if (Date.now() - i < 300) return;
|
|
63
|
+
const l = t(s);
|
|
64
|
+
a.track("page.click", {
|
|
65
|
+
...l,
|
|
66
|
+
href: o.href || void 0,
|
|
67
|
+
link_type: o.type,
|
|
68
|
+
is_navigation: !0
|
|
69
|
+
});
|
|
70
|
+
} catch (l) {
|
|
71
|
+
console.error("[insights] Failed to track navigation click", E(l));
|
|
72
|
+
}
|
|
73
|
+
}, c = (s, o = !1) => {
|
|
74
|
+
try {
|
|
75
|
+
if (!(s.target instanceof HTMLElement) || Date.now() - i < 300) return;
|
|
76
|
+
const l = t(s, o), h = A(s.target);
|
|
77
|
+
a.track("page.click", {
|
|
78
|
+
...l,
|
|
79
|
+
href: h.href || void 0,
|
|
80
|
+
link_type: h.type || void 0
|
|
81
|
+
});
|
|
82
|
+
} catch (l) {
|
|
83
|
+
console.error("[insights] Failed to track click", E(l));
|
|
84
|
+
}
|
|
85
|
+
}, r = (s) => {
|
|
86
|
+
if (!(s.target instanceof HTMLElement)) return;
|
|
87
|
+
const o = A(s.target);
|
|
88
|
+
if (o.type === "external" || o.type === "download") {
|
|
89
|
+
n(s, o);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (e) {
|
|
93
|
+
clearTimeout(e), e = null;
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
e = setTimeout(() => {
|
|
97
|
+
c(s, !1), e = null;
|
|
98
|
+
}, 250);
|
|
99
|
+
}, f = (s) => {
|
|
100
|
+
e && (clearTimeout(e), e = null), c(s, !0);
|
|
101
|
+
}, u = (s) => {
|
|
102
|
+
try {
|
|
103
|
+
if (!(s.target instanceof HTMLElement)) return;
|
|
104
|
+
i = Date.now();
|
|
105
|
+
const o = A(s.target);
|
|
106
|
+
if (o.type === "external" || o.type === "download") {
|
|
107
|
+
const h = t(s);
|
|
108
|
+
a.track("page.click", {
|
|
109
|
+
...h,
|
|
110
|
+
href: o.href || void 0,
|
|
111
|
+
link_type: o.type,
|
|
112
|
+
is_navigation: !0,
|
|
113
|
+
is_touch: !0
|
|
114
|
+
});
|
|
115
|
+
return;
|
|
26
116
|
}
|
|
27
|
-
|
|
28
|
-
|
|
117
|
+
const l = t(s);
|
|
118
|
+
a.track("page.click", {
|
|
119
|
+
...l,
|
|
120
|
+
href: o.href || void 0,
|
|
121
|
+
link_type: o.type || void 0,
|
|
122
|
+
is_touch: !0
|
|
123
|
+
});
|
|
124
|
+
} catch (o) {
|
|
125
|
+
console.error("[insights] Failed to track touch", E(o));
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
return document.addEventListener("click", r), document.addEventListener("dblclick", f), document.addEventListener("touchend", u, { passive: !0 }), () => {
|
|
129
|
+
document.removeEventListener("click", r), document.removeEventListener("dblclick", f), document.removeEventListener("touchend", u), e && clearTimeout(e);
|
|
130
|
+
};
|
|
131
|
+
}, pe = (a) => {
|
|
132
|
+
if (typeof window > "u") return () => {
|
|
133
|
+
};
|
|
134
|
+
const i = (n) => (c) => {
|
|
135
|
+
try {
|
|
136
|
+
const r = R(c, n);
|
|
137
|
+
r && a.track("page.copy", r);
|
|
138
|
+
} catch (r) {
|
|
139
|
+
console.error(`[insights] Failed to track clipboard ${n}`, E(r));
|
|
140
|
+
}
|
|
141
|
+
}, e = i("copy"), t = i("cut");
|
|
142
|
+
return document.addEventListener("copy", e, { capture: !0 }), document.addEventListener("cut", t, { capture: !0 }), () => {
|
|
143
|
+
document.removeEventListener("copy", e, { capture: !0 }), document.removeEventListener("cut", t, { capture: !0 });
|
|
144
|
+
};
|
|
145
|
+
}, ge = (a) => {
|
|
146
|
+
if (typeof window > "u") return () => {
|
|
147
|
+
};
|
|
148
|
+
const i = (n) => (c) => {
|
|
149
|
+
try {
|
|
150
|
+
const r = R(c, n);
|
|
151
|
+
if (r) {
|
|
152
|
+
const f = n === "submit" ? "form.submit" : "form.change";
|
|
153
|
+
a.track(f, r);
|
|
29
154
|
}
|
|
30
|
-
|
|
155
|
+
} catch (r) {
|
|
156
|
+
console.error(`[insights] Failed to track form ${n}`, E(r));
|
|
31
157
|
}
|
|
32
|
-
|
|
158
|
+
}, e = i("change"), t = i("submit");
|
|
159
|
+
return document.addEventListener("change", e, { capture: !0 }), document.addEventListener("submit", t, { capture: !0 }), () => {
|
|
160
|
+
document.removeEventListener("change", e, { capture: !0 }), document.removeEventListener("submit", t, { capture: !0 });
|
|
161
|
+
};
|
|
162
|
+
}, me = (a) => {
|
|
163
|
+
if (typeof window > "u") return () => {
|
|
164
|
+
};
|
|
165
|
+
const { page_id: i } = U.get();
|
|
166
|
+
let e = i || "", t = typeof window < "u" ? window.location.href : "";
|
|
167
|
+
const n = () => {
|
|
168
|
+
const { isIdentified: c } = q.get();
|
|
169
|
+
if (c)
|
|
170
|
+
try {
|
|
171
|
+
a.page({
|
|
172
|
+
resource: "page"
|
|
173
|
+
});
|
|
174
|
+
} catch (r) {
|
|
175
|
+
console.error("[insights] Failed to send page view", E(r));
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
if (i) {
|
|
179
|
+
const c = U.listen((r, f, u) => {
|
|
180
|
+
const { page_id: s } = r;
|
|
181
|
+
u === "page_id" && s && e !== s && (e = s, n());
|
|
182
|
+
});
|
|
183
|
+
return () => {
|
|
184
|
+
c();
|
|
185
|
+
};
|
|
186
|
+
} else {
|
|
187
|
+
const c = () => {
|
|
188
|
+
if (typeof window > "u") return;
|
|
189
|
+
const u = window.location.href;
|
|
190
|
+
u !== t && (t = u, n());
|
|
191
|
+
};
|
|
192
|
+
window.addEventListener("popstate", c);
|
|
193
|
+
const r = window.history.pushState, f = window.history.replaceState;
|
|
194
|
+
return window.history.pushState = function(...u) {
|
|
195
|
+
r.apply(this, u), c();
|
|
196
|
+
}, window.history.replaceState = function(...u) {
|
|
197
|
+
f.apply(this, u), c();
|
|
198
|
+
}, () => {
|
|
199
|
+
window.removeEventListener("popstate", c), window.history.pushState = r, window.history.replaceState = f;
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
}, F = async (a, i) => {
|
|
203
|
+
let e = null;
|
|
204
|
+
try {
|
|
205
|
+
const t = new AbortController();
|
|
206
|
+
return e = setTimeout(() => t.abort(), i), (await fetch(a, {
|
|
207
|
+
method: "GET",
|
|
208
|
+
signal: t.signal,
|
|
209
|
+
credentials: "omit"
|
|
210
|
+
})).ok;
|
|
211
|
+
} catch {
|
|
212
|
+
return !1;
|
|
213
|
+
} finally {
|
|
214
|
+
e && clearTimeout(e);
|
|
215
|
+
}
|
|
216
|
+
}, he = async (a) => {
|
|
217
|
+
const {
|
|
218
|
+
mode: i = "auto",
|
|
219
|
+
insightsUrl: e,
|
|
220
|
+
directInsightsUrl: t,
|
|
221
|
+
pingTimeout: n = 3e3,
|
|
222
|
+
debug: c = !1
|
|
223
|
+
} = a;
|
|
224
|
+
if (c)
|
|
225
|
+
return { mode: "proxy", url: e || "/debug-api" };
|
|
226
|
+
const r = Number.isFinite(n) && n >= 0 ? n : 3e3;
|
|
227
|
+
return i === "direct" ? { mode: "direct", url: t ?? null } : i === "proxy" || !t ? { mode: "proxy", url: e ?? null } : (e ? await F(`${e}/ping`, r) : !1) ? { mode: "proxy", url: e ?? null } : await F(`${t}/ping`, r) ? { mode: "direct", url: t } : { mode: "proxy", url: e ?? null };
|
|
228
|
+
}, we = () => {
|
|
229
|
+
if (typeof document > "u")
|
|
230
|
+
return {};
|
|
231
|
+
const {
|
|
232
|
+
type: a,
|
|
233
|
+
referrer: i,
|
|
234
|
+
data: e = {}
|
|
235
|
+
} = ie({
|
|
236
|
+
referrer: document.referrer,
|
|
237
|
+
currentUrl: window.location.href,
|
|
238
|
+
mapper: null
|
|
239
|
+
}), t = Object.keys(e);
|
|
240
|
+
for (const n of t)
|
|
241
|
+
e[n] && Array.isArray(e[n]) && e[n].length > 0 && (e[n] = e[n]?.[0]);
|
|
242
|
+
return { type: a, referrer: i, data: e, raw: document.referrer };
|
|
243
|
+
}, ve = () => new Promise((a, i) => {
|
|
244
|
+
let e = "Unknown";
|
|
245
|
+
function t(d) {
|
|
246
|
+
a({
|
|
247
|
+
isPrivate: d,
|
|
248
|
+
browserName: e
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
function n() {
|
|
252
|
+
const d = navigator.userAgent;
|
|
253
|
+
return d.match(/Chrome/) ? navigator.brave !== void 0 ? "Brave" : d.match(/Edg/) ? "Edge" : d.match(/OPR/) ? "Opera" : "Chrome" : "Chromium";
|
|
33
254
|
}
|
|
34
|
-
function
|
|
35
|
-
return
|
|
255
|
+
function c(d) {
|
|
256
|
+
return d === eval.toString().length;
|
|
36
257
|
}
|
|
37
|
-
function
|
|
38
|
-
const
|
|
39
|
-
return
|
|
258
|
+
function r() {
|
|
259
|
+
const d = navigator.vendor;
|
|
260
|
+
return d !== void 0 && d.indexOf("Apple") === 0 && c(37);
|
|
40
261
|
}
|
|
41
|
-
function
|
|
42
|
-
const
|
|
43
|
-
return
|
|
262
|
+
function f() {
|
|
263
|
+
const d = navigator.vendor;
|
|
264
|
+
return d !== void 0 && d.indexOf("Google") === 0 && c(33);
|
|
44
265
|
}
|
|
45
|
-
function
|
|
46
|
-
return document.documentElement !== void 0 && document.documentElement.style.MozAppearance !== void 0 &&
|
|
266
|
+
function u() {
|
|
267
|
+
return document.documentElement !== void 0 && document.documentElement.style.MozAppearance !== void 0 && c(37);
|
|
47
268
|
}
|
|
48
|
-
function
|
|
49
|
-
return navigator.msSaveBlob !== void 0 &&
|
|
269
|
+
function s() {
|
|
270
|
+
return navigator.msSaveBlob !== void 0 && c(39);
|
|
50
271
|
}
|
|
51
|
-
function
|
|
52
|
-
const
|
|
272
|
+
function o() {
|
|
273
|
+
const d = String(Math.random());
|
|
53
274
|
try {
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
const
|
|
275
|
+
const g = window.indexedDB.open(d, 1);
|
|
276
|
+
g.onupgradeneeded = (b) => {
|
|
277
|
+
const v = b.target?.result;
|
|
57
278
|
try {
|
|
58
|
-
|
|
59
|
-
autoIncrement:
|
|
60
|
-
}).put(new Blob());
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if (typeof message !== "string") {
|
|
68
|
-
return __callback(false);
|
|
69
|
-
}
|
|
70
|
-
const matchesExpectedError = /BlobURLs are not yet supported/.test(message);
|
|
71
|
-
return __callback(matchesExpectedError);
|
|
279
|
+
v.createObjectStore("test", {
|
|
280
|
+
autoIncrement: !0
|
|
281
|
+
}).put(new Blob()), t(!1);
|
|
282
|
+
} catch (k) {
|
|
283
|
+
let M = k;
|
|
284
|
+
if (k instanceof Error && (M = k.message ?? k), typeof M != "string")
|
|
285
|
+
return t(!1);
|
|
286
|
+
const O = /BlobURLs are not yet supported/.test(M);
|
|
287
|
+
return t(O);
|
|
72
288
|
} finally {
|
|
73
|
-
|
|
74
|
-
window.indexedDB.deleteDatabase(tmp_name);
|
|
289
|
+
v.close(), window.indexedDB.deleteDatabase(d);
|
|
75
290
|
}
|
|
76
291
|
};
|
|
77
|
-
} catch
|
|
78
|
-
return
|
|
292
|
+
} catch {
|
|
293
|
+
return t(!1);
|
|
79
294
|
}
|
|
80
295
|
}
|
|
81
|
-
function
|
|
82
|
-
const
|
|
83
|
-
const storage = window.localStorage;
|
|
296
|
+
function l() {
|
|
297
|
+
const d = window.openDatabase, g = window.localStorage;
|
|
84
298
|
try {
|
|
85
|
-
|
|
86
|
-
} catch
|
|
87
|
-
return
|
|
299
|
+
d(null, null, null, null);
|
|
300
|
+
} catch {
|
|
301
|
+
return t(!0);
|
|
88
302
|
}
|
|
89
303
|
try {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
return __callback(true);
|
|
304
|
+
g.setItem("test", "1"), g.removeItem("test");
|
|
305
|
+
} catch {
|
|
306
|
+
return t(!0);
|
|
94
307
|
}
|
|
95
|
-
return
|
|
308
|
+
return t(!1);
|
|
96
309
|
}
|
|
97
|
-
function
|
|
98
|
-
|
|
99
|
-
newSafariTest();
|
|
100
|
-
} else {
|
|
101
|
-
oldSafariTest();
|
|
102
|
-
}
|
|
310
|
+
function h() {
|
|
311
|
+
navigator.maxTouchPoints !== void 0 ? o() : l();
|
|
103
312
|
}
|
|
104
|
-
function
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
return performance.memory.jsHeapSizeLimit;
|
|
108
|
-
}
|
|
109
|
-
return 1073741824;
|
|
313
|
+
function y() {
|
|
314
|
+
const d = window;
|
|
315
|
+
return d.performance !== void 0 && d.performance.memory !== void 0 && d.performance.memory.jsHeapSizeLimit !== void 0 ? performance.memory.jsHeapSizeLimit : 1073741824;
|
|
110
316
|
}
|
|
111
|
-
function
|
|
317
|
+
function w() {
|
|
112
318
|
navigator.webkitTemporaryStorage.queryUsageAndQuota(
|
|
113
|
-
(
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
__callback(quotaInMib < quotaLimitInMib);
|
|
319
|
+
(d, g) => {
|
|
320
|
+
const b = Math.round(g / 1048576), v = Math.round(y() / (1024 * 1024)) * 2;
|
|
321
|
+
t(b < v);
|
|
117
322
|
},
|
|
118
|
-
(
|
|
119
|
-
|
|
323
|
+
(d) => {
|
|
324
|
+
i(new Error(`detectIncognito somehow failed to query storage quota: ${d.message}`));
|
|
120
325
|
}
|
|
121
326
|
);
|
|
122
327
|
}
|
|
123
|
-
function
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
};
|
|
131
|
-
fs(0, 1, success, error);
|
|
328
|
+
function p() {
|
|
329
|
+
const d = window.webkitRequestFileSystem;
|
|
330
|
+
d(0, 1, () => {
|
|
331
|
+
t(!1);
|
|
332
|
+
}, () => {
|
|
333
|
+
t(!0);
|
|
334
|
+
});
|
|
132
335
|
}
|
|
133
|
-
function
|
|
134
|
-
|
|
135
|
-
storageQuotaChromePrivateTest();
|
|
136
|
-
} else {
|
|
137
|
-
oldChromePrivateTest();
|
|
138
|
-
}
|
|
336
|
+
function I() {
|
|
337
|
+
self.Promise !== void 0 && self.Promise.allSettled !== void 0 ? w() : p();
|
|
139
338
|
}
|
|
140
|
-
function
|
|
141
|
-
|
|
339
|
+
function D() {
|
|
340
|
+
t(navigator.serviceWorker === void 0);
|
|
142
341
|
}
|
|
143
|
-
function
|
|
144
|
-
|
|
342
|
+
function B() {
|
|
343
|
+
t(window.indexedDB === void 0);
|
|
145
344
|
}
|
|
146
|
-
function
|
|
147
|
-
|
|
148
|
-
browserName = "Safari";
|
|
149
|
-
safariPrivateTest();
|
|
150
|
-
} else if (isChrome()) {
|
|
151
|
-
browserName = identifyChromium();
|
|
152
|
-
chromePrivateTest();
|
|
153
|
-
} else if (isFirefox()) {
|
|
154
|
-
browserName = "Firefox";
|
|
155
|
-
firefoxPrivateTest();
|
|
156
|
-
} else if (isMSIE()) {
|
|
157
|
-
browserName = "Internet Explorer";
|
|
158
|
-
msiePrivateTest();
|
|
159
|
-
} else {
|
|
160
|
-
reject(new Error("detectIncognito cannot determine the browser"));
|
|
161
|
-
}
|
|
345
|
+
function L() {
|
|
346
|
+
r() ? (e = "Safari", h()) : f() ? (e = n(), I()) : u() ? (e = "Firefox", D()) : s() ? (e = "Internet Explorer", B()) : i(new Error("detectIncognito cannot determine the browser"));
|
|
162
347
|
}
|
|
163
|
-
|
|
164
|
-
})
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
// src/utils/getUserProperties.ts
|
|
168
|
-
var getGPUInfo = () => {
|
|
169
|
-
const canvas = document.createElement("canvas");
|
|
170
|
-
const gl = canvas?.getContext("webgl") || canvas?.getContext("experimental-webgl");
|
|
171
|
-
if (!gl) {
|
|
348
|
+
L();
|
|
349
|
+
}), ye = () => {
|
|
350
|
+
const a = document.createElement("canvas"), i = a?.getContext("webgl") || a?.getContext("experimental-webgl");
|
|
351
|
+
if (!i)
|
|
172
352
|
return null;
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
let timezone = "";
|
|
180
|
-
let dark_mode = false;
|
|
181
|
-
let private_mode = false;
|
|
182
|
-
const properties = {};
|
|
183
|
-
if (!window) {
|
|
353
|
+
const e = i?.getExtension("WEBGL_debug_renderer_info");
|
|
354
|
+
return e ? i?.getParameter(e.UNMASKED_RENDERER_WEBGL) : null;
|
|
355
|
+
}, ke = async () => {
|
|
356
|
+
let a = "", i = "", e = !1, t = !1;
|
|
357
|
+
const n = {};
|
|
358
|
+
if (!window)
|
|
184
359
|
return {
|
|
185
|
-
locale,
|
|
186
|
-
timezone,
|
|
187
|
-
dark_mode,
|
|
188
|
-
private_mode,
|
|
189
|
-
properties
|
|
360
|
+
locale: a,
|
|
361
|
+
timezone: i,
|
|
362
|
+
dark_mode: e,
|
|
363
|
+
private_mode: t,
|
|
364
|
+
properties: n
|
|
190
365
|
};
|
|
191
|
-
}
|
|
192
366
|
try {
|
|
193
|
-
({ isPrivate:
|
|
194
|
-
} catch (
|
|
195
|
-
console.error(
|
|
367
|
+
({ isPrivate: t } = await ve());
|
|
368
|
+
} catch (r) {
|
|
369
|
+
console.error(r);
|
|
196
370
|
}
|
|
197
371
|
try {
|
|
198
|
-
|
|
199
|
-
} catch (
|
|
200
|
-
console.error(
|
|
372
|
+
e = window.matchMedia?.("(prefers-color-scheme: dark)").matches;
|
|
373
|
+
} catch (r) {
|
|
374
|
+
console.error(r);
|
|
201
375
|
}
|
|
202
376
|
try {
|
|
203
|
-
|
|
204
|
-
} catch (
|
|
205
|
-
console.error(
|
|
377
|
+
i = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
378
|
+
} catch (r) {
|
|
379
|
+
console.error(r);
|
|
206
380
|
}
|
|
207
381
|
try {
|
|
208
|
-
|
|
209
|
-
} catch (
|
|
210
|
-
console.error(
|
|
382
|
+
a = oe();
|
|
383
|
+
} catch (r) {
|
|
384
|
+
console.error(r);
|
|
211
385
|
}
|
|
212
386
|
if (navigator && "connection" in navigator) {
|
|
213
|
-
const
|
|
214
|
-
|
|
387
|
+
const r = navigator.connection || navigator?.mozConnection || navigator.webkitConnection;
|
|
388
|
+
n.network_type = r.effectiveType;
|
|
215
389
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
if (screen) {
|
|
220
|
-
properties.screen_width = screen?.width;
|
|
221
|
-
properties.screen_height = screen?.height;
|
|
222
|
-
properties.color_depth = screen?.colorDepth;
|
|
223
|
-
properties.orientation = screen?.orientation?.type;
|
|
224
|
-
}
|
|
225
|
-
if (navigator && "getBattery" in navigator) {
|
|
226
|
-
const battery = await navigator?.getBattery();
|
|
227
|
-
if (battery) {
|
|
228
|
-
properties.battery_level = Number((battery?.level * 100).toFixed(0));
|
|
229
|
-
properties.battery_charging = battery?.charging;
|
|
230
|
-
properties.battery_discharging_time = battery?.dischargingTime;
|
|
231
|
-
properties.battery_full_charge_capacity = battery?.fullChargeCapacity;
|
|
232
|
-
properties.battery_charging_time = battery?.chargingTime;
|
|
233
|
-
}
|
|
390
|
+
if (n.width = window?.innerWidth, n.height = window?.innerHeight, n.pixel_ratio = window?.devicePixelRatio, screen && (n.screen_width = screen?.width, n.screen_height = screen?.height, n.color_depth = screen?.colorDepth, n.orientation = screen?.orientation?.type), navigator && "getBattery" in navigator) {
|
|
391
|
+
const r = await navigator?.getBattery();
|
|
392
|
+
r && (n.battery_level = Number((r?.level * 100).toFixed(0)), n.battery_charging = r?.charging, n.battery_discharging_time = r?.dischargingTime, n.battery_full_charge_capacity = r?.fullChargeCapacity, n.battery_charging_time = r?.chargingTime);
|
|
234
393
|
}
|
|
235
|
-
|
|
236
|
-
|
|
394
|
+
navigator && "deviceMemory" in navigator && (n.device_memory = navigator?.deviceMemory);
|
|
395
|
+
const c = "ontouchstart" in window || typeof navigator?.maxTouchPoints < "u" && navigator?.maxTouchPoints > 0;
|
|
396
|
+
if (n.touch_supported = c, "hardwareConcurrency" in navigator && (n.hardware_concurrency = navigator?.hardwareConcurrency), navigator && "mediaDevices" in navigator) {
|
|
397
|
+
const f = await navigator?.mediaDevices?.enumerateDevices(), u = f.some((o) => o?.kind === "videoinput");
|
|
398
|
+
n.camera_supported = u;
|
|
399
|
+
const s = f.some((o) => o?.kind === "audioinput");
|
|
400
|
+
n.microphone_supported = s;
|
|
237
401
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
const mediaDevices = navigator?.mediaDevices;
|
|
245
|
-
const devices = await mediaDevices?.enumerateDevices();
|
|
246
|
-
const hasCamera = devices.some((device) => device?.kind === "videoinput");
|
|
247
|
-
properties.camera_supported = hasCamera;
|
|
248
|
-
const hasMicrophone = devices.some((device) => device?.kind === "audioinput");
|
|
249
|
-
properties.microphone_supported = hasMicrophone;
|
|
250
|
-
}
|
|
251
|
-
properties.gpu = getGPUInfo();
|
|
252
|
-
return {
|
|
253
|
-
locale,
|
|
254
|
-
timezone,
|
|
255
|
-
dark_mode,
|
|
256
|
-
private_mode,
|
|
257
|
-
properties
|
|
258
|
-
};
|
|
259
|
-
};
|
|
260
|
-
var AnalyticsEventsList = [
|
|
261
|
-
// Bevy Events
|
|
262
|
-
"bevy.collection.filled",
|
|
263
|
-
"bevy.collection.submitted",
|
|
264
|
-
"bevy.collection.view",
|
|
265
|
-
// Block Events
|
|
266
|
-
"block.view",
|
|
267
|
-
// Blog Events
|
|
268
|
-
"blog.post.view",
|
|
269
|
-
// Event Events
|
|
270
|
-
"event.booking.confirmed",
|
|
271
|
-
"event.booking.initiated",
|
|
272
|
-
"event.booking.pending",
|
|
273
|
-
"event.coupon.applied",
|
|
274
|
-
"event.event.view",
|
|
275
|
-
// Form Events
|
|
276
|
-
"form.change",
|
|
277
|
-
"form.submit",
|
|
278
|
-
// Membership Events
|
|
279
|
-
"membership.account.signin",
|
|
280
|
-
"membership.account.signout",
|
|
281
|
-
"membership.account.signup",
|
|
282
|
-
// UI Events
|
|
283
|
-
"button.click",
|
|
284
|
-
"page.bounce",
|
|
285
|
-
"page.click",
|
|
286
|
-
"page.copy",
|
|
287
|
-
"page.impression",
|
|
288
|
-
"page.scroll",
|
|
289
|
-
"page.view",
|
|
290
|
-
"page.selection",
|
|
291
|
-
// User Activity Events
|
|
292
|
-
"user.active",
|
|
293
|
-
"user.idle"
|
|
294
|
-
];
|
|
295
|
-
var AnalyticsEvents = listToRecord(AnalyticsEventsList);
|
|
296
|
-
|
|
297
|
-
// src/index.ts
|
|
298
|
-
var BATCH_SIZE = 50;
|
|
299
|
-
var BATCH_INTERVAL_MS = 5e3;
|
|
300
|
-
var MAX_EVENTS_PER_PAGE = 500;
|
|
301
|
-
var BROADCAST_CHANNEL_NAME = "levo_analytics";
|
|
302
|
-
var createLevoInsights = (client, options = {}) => {
|
|
303
|
-
const { workspace, fetch: levoFetch, NODE_ENV } = client;
|
|
304
|
-
const {
|
|
305
|
-
insightsMode = "auto",
|
|
306
|
-
insightsUrl = "",
|
|
307
|
-
directInsightsUrl = "",
|
|
308
|
-
pingTimeout: providedPingTimeout = 3e3,
|
|
309
|
-
site
|
|
310
|
-
} = options;
|
|
311
|
-
const pingTimeout = Number.isFinite(providedPingTimeout) && providedPingTimeout >= 0 ? providedPingTimeout : 3e3;
|
|
312
|
-
const _IDLE_THROTTLE = 1 * 1e3;
|
|
313
|
-
const _IDLE_TIMEOUT = 60 * 1e3;
|
|
314
|
-
let instance = null;
|
|
315
|
-
let idle_listener = null;
|
|
316
|
-
const storage_keys = {
|
|
317
|
-
/** Legacy: Lock key for identify operation (no longer used internally) */
|
|
318
|
-
identify: "lock:lv_aud_identify",
|
|
319
|
-
/** Key for tracking open tab count */
|
|
320
|
-
open_tabs: "lv_insights_ot",
|
|
321
|
-
/** Key for current tab ID (sessionStorage) */
|
|
322
|
-
current_tab: "lv_insights_ct",
|
|
323
|
-
/** Key for all tabs registry */
|
|
324
|
-
all_tabs: "lv_insights_at",
|
|
325
|
-
/** Device JWT for direct mode (1yr expiry, rotated on /welcome, analytics-only scope) */
|
|
326
|
-
device_token: "lv_aud_device",
|
|
327
|
-
/** Session JWT for direct mode (1yr expiry, rotated on /welcome, analytics-only scope) */
|
|
328
|
-
session_token: "lv_aud_session",
|
|
329
|
-
/** Cached insights mode ('proxy' | 'direct') */
|
|
330
|
-
mode: "lv_aud_mode"
|
|
331
|
-
};
|
|
332
|
-
let _insightsMode = "proxy";
|
|
333
|
-
let _insightsBaseUrl = "";
|
|
334
|
-
let _localStorageAvailable = true;
|
|
335
|
-
const _memoryStorage = /* @__PURE__ */ new Map();
|
|
336
|
-
const checkLocalStorageAvailable = () => {
|
|
337
|
-
if (typeof window === "undefined" || !("localStorage" in window)) {
|
|
338
|
-
return false;
|
|
339
|
-
}
|
|
340
|
-
try {
|
|
341
|
-
const testKey = "__levo_test__";
|
|
342
|
-
window.localStorage.setItem(testKey, "test");
|
|
343
|
-
window.localStorage.removeItem(testKey);
|
|
344
|
-
return true;
|
|
345
|
-
} catch {
|
|
346
|
-
return false;
|
|
347
|
-
}
|
|
348
|
-
};
|
|
349
|
-
const getFromStorage = (key) => {
|
|
350
|
-
if (typeof window === "undefined") {
|
|
351
|
-
return _memoryStorage.get(key) || null;
|
|
352
|
-
}
|
|
353
|
-
if (_localStorageAvailable) {
|
|
354
|
-
try {
|
|
355
|
-
return window.localStorage.getItem(key);
|
|
356
|
-
} catch {
|
|
357
|
-
return _memoryStorage.get(key) || null;
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
return _memoryStorage.get(key) || null;
|
|
361
|
-
};
|
|
362
|
-
const setInStorage = (key, value) => {
|
|
363
|
-
if (typeof window === "undefined") {
|
|
364
|
-
_memoryStorage.set(key, value);
|
|
365
|
-
return;
|
|
366
|
-
}
|
|
367
|
-
if (_localStorageAvailable) {
|
|
368
|
-
try {
|
|
369
|
-
window.localStorage.setItem(key, value);
|
|
370
|
-
return;
|
|
371
|
-
} catch {
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
_memoryStorage.set(key, value);
|
|
375
|
-
};
|
|
376
|
-
const removeFromStorage = (key) => {
|
|
377
|
-
_memoryStorage.delete(key);
|
|
378
|
-
if (typeof window === "undefined" || !_localStorageAvailable) {
|
|
379
|
-
return;
|
|
380
|
-
}
|
|
381
|
-
try {
|
|
382
|
-
window.localStorage.removeItem(key);
|
|
383
|
-
} catch {
|
|
384
|
-
}
|
|
402
|
+
return n.gpu = ye(), {
|
|
403
|
+
locale: a,
|
|
404
|
+
timezone: i,
|
|
405
|
+
dark_mode: e,
|
|
406
|
+
private_mode: t,
|
|
407
|
+
properties: n
|
|
385
408
|
};
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
409
|
+
}, be = (a, i, e) => {
|
|
410
|
+
const { debug: t } = P();
|
|
411
|
+
if (!a)
|
|
412
|
+
return null;
|
|
413
|
+
const n = {
|
|
414
|
+
name: a.workspace,
|
|
415
|
+
/**
|
|
416
|
+
* Handle track events (custom events like clicks, scrolls, etc.)
|
|
417
|
+
*
|
|
418
|
+
* Enriches the event with:
|
|
419
|
+
* - Session/device IDs
|
|
420
|
+
* - Page metadata (URL, title, etc.)
|
|
421
|
+
* - Tab information
|
|
422
|
+
* - Timestamp
|
|
423
|
+
*
|
|
424
|
+
* Then queues for batched sending.
|
|
425
|
+
*/
|
|
426
|
+
track: ({ payload: c }) => {
|
|
427
|
+
if (!e()) return;
|
|
428
|
+
const r = c?.properties || {};
|
|
429
|
+
i(c.event, r);
|
|
430
|
+
},
|
|
431
|
+
/**
|
|
432
|
+
* Handle page view events.
|
|
433
|
+
*
|
|
434
|
+
* Called when navigating to a new page (in SPAs) or on initial load.
|
|
435
|
+
* Resets the rate limit counter and tracks a page.view event.
|
|
436
|
+
*/
|
|
437
|
+
page: ({ payload: c }) => {
|
|
438
|
+
if (!e()) return;
|
|
439
|
+
$();
|
|
440
|
+
const r = c?.properties || {};
|
|
441
|
+
i("page.view", {
|
|
442
|
+
...r,
|
|
443
|
+
resource: "page"
|
|
405
444
|
});
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
return cachedMode;
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
if (await pingEndpoint(`${insightsUrl}/ping`, pingTimeout)) {
|
|
446
|
-
setInStorage(storage_keys.mode, "proxy");
|
|
447
|
-
_insightsBaseUrl = insightsUrl;
|
|
448
|
-
return "proxy";
|
|
449
|
-
}
|
|
450
|
-
if (directInsightsUrl) {
|
|
451
|
-
setInStorage(storage_keys.mode, "direct");
|
|
452
|
-
_insightsBaseUrl = directInsightsUrl;
|
|
453
|
-
return "direct";
|
|
454
|
-
}
|
|
455
|
-
_insightsBaseUrl = insightsUrl;
|
|
456
|
-
return "proxy";
|
|
457
|
-
};
|
|
458
|
-
let _session = "";
|
|
459
|
-
let _device = "";
|
|
460
|
-
let is_identified = false;
|
|
461
|
-
let _eventCount = 0;
|
|
462
|
-
let _eventQueue = [];
|
|
463
|
-
let _flushTimer = null;
|
|
464
|
-
let _visibilityHandler = null;
|
|
465
|
-
let _beforeUnloadHandler = null;
|
|
466
|
-
let _pageHideHandler = null;
|
|
467
|
-
let _channel = null;
|
|
468
|
-
let _pendingIdentify = false;
|
|
469
|
-
const buildSessionSyncMessage = () => {
|
|
470
|
-
const message = {
|
|
471
|
-
type: "SESSION_SYNC",
|
|
472
|
-
session: _session,
|
|
473
|
-
device: _device
|
|
474
|
-
};
|
|
475
|
-
if (_insightsMode === "direct") {
|
|
476
|
-
const storedDeviceToken = getFromStorage(storage_keys.device_token);
|
|
477
|
-
const storedSessionToken = getFromStorage(storage_keys.session_token);
|
|
478
|
-
if (storedDeviceToken) message.deviceToken = storedDeviceToken;
|
|
479
|
-
if (storedSessionToken) message.sessionToken = storedSessionToken;
|
|
480
|
-
}
|
|
481
|
-
return message;
|
|
482
|
-
};
|
|
483
|
-
const initBroadcastChannel = () => {
|
|
484
|
-
if (typeof BroadcastChannel === "undefined") {
|
|
485
|
-
return;
|
|
486
|
-
}
|
|
487
|
-
try {
|
|
488
|
-
_channel = new BroadcastChannel(BROADCAST_CHANNEL_NAME);
|
|
489
|
-
_channel.onmessage = (event) => {
|
|
490
|
-
const { type, session, device, deviceToken, sessionToken } = event.data;
|
|
491
|
-
if (type === "SESSION_SYNC" && !is_identified) {
|
|
492
|
-
_session = session;
|
|
493
|
-
_device = device;
|
|
494
|
-
is_identified = true;
|
|
495
|
-
_pendingIdentify = false;
|
|
496
|
-
if (_insightsMode === "direct" && deviceToken && sessionToken) {
|
|
497
|
-
setInStorage(storage_keys.device_token, deviceToken);
|
|
498
|
-
setInStorage(storage_keys.session_token, sessionToken);
|
|
445
|
+
},
|
|
446
|
+
/**
|
|
447
|
+
* Handle identify events (session establishment).
|
|
448
|
+
*
|
|
449
|
+
* This is called when identify() is invoked. It:
|
|
450
|
+
* 1. Reads identity from session store (set by init())
|
|
451
|
+
* 2. Checks if already identified (via BroadcastChannel) - if so, skip
|
|
452
|
+
* 3. Calls /welcome API to get session/device IDs
|
|
453
|
+
* 4. On success, broadcasts session to other tabs
|
|
454
|
+
*
|
|
455
|
+
* The /welcome API uses HttpOnly cookies to maintain persistent
|
|
456
|
+
* device identity across sessions.
|
|
457
|
+
*/
|
|
458
|
+
identify: ({ payload: c }) => {
|
|
459
|
+
if (!e()) return;
|
|
460
|
+
const { workspace: r, site_id: f, debug: u } = P(), {
|
|
461
|
+
mode: s,
|
|
462
|
+
isIdentified: o,
|
|
463
|
+
isIdentifying: l,
|
|
464
|
+
sessionToken: h,
|
|
465
|
+
deviceToken: y,
|
|
466
|
+
insightsBaseUrl: w,
|
|
467
|
+
identity: p
|
|
468
|
+
} = C(), I = z(), D = C().allTabs.length;
|
|
469
|
+
if (!w || !p)
|
|
470
|
+
return;
|
|
471
|
+
const L = {
|
|
472
|
+
...{
|
|
473
|
+
private_mode: c.traits?.private_mode ?? p.privateMode ?? !1,
|
|
474
|
+
dark_mode: c.traits?.dark_mode ?? p.darkMode ?? !1,
|
|
475
|
+
timezone: c.traits?.timezone ?? p.timezone ?? "",
|
|
476
|
+
locale: c.traits?.locale ?? p.locale ?? "",
|
|
477
|
+
referrer: c.traits?.referrer ?? p.referrer ?? { type: "", referrer: {}, data: {} },
|
|
478
|
+
properties: {
|
|
479
|
+
...p.properties
|
|
499
480
|
}
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
481
|
+
},
|
|
482
|
+
workspace_id: r ?? "",
|
|
483
|
+
site_id: f ?? void 0,
|
|
484
|
+
hostname: window.location.hostname,
|
|
485
|
+
pathname: window.location.pathname,
|
|
486
|
+
page_title: document.title,
|
|
487
|
+
url: window.location.href,
|
|
488
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
489
|
+
tab_id: I ?? "",
|
|
490
|
+
tab_count: D ?? 0
|
|
504
491
|
};
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
}
|
|
519
|
-
const batch = _eventQueue.map((event) => ({
|
|
520
|
-
...event,
|
|
521
|
-
session_id: event.session_id || _session,
|
|
522
|
-
device_id: event.device_id || _device
|
|
523
|
-
}));
|
|
524
|
-
_eventQueue = [];
|
|
525
|
-
const url = `${baseUrl}/v1/insights/event/bulk?workspace=${workspace}`;
|
|
526
|
-
const headers = {
|
|
527
|
-
"Content-Type": "application/json",
|
|
528
|
-
...getAuthHeaders()
|
|
529
|
-
};
|
|
530
|
-
if (_insightsMode === "proxy" && navigator.sendBeacon) {
|
|
531
|
-
const success = navigator.sendBeacon(url, JSON.stringify(batch));
|
|
532
|
-
if (success) {
|
|
492
|
+
if (u && console.log("[@levo-so/insights] Identification triggered:", {
|
|
493
|
+
isIdentified: o,
|
|
494
|
+
isIdentifying: l,
|
|
495
|
+
welcomeInput: L
|
|
496
|
+
}), o || l)
|
|
497
|
+
return;
|
|
498
|
+
if (T({ isIdentifying: !0 }), u) {
|
|
499
|
+
console.log("[@levo-so/insights] Debug mode enabled. Mocking session identification."), T({
|
|
500
|
+
isIdentified: !0,
|
|
501
|
+
isIdentifying: !1,
|
|
502
|
+
sessionId: "debug-session",
|
|
503
|
+
deviceId: "debug-device"
|
|
504
|
+
});
|
|
533
505
|
return;
|
|
534
506
|
}
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
headers,
|
|
540
|
-
keepalive: true,
|
|
541
|
-
credentials: _insightsMode === "proxy" ? "include" : "omit"
|
|
542
|
-
}).catch(() => {
|
|
543
|
-
});
|
|
544
|
-
};
|
|
545
|
-
const startFlushTimer = () => {
|
|
546
|
-
if (_flushTimer) {
|
|
547
|
-
return;
|
|
548
|
-
}
|
|
549
|
-
_flushTimer = setInterval(() => {
|
|
550
|
-
flushEventQueue();
|
|
551
|
-
}, BATCH_INTERVAL_MS);
|
|
552
|
-
if (typeof document !== "undefined") {
|
|
553
|
-
_visibilityHandler = () => {
|
|
554
|
-
if (document.visibilityState === "hidden") {
|
|
555
|
-
flushEventQueue();
|
|
556
|
-
}
|
|
507
|
+
const d = {
|
|
508
|
+
Accept: "application/json",
|
|
509
|
+
"Content-Type": "application/json",
|
|
510
|
+
...G({ sessionToken: h, deviceToken: y, mode: s })
|
|
557
511
|
};
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
const stopFlushTimer = () => {
|
|
570
|
-
if (_flushTimer) {
|
|
571
|
-
clearInterval(_flushTimer);
|
|
572
|
-
_flushTimer = null;
|
|
573
|
-
}
|
|
574
|
-
if (typeof document !== "undefined") {
|
|
575
|
-
if (_visibilityHandler) {
|
|
576
|
-
document.removeEventListener("visibilitychange", _visibilityHandler);
|
|
577
|
-
_visibilityHandler = null;
|
|
578
|
-
}
|
|
579
|
-
if (_beforeUnloadHandler) {
|
|
580
|
-
window.removeEventListener("beforeunload", _beforeUnloadHandler);
|
|
581
|
-
_beforeUnloadHandler = null;
|
|
582
|
-
}
|
|
583
|
-
if (_pageHideHandler) {
|
|
584
|
-
window.removeEventListener("pagehide", _pageHideHandler);
|
|
585
|
-
_pageHideHandler = null;
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
};
|
|
589
|
-
const queueEvent = (collectInput) => {
|
|
590
|
-
if (_eventCount >= MAX_EVENTS_PER_PAGE) {
|
|
591
|
-
console.warn(`[@levo-so/core] Event limit (${MAX_EVENTS_PER_PAGE}) reached for this page`);
|
|
592
|
-
return;
|
|
593
|
-
}
|
|
594
|
-
_eventCount++;
|
|
595
|
-
_eventQueue.push(collectInput);
|
|
596
|
-
if (_eventQueue.length >= BATCH_SIZE) {
|
|
597
|
-
flushEventQueue();
|
|
598
|
-
}
|
|
599
|
-
};
|
|
600
|
-
const getReferrer = () => {
|
|
601
|
-
if (typeof document === "undefined") {
|
|
602
|
-
return {};
|
|
603
|
-
}
|
|
604
|
-
const {
|
|
605
|
-
type,
|
|
606
|
-
referrer,
|
|
607
|
-
data = {}
|
|
608
|
-
} = getVisitorSource({
|
|
609
|
-
referrer: document.referrer,
|
|
610
|
-
currentUrl: window.location.href,
|
|
611
|
-
mapper: null
|
|
612
|
-
});
|
|
613
|
-
const dataKeys = Object.keys(data);
|
|
614
|
-
for (const key of dataKeys) {
|
|
615
|
-
if (data[key] && Array.isArray(data[key]) && data[key].length > 0) {
|
|
616
|
-
data[key] = data[key]?.[0];
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
return { type, referrer, data, raw: document.referrer };
|
|
620
|
-
};
|
|
621
|
-
const getCurrentTabId = () => {
|
|
622
|
-
try {
|
|
623
|
-
if (typeof window === "undefined" || !("sessionStorage" in window)) {
|
|
624
|
-
return "";
|
|
625
|
-
}
|
|
626
|
-
return window.sessionStorage.getItem(storage_keys.current_tab) || "";
|
|
627
|
-
} catch {
|
|
628
|
-
return "";
|
|
629
|
-
}
|
|
630
|
-
};
|
|
631
|
-
const getTabCount = () => {
|
|
632
|
-
try {
|
|
633
|
-
if (typeof window === "undefined" || !("localStorage" in window)) {
|
|
634
|
-
return 0;
|
|
635
|
-
}
|
|
636
|
-
return Number(window.localStorage.getItem(storage_keys.open_tabs)) || 0;
|
|
637
|
-
} catch {
|
|
638
|
-
return 0;
|
|
639
|
-
}
|
|
640
|
-
};
|
|
641
|
-
const getActivityStatus = () => {
|
|
642
|
-
const status = idle_listener?.getStatus();
|
|
643
|
-
if (!status) {
|
|
644
|
-
return null;
|
|
645
|
-
}
|
|
646
|
-
return {
|
|
647
|
-
status: status.isIdle ? "idle" : "active",
|
|
648
|
-
seconds: status.isIdle ? status.idle : status.active
|
|
649
|
-
};
|
|
650
|
-
};
|
|
651
|
-
const identify = async (options2) => {
|
|
652
|
-
if (!instance) {
|
|
653
|
-
return;
|
|
654
|
-
}
|
|
655
|
-
const withLock = options2?.withLock ?? true;
|
|
656
|
-
const referrer = getReferrer();
|
|
657
|
-
const traits = await getUserProperties();
|
|
658
|
-
await instance.identify("", {
|
|
659
|
-
...traits,
|
|
660
|
-
referrer,
|
|
661
|
-
withLock
|
|
662
|
-
});
|
|
663
|
-
};
|
|
664
|
-
const request = async (url, data) => {
|
|
665
|
-
const headers = {
|
|
666
|
-
Accept: "application/json",
|
|
667
|
-
"Content-Type": "application/json",
|
|
668
|
-
...getAuthHeaders()
|
|
669
|
-
};
|
|
670
|
-
try {
|
|
671
|
-
const response = await levoFetch.url(_insightsBaseUrl || insightsUrl, true).url(url).options({
|
|
672
|
-
keepAlive: true,
|
|
673
|
-
credentials: _insightsMode === "proxy" ? "include" : "omit"
|
|
674
|
-
}).headers(headers).post(data).json();
|
|
675
|
-
return response;
|
|
676
|
-
} catch (error) {
|
|
677
|
-
console.warn(`Analytics request failed for ${url}:`, error);
|
|
678
|
-
return null;
|
|
679
|
-
}
|
|
680
|
-
};
|
|
681
|
-
const initiate = async (properties) => {
|
|
682
|
-
if (NODE_ENV === "development") {
|
|
683
|
-
return;
|
|
684
|
-
}
|
|
685
|
-
_eventCount = 0;
|
|
686
|
-
_localStorageAvailable = checkLocalStorageAvailable();
|
|
687
|
-
_insightsMode = await detectInsightsMode();
|
|
688
|
-
initBroadcastChannel();
|
|
689
|
-
requestSessionFromOtherTabs();
|
|
690
|
-
startFlushTimer();
|
|
691
|
-
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
692
|
-
const plugin = {
|
|
693
|
-
name: workspace,
|
|
694
|
-
/**
|
|
695
|
-
* Handle track events (custom events like clicks, scrolls, etc.)
|
|
696
|
-
*
|
|
697
|
-
* Enriches the event with:
|
|
698
|
-
* - Session/device IDs
|
|
699
|
-
* - Page metadata (URL, title, etc.)
|
|
700
|
-
* - Tab information
|
|
701
|
-
* - Timestamp
|
|
702
|
-
*
|
|
703
|
-
* Then queues for batched sending.
|
|
704
|
-
*/
|
|
705
|
-
track: ({ payload }) => {
|
|
706
|
-
if (!insightsUrl || !workspace) {
|
|
707
|
-
return;
|
|
708
|
-
}
|
|
709
|
-
const payloadProperties = payload?.properties || {};
|
|
710
|
-
const collectInput = {
|
|
711
|
-
session_id: _session,
|
|
712
|
-
device_id: _device,
|
|
713
|
-
event: payload.event,
|
|
714
|
-
version: payload.version || 1,
|
|
715
|
-
workspace_id: workspace,
|
|
716
|
-
site_id: site || void 0,
|
|
717
|
-
properties: {
|
|
718
|
-
...properties,
|
|
719
|
-
...payloadProperties,
|
|
720
|
-
// Remove metadata fields from properties (they're top-level)
|
|
721
|
-
version: void 0,
|
|
722
|
-
resource: void 0,
|
|
723
|
-
identifier: void 0,
|
|
724
|
-
hostname: void 0,
|
|
725
|
-
pathname: void 0,
|
|
726
|
-
url: void 0,
|
|
727
|
-
page_title: void 0,
|
|
728
|
-
created_at: void 0
|
|
729
|
-
},
|
|
730
|
-
hostname: payload?.hostname || window.location.hostname,
|
|
731
|
-
pathname: payload?.pathname || window.location.pathname,
|
|
732
|
-
url: payload?.url || window.location.href,
|
|
733
|
-
page_title: payload?.page_title || document.title,
|
|
734
|
-
resource: payloadProperties?.resource || "page",
|
|
735
|
-
identifier: payloadProperties?.identifier || properties?.id,
|
|
736
|
-
created_at: payload?.created_at || (/* @__PURE__ */ new Date()).toISOString(),
|
|
737
|
-
tab_id: getCurrentTabId(),
|
|
738
|
-
tab_count: getTabCount()
|
|
739
|
-
};
|
|
740
|
-
queueEvent(collectInput);
|
|
741
|
-
},
|
|
742
|
-
/**
|
|
743
|
-
* Handle page view events.
|
|
744
|
-
*
|
|
745
|
-
* Called when navigating to a new page (in SPAs) or on initial load.
|
|
746
|
-
* Resets the rate limit counter and tracks a page.view event.
|
|
747
|
-
*/
|
|
748
|
-
page: ({ payload }) => {
|
|
749
|
-
if (!insightsUrl) {
|
|
750
|
-
return;
|
|
751
|
-
}
|
|
752
|
-
_eventCount = 0;
|
|
753
|
-
const payloadProperties = payload?.properties || {};
|
|
754
|
-
track("page.view", {
|
|
755
|
-
...properties,
|
|
756
|
-
...payloadProperties,
|
|
757
|
-
title: document.title,
|
|
758
|
-
identifier: properties.id,
|
|
759
|
-
resource: "page"
|
|
760
|
-
});
|
|
761
|
-
},
|
|
762
|
-
/**
|
|
763
|
-
* Handle identify events (session establishment).
|
|
764
|
-
*
|
|
765
|
-
* This is called when identify() is invoked. It:
|
|
766
|
-
* 1. Checks if already identified (via BroadcastChannel) - if so, skip
|
|
767
|
-
* 2. Calls /welcome API to get session/device IDs
|
|
768
|
-
* 3. On success, broadcasts session to other tabs
|
|
769
|
-
*
|
|
770
|
-
* The /welcome API uses HttpOnly cookies to maintain persistent
|
|
771
|
-
* device identity across sessions.
|
|
772
|
-
*/
|
|
773
|
-
identify: ({ payload }) => {
|
|
774
|
-
if (!insightsUrl || !workspace) {
|
|
775
|
-
return;
|
|
776
|
-
}
|
|
777
|
-
if (is_identified) {
|
|
778
|
-
return;
|
|
779
|
-
}
|
|
780
|
-
if (_pendingIdentify) {
|
|
781
|
-
return;
|
|
782
|
-
}
|
|
783
|
-
_pendingIdentify = true;
|
|
784
|
-
const welcomeInput = {
|
|
785
|
-
private_mode: payload.traits.private_mode,
|
|
786
|
-
dark_mode: payload.traits.dark_mode,
|
|
787
|
-
timezone: payload.traits.timezone,
|
|
788
|
-
locale: payload.traits.locale,
|
|
789
|
-
referrer: payload.traits.referrer,
|
|
790
|
-
properties: payload.traits.properties,
|
|
791
|
-
workspace_id: workspace,
|
|
792
|
-
site_id: site || void 0,
|
|
793
|
-
hostname: window.location.hostname,
|
|
794
|
-
pathname: window.location.pathname,
|
|
795
|
-
page_title: document.title,
|
|
796
|
-
url: window.location.href,
|
|
797
|
-
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
798
|
-
tab_id: getCurrentTabId(),
|
|
799
|
-
tab_count: getTabCount()
|
|
800
|
-
};
|
|
801
|
-
request(
|
|
802
|
-
`/v1/insights/event/welcome`,
|
|
803
|
-
welcomeInput
|
|
804
|
-
).then((data) => {
|
|
805
|
-
if (is_identified) {
|
|
806
|
-
_pendingIdentify = false;
|
|
807
|
-
return;
|
|
808
|
-
}
|
|
809
|
-
is_identified = true;
|
|
810
|
-
_pendingIdentify = false;
|
|
811
|
-
if (data?.content?.data?.session) {
|
|
812
|
-
_session = data?.content.data.session;
|
|
813
|
-
}
|
|
814
|
-
if (data?.content?.data?.device) {
|
|
815
|
-
_device = data?.content.data.device;
|
|
512
|
+
a.fetch.url(w, !0).url("/v1/insights/event/welcome").options({
|
|
513
|
+
keepAlive: !0,
|
|
514
|
+
credentials: s === "proxy" ? "include" : "omit"
|
|
515
|
+
}).headers(d).post(L).json().then((g) => {
|
|
516
|
+
if (!e()) return;
|
|
517
|
+
const { isIdentified: b } = C();
|
|
518
|
+
if (!b) {
|
|
519
|
+
const v = { isIdentified: !0 };
|
|
520
|
+
if (g?.content?.data?.session && (v.sessionId = g?.content?.data?.session), g?.content?.data?.device && (v.deviceId = g?.content?.data?.device), s === "direct" && g?.content?.meta) {
|
|
521
|
+
const k = g.content.meta;
|
|
522
|
+
k.device_token && (v.deviceToken = k.device_token), k.session_token && (v.sessionToken = k.session_token);
|
|
816
523
|
}
|
|
817
|
-
|
|
818
|
-
const meta = data.content.meta;
|
|
819
|
-
if (meta.device_token) {
|
|
820
|
-
setInStorage(storage_keys.device_token, meta.device_token);
|
|
821
|
-
}
|
|
822
|
-
if (meta.session_token) {
|
|
823
|
-
setInStorage(storage_keys.session_token, meta.session_token);
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
broadcastSession();
|
|
827
|
-
}).catch((e) => {
|
|
828
|
-
_pendingIdentify = false;
|
|
829
|
-
return getLevoError(e);
|
|
830
|
-
});
|
|
831
|
-
}
|
|
832
|
-
};
|
|
833
|
-
instance = Analytics({
|
|
834
|
-
app: workspace || "",
|
|
835
|
-
plugins: [plugin]
|
|
836
|
-
});
|
|
837
|
-
await identify();
|
|
838
|
-
startActivityListener();
|
|
839
|
-
return instance.page({
|
|
840
|
-
resource: "page",
|
|
841
|
-
identifier: properties.id
|
|
842
|
-
});
|
|
843
|
-
};
|
|
844
|
-
const startActivityListener = () => {
|
|
845
|
-
if (typeof document !== "undefined" && !idle_listener) {
|
|
846
|
-
idle_listener = onUserActivity({
|
|
847
|
-
timeout: _IDLE_TIMEOUT,
|
|
848
|
-
throttle: _IDLE_THROTTLE,
|
|
849
|
-
onIdle: (activeForSeconds) => {
|
|
850
|
-
track("user.idle", {
|
|
851
|
-
seconds_active: activeForSeconds
|
|
852
|
-
});
|
|
853
|
-
},
|
|
854
|
-
onWakeUp: (idleForSeconds) => {
|
|
855
|
-
track("user.active", {
|
|
856
|
-
seconds_idle: idleForSeconds
|
|
857
|
-
});
|
|
524
|
+
T(v);
|
|
858
525
|
}
|
|
526
|
+
}).catch((g) => {
|
|
527
|
+
console.log("/welcome failed with error", E(g));
|
|
528
|
+
}).finally(() => {
|
|
529
|
+
T({ isIdentifying: !1 });
|
|
859
530
|
});
|
|
860
531
|
}
|
|
861
|
-
return null;
|
|
862
532
|
};
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
533
|
+
return ae({
|
|
534
|
+
app: a.workspace || "",
|
|
535
|
+
debug: !!t,
|
|
536
|
+
plugins: [n]
|
|
537
|
+
});
|
|
538
|
+
};
|
|
539
|
+
let m = null, _ = !1;
|
|
540
|
+
const x = [], Ie = (a, i) => {
|
|
541
|
+
const { insightsUrl: e, debug: t = !1, site: n = null } = i;
|
|
542
|
+
K({
|
|
543
|
+
workspace: a.workspace,
|
|
544
|
+
debug: t,
|
|
545
|
+
site_id: n
|
|
546
|
+
}), typeof window < "u" && Promise.all([ke(), we()]).then(([o, l]) => {
|
|
547
|
+
const h = l?.type ? {
|
|
548
|
+
type: l.type,
|
|
549
|
+
referrer: l.referrer,
|
|
550
|
+
data: l.data,
|
|
551
|
+
raw: l.raw ?? ""
|
|
552
|
+
} : null;
|
|
553
|
+
T({
|
|
554
|
+
identity: {
|
|
555
|
+
locale: o.locale,
|
|
556
|
+
timezone: o.timezone,
|
|
557
|
+
darkMode: o.dark_mode,
|
|
558
|
+
privateMode: o.private_mode,
|
|
559
|
+
referrer: h,
|
|
560
|
+
properties: o.properties
|
|
870
561
|
}
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
562
|
+
});
|
|
563
|
+
}).catch(() => {
|
|
564
|
+
T({
|
|
565
|
+
identity: {
|
|
566
|
+
locale: null,
|
|
567
|
+
timezone: null,
|
|
568
|
+
darkMode: null,
|
|
569
|
+
privateMode: null,
|
|
570
|
+
referrer: null,
|
|
571
|
+
properties: null
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
});
|
|
575
|
+
const c = async (o, l) => {
|
|
576
|
+
if (typeof window > "u")
|
|
876
577
|
return;
|
|
877
|
-
}
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
}
|
|
881
|
-
const collectInput = {
|
|
882
|
-
event,
|
|
883
|
-
version: properties?.version || 1,
|
|
578
|
+
const { page_id: h } = P(), { allTabs: y } = C(), w = z(), p = y.length, I = {
|
|
579
|
+
event: o,
|
|
580
|
+
version: l?.version || 1,
|
|
884
581
|
properties: {
|
|
885
|
-
...
|
|
582
|
+
...l,
|
|
886
583
|
version: void 0,
|
|
887
584
|
resource: void 0,
|
|
888
585
|
identifier: void 0,
|
|
@@ -894,48 +591,74 @@ var createLevoInsights = (client, options = {}) => {
|
|
|
894
591
|
},
|
|
895
592
|
hostname: window.location.hostname,
|
|
896
593
|
pathname: window.location.pathname,
|
|
897
|
-
url: window.location.href,
|
|
898
|
-
page_title: document.title,
|
|
899
|
-
resource:
|
|
900
|
-
identifier:
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
tab_id: getCurrentTabId(),
|
|
905
|
-
tab_count: getTabCount()
|
|
594
|
+
url: l?.url ?? window.location.href,
|
|
595
|
+
page_title: l?.page_title ?? document.title,
|
|
596
|
+
resource: l?.resource ?? "page",
|
|
597
|
+
identifier: l?.id ?? h ?? void 0,
|
|
598
|
+
created_at: l?.created_at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
599
|
+
tab_id: w ?? "",
|
|
600
|
+
tab_count: p
|
|
906
601
|
};
|
|
907
|
-
|
|
908
|
-
}
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
602
|
+
W(I);
|
|
603
|
+
}, r = (o) => {
|
|
604
|
+
!m || !_ || m.identify("", { withLock: !0 });
|
|
605
|
+
}, f = (o) => {
|
|
606
|
+
const { page_id: l } = P();
|
|
607
|
+
l !== o && j("page_id", o);
|
|
913
608
|
};
|
|
914
609
|
return {
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
610
|
+
init: (o = {}) => {
|
|
611
|
+
if (typeof window > "u")
|
|
612
|
+
throw new Error("[@levo-so/insights] init() should only be called on the client side.");
|
|
613
|
+
const { pageId: l } = o;
|
|
614
|
+
if (l && f(l), !_ && !(a.NODE_ENV === "development" && !t)) {
|
|
615
|
+
if (!e) {
|
|
616
|
+
console.error(
|
|
617
|
+
"[@levo-so/insights] The utility could not be initialized due to missing insights endpoint."
|
|
618
|
+
);
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
_ = !0, Q(() => {
|
|
622
|
+
if (!_) return;
|
|
623
|
+
const { insightsBaseUrl: h } = C();
|
|
624
|
+
h || he(i).then(({ mode: w, url: p }) => {
|
|
625
|
+
_ && p && T({ mode: w, insightsBaseUrl: p });
|
|
626
|
+
}).catch(() => {
|
|
627
|
+
e && T({ mode: "proxy", insightsBaseUrl: e });
|
|
628
|
+
});
|
|
629
|
+
const y = Z.subscribe((w) => {
|
|
630
|
+
if (!(!w || !_) && !m) {
|
|
631
|
+
const p = be(a, c, () => m === p);
|
|
632
|
+
m = p, C().insightsBaseUrl && m && (x.push(
|
|
633
|
+
J(),
|
|
634
|
+
V(m),
|
|
635
|
+
ee(m),
|
|
636
|
+
fe(m),
|
|
637
|
+
pe(m),
|
|
638
|
+
te(),
|
|
639
|
+
ge(m),
|
|
640
|
+
me(m),
|
|
641
|
+
ne(m),
|
|
642
|
+
re(m)
|
|
643
|
+
), r(), m.page({ resource: "page" }));
|
|
644
|
+
}
|
|
645
|
+
});
|
|
646
|
+
x.push(y);
|
|
647
|
+
});
|
|
648
|
+
}
|
|
921
649
|
},
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
650
|
+
destroy: () => {
|
|
651
|
+
_ && (N(X()), Y(), x.forEach((o) => {
|
|
652
|
+
o();
|
|
653
|
+
}), x.length = 0, m = null, _ = !1);
|
|
925
654
|
},
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
/** Identify/establish session */
|
|
931
|
-
identify,
|
|
932
|
-
/** Track a custom event */
|
|
933
|
-
track,
|
|
934
|
-
/** Track a bounce event */
|
|
935
|
-
bounce,
|
|
936
|
-
/** Cleanup the module */
|
|
937
|
-
destroy
|
|
655
|
+
track: c,
|
|
656
|
+
get instance() {
|
|
657
|
+
return m;
|
|
658
|
+
}
|
|
938
659
|
};
|
|
939
660
|
};
|
|
940
|
-
|
|
941
|
-
|
|
661
|
+
export {
|
|
662
|
+
xe as AnalyticsEvents,
|
|
663
|
+
Ie as createLevoInsights
|
|
664
|
+
};
|