@tracelog/lib 0.2.2 → 0.4.0
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 +6 -0
- package/dist/browser/tracelog.js +59 -46
- package/dist/cjs/api.d.ts +7 -7
- package/dist/cjs/api.js +11 -7
- package/dist/cjs/app.types.d.ts +1 -1
- package/dist/cjs/handlers/scroll.handler.d.ts +1 -0
- package/dist/cjs/handlers/scroll.handler.js +25 -7
- package/dist/cjs/managers/session.manager.js +1 -1
- package/dist/cjs/types/event.types.d.ts +5 -0
- package/dist/cjs/types/window.types.d.ts +5 -0
- package/dist/esm/api.d.ts +7 -7
- package/dist/esm/api.js +11 -7
- package/dist/esm/app.types.d.ts +1 -1
- package/dist/esm/handlers/scroll.handler.d.ts +1 -0
- package/dist/esm/handlers/scroll.handler.js +25 -7
- package/dist/esm/managers/session.manager.js +1 -1
- package/dist/esm/types/event.types.d.ts +5 -0
- package/dist/esm/types/window.types.d.ts +5 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -107,6 +107,12 @@ await tracelog.init({
|
|
|
107
107
|
|
|
108
108
|
## Configuration
|
|
109
109
|
|
|
110
|
+
**Disabling TraceLog:**
|
|
111
|
+
```typescript
|
|
112
|
+
// Set this flag before initialization to disable TraceLog completely
|
|
113
|
+
window.__traceLogDisabled = true;
|
|
114
|
+
```
|
|
115
|
+
|
|
110
116
|
**Environment-based settings:**
|
|
111
117
|
- Use `samplingRate: 0.1` to reduce data volume in high-traffic applications
|
|
112
118
|
- Configure `sessionTimeout` to match your application's user session length
|
package/dist/browser/tracelog.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
var y = /* @__PURE__ */ ((r) => (r.Mobile = "mobile", r.Tablet = "tablet", r.Desktop = "desktop", r.Unknown = "unknown", r))(y || {});
|
|
2
|
-
const ee = 15 * 60 * 1e3, Ze = 1e3, et = 1e4, Ue = 250, tt = 24, Ee = 500, ve = 3, rt = 5e3, xe = 1e4, nt = 10, ye = 5, Te = 500,
|
|
2
|
+
const ee = 15 * 60 * 1e3, Ze = 1e3, et = 1e4, Ue = 250, tt = 24, Ee = 500, ve = 3, rt = 5e3, xe = 1e4, nt = 10, ye = 5, Te = 500, _e = 120, A = 1, st = 0, it = 1, z = 3e4, G = 864e5, Ie = 120, we = 8 * 1024, Ae = 10, be = 10, Y = 255, T = 1e3, K = 100, Me = 3, I = 2, at = 2e3, k = "data-tl", ot = [
|
|
3
3
|
"button",
|
|
4
4
|
"a",
|
|
5
5
|
'input[type="button"]',
|
|
@@ -75,7 +75,7 @@ const ee = 15 * 60 * 1e3, Ze = 1e3, et = 1e4, Ue = 250, tt = 24, Ee = 500, ve =
|
|
|
75
75
|
excludedUrlPaths: r.excludedUrlPaths ?? [],
|
|
76
76
|
tags: r.tags ?? [],
|
|
77
77
|
ipExcluded: r.ipExcluded ?? !1
|
|
78
|
-
}),
|
|
78
|
+
}), _ = "tl", dt = (r) => r ? `${_}:${r}:uid` : `${_}:uid`, ht = (r) => r ? `${_}:${r}:queue` : `${_}:queue`, gt = (r) => r ? `${_}:${r}:session` : `${_}:session`, ft = (r) => r ? `${_}:${r}:broadcast` : `${_}:broadcast`, Fe = {
|
|
79
79
|
LCP: 4e3,
|
|
80
80
|
FCP: 1800,
|
|
81
81
|
CLS: 0.25,
|
|
@@ -224,7 +224,7 @@ const St = () => {
|
|
|
224
224
|
const e = Math.random() * 16 | 0;
|
|
225
225
|
return (r === "x" ? e : e & 3 | 8).toString(16);
|
|
226
226
|
});
|
|
227
|
-
var w = /* @__PURE__ */ ((r) => (r.Skip = "skip", r.Localhost = "localhost:", r))(w || {}), re = /* @__PURE__ */ ((r) => (r.EVENT = "event", r.QUEUE = "queue", r))(re || {}), d = /* @__PURE__ */ ((r) => (r.PAGE_VIEW = "page_view", r.CLICK = "click", r.SCROLL = "scroll", r.SESSION_START = "session_start", r.SESSION_END = "session_end", r.CUSTOM = "custom", r.WEB_VITALS = "web_vitals", r.ERROR = "error", r))(d || {}), x = /* @__PURE__ */ ((r) => (r.UP = "up", r.DOWN = "down", r))(x || {}), N = /* @__PURE__ */ ((r) => (r.JS_ERROR = "js_error", r.PROMISE_REJECTION = "promise_rejection", r.NETWORK_ERROR = "network_error", r))(N || {}), H = /* @__PURE__ */ ((r) => (r.QA = "qa", r.DEBUG = "debug", r))(H || {}), yt = /* @__PURE__ */ ((r) => (r.AND = "AND", r.OR = "OR", r))(yt || {}), Tt = /* @__PURE__ */ ((r) => (r.URL_MATCHES = "url_matches", r.ELEMENT_MATCHES = "element_matches", r.DEVICE_TYPE = "device_type", r.ELEMENT_TEXT = "element_text", r.ELEMENT_ATTRIBUTE = "element_attribute", r.UTM_SOURCE = "utm_source", r.UTM_MEDIUM = "utm_medium", r.UTM_CAMPAIGN = "utm_campaign", r))(Tt || {}),
|
|
227
|
+
var w = /* @__PURE__ */ ((r) => (r.Skip = "skip", r.Localhost = "localhost:", r))(w || {}), re = /* @__PURE__ */ ((r) => (r.EVENT = "event", r.QUEUE = "queue", r))(re || {}), d = /* @__PURE__ */ ((r) => (r.PAGE_VIEW = "page_view", r.CLICK = "click", r.SCROLL = "scroll", r.SESSION_START = "session_start", r.SESSION_END = "session_end", r.CUSTOM = "custom", r.WEB_VITALS = "web_vitals", r.ERROR = "error", r))(d || {}), x = /* @__PURE__ */ ((r) => (r.UP = "up", r.DOWN = "down", r))(x || {}), N = /* @__PURE__ */ ((r) => (r.JS_ERROR = "js_error", r.PROMISE_REJECTION = "promise_rejection", r.NETWORK_ERROR = "network_error", r))(N || {}), H = /* @__PURE__ */ ((r) => (r.QA = "qa", r.DEBUG = "debug", r))(H || {}), yt = /* @__PURE__ */ ((r) => (r.AND = "AND", r.OR = "OR", r))(yt || {}), Tt = /* @__PURE__ */ ((r) => (r.URL_MATCHES = "url_matches", r.ELEMENT_MATCHES = "element_matches", r.DEVICE_TYPE = "device_type", r.ELEMENT_TEXT = "element_text", r.ELEMENT_ATTRIBUTE = "element_attribute", r.UTM_SOURCE = "utm_source", r.UTM_MEDIUM = "utm_medium", r.UTM_CAMPAIGN = "utm_campaign", r))(Tt || {}), _t = /* @__PURE__ */ ((r) => (r.EQUALS = "equals", r.CONTAINS = "contains", r.STARTS_WITH = "starts_with", r.ENDS_WITH = "ends_with", r.REGEX = "regex", r.GREATER_THAN = "greater_than", r.LESS_THAN = "less_than", r.EXISTS = "exists", r.NOT_EXISTS = "not_exists", r))(_t || {});
|
|
228
228
|
class O extends Error {
|
|
229
229
|
constructor(e, t, n) {
|
|
230
230
|
super(e), this.errorCode = t, this.layer = n, this.name = this.constructor.name, Error.captureStackTrace && Error.captureStackTrace(this, this.constructor);
|
|
@@ -240,7 +240,7 @@ class M extends O {
|
|
|
240
240
|
super(e, "APP_CONFIG_INVALID", t);
|
|
241
241
|
}
|
|
242
242
|
}
|
|
243
|
-
class
|
|
243
|
+
class It extends O {
|
|
244
244
|
constructor(e, t = "config") {
|
|
245
245
|
super(e, "SESSION_TIMEOUT_INVALID", t);
|
|
246
246
|
}
|
|
@@ -270,7 +270,7 @@ const At = (r) => {
|
|
|
270
270
|
provided: r.sessionTimeout,
|
|
271
271
|
min: z,
|
|
272
272
|
max: G
|
|
273
|
-
}), new
|
|
273
|
+
}), new It(p.INVALID_SESSION_TIMEOUT, "config");
|
|
274
274
|
if (r.globalMetadata !== void 0 && (typeof r.globalMetadata != "object" || r.globalMetadata === null))
|
|
275
275
|
throw a.clientError("ConfigValidation", "Global metadata must be an object", {
|
|
276
276
|
provided: r.globalMetadata,
|
|
@@ -545,9 +545,9 @@ const At = (r) => {
|
|
|
545
545
|
} : r.length === 0 ? {
|
|
546
546
|
valid: !1,
|
|
547
547
|
error: "Event name cannot be empty"
|
|
548
|
-
} : r.length >
|
|
548
|
+
} : r.length > Ie ? {
|
|
549
549
|
valid: !1,
|
|
550
|
-
error: `Event name is too long (max ${
|
|
550
|
+
error: `Event name is too long (max ${Ie} characters)`
|
|
551
551
|
} : r.includes("<") || r.includes(">") || r.includes("&") ? {
|
|
552
552
|
valid: !1,
|
|
553
553
|
error: "Event name contains invalid characters"
|
|
@@ -1492,7 +1492,7 @@ class Yt extends f {
|
|
|
1492
1492
|
this.visibilityChangeHandler || this.beforeUnloadHandler || (this.visibilityChangeHandler = () => {
|
|
1493
1493
|
document.hidden ? this.clearSessionTimeout() : this.get("sessionId") && this.setupSessionTimeout();
|
|
1494
1494
|
}, this.beforeUnloadHandler = () => {
|
|
1495
|
-
this.
|
|
1495
|
+
this.endSession("page_unload");
|
|
1496
1496
|
}, document.addEventListener("visibilitychange", this.visibilityChangeHandler), window.addEventListener("beforeunload", this.beforeUnloadHandler));
|
|
1497
1497
|
}
|
|
1498
1498
|
cleanupLifecycleListeners() {
|
|
@@ -1765,22 +1765,33 @@ class Jt extends f {
|
|
|
1765
1765
|
limitWarningLogged = !1;
|
|
1766
1766
|
minDepthChange = ye;
|
|
1767
1767
|
minIntervalMs = Te;
|
|
1768
|
-
maxEventsPerSession =
|
|
1768
|
+
maxEventsPerSession = _e;
|
|
1769
1769
|
constructor(e) {
|
|
1770
1770
|
super(), this.eventManager = e;
|
|
1771
1771
|
}
|
|
1772
1772
|
startTracking() {
|
|
1773
1773
|
this.limitWarningLogged = !1, this.applyConfigOverrides(), this.set("scrollEventCount", 0);
|
|
1774
|
-
const e = this.get("config").scrollContainerSelectors,
|
|
1775
|
-
|
|
1776
|
-
for (const s of n)
|
|
1777
|
-
this.setupScrollContainer(s);
|
|
1774
|
+
const e = this.get("config").scrollContainerSelectors, t = Array.isArray(e) ? e : typeof e == "string" ? [e] : [];
|
|
1775
|
+
t.length === 0 ? this.setupScrollContainer(window) : this.trySetupContainers(t, 0);
|
|
1778
1776
|
}
|
|
1779
1777
|
stopTracking() {
|
|
1780
1778
|
for (const e of this.containers)
|
|
1781
1779
|
this.clearContainerTimer(e), e.element instanceof Window ? window.removeEventListener("scroll", e.listener) : e.element.removeEventListener("scroll", e.listener);
|
|
1782
1780
|
this.containers.length = 0, this.set("scrollEventCount", 0), this.limitWarningLogged = !1;
|
|
1783
1781
|
}
|
|
1782
|
+
trySetupContainers(e, t) {
|
|
1783
|
+
const n = e.map((s) => this.safeQuerySelector(s)).filter((s) => s instanceof HTMLElement);
|
|
1784
|
+
if (n.length > 0) {
|
|
1785
|
+
for (const s of n)
|
|
1786
|
+
this.containers.some((o) => o.element === s) || this.setupScrollContainer(s);
|
|
1787
|
+
return;
|
|
1788
|
+
}
|
|
1789
|
+
if (t < 5) {
|
|
1790
|
+
setTimeout(() => this.trySetupContainers(e, t + 1), 200);
|
|
1791
|
+
return;
|
|
1792
|
+
}
|
|
1793
|
+
this.containers.length === 0 && this.setupScrollContainer(window);
|
|
1794
|
+
}
|
|
1784
1795
|
setupScrollContainer(e) {
|
|
1785
1796
|
if (e !== window && !this.isElementScrollable(e))
|
|
1786
1797
|
return;
|
|
@@ -1836,7 +1847,7 @@ class Jt extends f {
|
|
|
1836
1847
|
}));
|
|
1837
1848
|
}
|
|
1838
1849
|
applyConfigOverrides() {
|
|
1839
|
-
this.minDepthChange = ye, this.minIntervalMs = Te, this.maxEventsPerSession =
|
|
1850
|
+
this.minDepthChange = ye, this.minIntervalMs = Te, this.maxEventsPerSession = _e;
|
|
1840
1851
|
}
|
|
1841
1852
|
isWindowScrollable() {
|
|
1842
1853
|
return document.documentElement.scrollHeight > window.innerHeight;
|
|
@@ -2048,7 +2059,7 @@ class tr extends f {
|
|
|
2048
2059
|
"largest-contentful-paint",
|
|
2049
2060
|
(n) => {
|
|
2050
2061
|
const s = n.getEntries(), i = s[s.length - 1];
|
|
2051
|
-
i && this.sendVital({ type: "LCP", value: Number(i.startTime.toFixed(
|
|
2062
|
+
i && this.sendVital({ type: "LCP", value: Number(i.startTime.toFixed(I)) });
|
|
2052
2063
|
},
|
|
2053
2064
|
{ type: "largest-contentful-paint", buffered: !0 },
|
|
2054
2065
|
!0
|
|
@@ -2066,14 +2077,14 @@ class tr extends f {
|
|
|
2066
2077
|
const c = typeof o.value == "number" ? o.value : 0;
|
|
2067
2078
|
e += c;
|
|
2068
2079
|
}
|
|
2069
|
-
this.sendVital({ type: "CLS", value: Number(e.toFixed(
|
|
2080
|
+
this.sendVital({ type: "CLS", value: Number(e.toFixed(I)) });
|
|
2070
2081
|
},
|
|
2071
2082
|
{ type: "layout-shift", buffered: !0 }
|
|
2072
2083
|
), this.safeObserve(
|
|
2073
2084
|
"paint",
|
|
2074
2085
|
(n) => {
|
|
2075
2086
|
for (const s of n.getEntries())
|
|
2076
|
-
s.name === "first-contentful-paint" && this.sendVital({ type: "FCP", value: Number(s.startTime.toFixed(
|
|
2087
|
+
s.name === "first-contentful-paint" && this.sendVital({ type: "FCP", value: Number(s.startTime.toFixed(I)) });
|
|
2077
2088
|
},
|
|
2078
2089
|
{ type: "paint", buffered: !0 },
|
|
2079
2090
|
!0
|
|
@@ -2086,7 +2097,7 @@ class tr extends f {
|
|
|
2086
2097
|
const c = (o.processingEnd ?? 0) - (o.startTime ?? 0);
|
|
2087
2098
|
s = Math.max(s, c);
|
|
2088
2099
|
}
|
|
2089
|
-
s > 0 && this.sendVital({ type: "INP", value: Number(s.toFixed(
|
|
2100
|
+
s > 0 && this.sendVital({ type: "INP", value: Number(s.toFixed(I)) });
|
|
2090
2101
|
},
|
|
2091
2102
|
{ type: "event", buffered: !0 }
|
|
2092
2103
|
);
|
|
@@ -2094,7 +2105,7 @@ class tr extends f {
|
|
|
2094
2105
|
async initWebVitals() {
|
|
2095
2106
|
try {
|
|
2096
2107
|
const { onLCP: e, onCLS: t, onFCP: n, onTTFB: s, onINP: i } = await Promise.resolve().then(() => Tr), o = (c) => (l) => {
|
|
2097
|
-
const u = Number(l.value.toFixed(
|
|
2108
|
+
const u = Number(l.value.toFixed(I));
|
|
2098
2109
|
this.sendVital({ type: c, value: u });
|
|
2099
2110
|
};
|
|
2100
2111
|
e(o("LCP")), t(o("CLS")), n(o("FCP")), s(o("TTFB")), i(o("INP"));
|
|
@@ -2110,7 +2121,7 @@ class tr extends f {
|
|
|
2110
2121
|
if (!e)
|
|
2111
2122
|
return;
|
|
2112
2123
|
const t = e.responseStart;
|
|
2113
|
-
typeof t == "number" && Number.isFinite(t) && this.sendVital({ type: "TTFB", value: Number(t.toFixed(
|
|
2124
|
+
typeof t == "number" && Number.isFinite(t) && this.sendVital({ type: "TTFB", value: Number(t.toFixed(I)) });
|
|
2114
2125
|
} catch (e) {
|
|
2115
2126
|
a.warn("PerformanceHandler", "Failed to report TTFB", {
|
|
2116
2127
|
error: e instanceof Error ? e.message : "Unknown error"
|
|
@@ -2123,7 +2134,7 @@ class tr extends f {
|
|
|
2123
2134
|
(e) => {
|
|
2124
2135
|
const t = e.getEntries();
|
|
2125
2136
|
for (const n of t) {
|
|
2126
|
-
const s = Number(n.duration.toFixed(
|
|
2137
|
+
const s = Number(n.duration.toFixed(I)), i = Date.now();
|
|
2127
2138
|
i - this.lastLongTaskSentAt >= mt && (this.shouldSendVital("LONG_TASK", s) && this.trackWebVital("LONG_TASK", s), this.lastLongTaskSentAt = i);
|
|
2128
2139
|
}
|
|
2129
2140
|
},
|
|
@@ -2399,30 +2410,32 @@ let g = null, C = !1, q = !1;
|
|
|
2399
2410
|
const sr = async (r) => {
|
|
2400
2411
|
if (typeof window > "u" || typeof document > "u")
|
|
2401
2412
|
throw new Error("This library can only be used in a browser environment");
|
|
2402
|
-
if (
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
a.info("API", "Initializing TraceLog", { projectId: r.id });
|
|
2411
|
-
const e = Lt(r), t = new nr();
|
|
2413
|
+
if (!window.__traceLogDisabled) {
|
|
2414
|
+
if (g) {
|
|
2415
|
+
a.debug("API", "Library already initialized, skipping duplicate initialization");
|
|
2416
|
+
return;
|
|
2417
|
+
}
|
|
2418
|
+
if (C)
|
|
2419
|
+
throw a.warn("API", "Initialization already in progress"), new Error("Initialization already in progress");
|
|
2420
|
+
C = !0;
|
|
2412
2421
|
try {
|
|
2413
|
-
|
|
2414
|
-
|
|
2422
|
+
a.info("API", "Initializing TraceLog", { projectId: r.id });
|
|
2423
|
+
const e = Lt(r), t = new nr();
|
|
2415
2424
|
try {
|
|
2416
|
-
await t.
|
|
2417
|
-
} catch (
|
|
2418
|
-
|
|
2425
|
+
await t.init(e), g = t, a.info("API", "TraceLog initialized successfully", { projectId: e.id });
|
|
2426
|
+
} catch (n) {
|
|
2427
|
+
try {
|
|
2428
|
+
await t.destroy(!0);
|
|
2429
|
+
} catch (s) {
|
|
2430
|
+
a.warn("API", "Failed to cleanup partially initialized app", { cleanupError: s });
|
|
2431
|
+
}
|
|
2432
|
+
throw n;
|
|
2419
2433
|
}
|
|
2420
|
-
|
|
2434
|
+
} catch (e) {
|
|
2435
|
+
throw g = null, a.error("API", "Initialization failed", { error: e }), e;
|
|
2436
|
+
} finally {
|
|
2437
|
+
C = !1;
|
|
2421
2438
|
}
|
|
2422
|
-
} catch (e) {
|
|
2423
|
-
throw g = null, a.error("API", "Initialization failed", { error: e }), e;
|
|
2424
|
-
} finally {
|
|
2425
|
-
C = !1;
|
|
2426
2439
|
}
|
|
2427
2440
|
}, ir = (r, e) => {
|
|
2428
2441
|
if (!g)
|
|
@@ -2453,10 +2466,10 @@ const sr = async (r) => {
|
|
|
2453
2466
|
} finally {
|
|
2454
2467
|
q = !1;
|
|
2455
2468
|
}
|
|
2456
|
-
},
|
|
2469
|
+
}, _r = {
|
|
2457
2470
|
WEB_VITALS_THRESHOLDS: Fe
|
|
2458
2471
|
// Business thresholds for performance analysis
|
|
2459
|
-
},
|
|
2472
|
+
}, Ir = {
|
|
2460
2473
|
PII_PATTERNS: ze
|
|
2461
2474
|
// Patterns for sensitive data protection
|
|
2462
2475
|
}, wr = {
|
|
@@ -2741,7 +2754,7 @@ export {
|
|
|
2741
2754
|
Cr as ANALYTICS_QUERY_LIMITS,
|
|
2742
2755
|
Pr as ANOMALY_DETECTION,
|
|
2743
2756
|
Mr as CONTENT_ANALYTICS,
|
|
2744
|
-
|
|
2757
|
+
Ir as DATA_PROTECTION,
|
|
2745
2758
|
br as DEVICE_ANALYTICS,
|
|
2746
2759
|
y as DeviceType,
|
|
2747
2760
|
wr as ENGAGEMENT_THRESHOLDS,
|
|
@@ -2749,13 +2762,13 @@ export {
|
|
|
2749
2762
|
d as EventType,
|
|
2750
2763
|
Rr as INSIGHT_THRESHOLDS,
|
|
2751
2764
|
H as Mode,
|
|
2752
|
-
|
|
2765
|
+
_r as PERFORMANCE_CONFIG,
|
|
2753
2766
|
Nr as SEGMENTATION_ANALYTICS,
|
|
2754
2767
|
Ar as SESSION_ANALYTICS,
|
|
2755
2768
|
Or as SPECIAL_PAGE_URLS,
|
|
2756
2769
|
x as ScrollDirection,
|
|
2757
2770
|
Lr as TEMPORAL_ANALYSIS,
|
|
2758
|
-
|
|
2771
|
+
_t as TagConditionOperator,
|
|
2759
2772
|
Tt as TagConditionType,
|
|
2760
2773
|
yt as TagLogicalOperator,
|
|
2761
2774
|
Dr as tracelog
|
package/dist/cjs/api.d.ts
CHANGED
|
@@ -28,14 +28,14 @@ export declare const event: (name: string, metadata?: Record<string, MetadataTyp
|
|
|
28
28
|
* @param event - Event name to listen to
|
|
29
29
|
* @param callback - Function to call when event is emitted
|
|
30
30
|
* @example
|
|
31
|
-
* // Listen for
|
|
32
|
-
* tracelog.on('
|
|
33
|
-
* console.log('Event tracked:', data.type
|
|
31
|
+
* // Listen for tracked events
|
|
32
|
+
* tracelog.on('event', (data) => {
|
|
33
|
+
* console.log('Event tracked:', data.type);
|
|
34
34
|
* });
|
|
35
35
|
*
|
|
36
|
-
* // Listen for sent
|
|
37
|
-
* tracelog.on('
|
|
38
|
-
* console.log('Events sent:', data.
|
|
36
|
+
* // Listen for event queues being sent
|
|
37
|
+
* tracelog.on('queue', (data) => {
|
|
38
|
+
* console.log('Events sent:', data.events.length);
|
|
39
39
|
* });
|
|
40
40
|
*/
|
|
41
41
|
export declare const on: <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>) => void;
|
|
@@ -45,7 +45,7 @@ export declare const on: <K extends keyof EmitterMap>(event: K, callback: Emitte
|
|
|
45
45
|
* @param callback - The same function reference that was used in on()
|
|
46
46
|
* @example
|
|
47
47
|
* // Remove a specific listener
|
|
48
|
-
* tracelog.off('
|
|
48
|
+
* tracelog.off('event', myCallback);
|
|
49
49
|
*/
|
|
50
50
|
export declare const off: <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>) => void;
|
|
51
51
|
/**
|
package/dist/cjs/api.js
CHANGED
|
@@ -21,6 +21,10 @@ const init = async (appConfig) => {
|
|
|
21
21
|
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
|
22
22
|
throw new Error('This library can only be used in a browser environment');
|
|
23
23
|
}
|
|
24
|
+
// Check if TraceLog is disabled
|
|
25
|
+
if (window.__traceLogDisabled) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
24
28
|
// Already initialized - safe to return
|
|
25
29
|
if (app) {
|
|
26
30
|
utils_1.debugLog.debug('API', 'Library already initialized, skipping duplicate initialization');
|
|
@@ -92,14 +96,14 @@ exports.event = event;
|
|
|
92
96
|
* @param event - Event name to listen to
|
|
93
97
|
* @param callback - Function to call when event is emitted
|
|
94
98
|
* @example
|
|
95
|
-
* // Listen for
|
|
96
|
-
* tracelog.on('
|
|
97
|
-
* console.log('Event tracked:', data.type
|
|
99
|
+
* // Listen for tracked events
|
|
100
|
+
* tracelog.on('event', (data) => {
|
|
101
|
+
* console.log('Event tracked:', data.type);
|
|
98
102
|
* });
|
|
99
103
|
*
|
|
100
|
-
* // Listen for sent
|
|
101
|
-
* tracelog.on('
|
|
102
|
-
* console.log('Events sent:', data.
|
|
104
|
+
* // Listen for event queues being sent
|
|
105
|
+
* tracelog.on('queue', (data) => {
|
|
106
|
+
* console.log('Events sent:', data.events.length);
|
|
103
107
|
* });
|
|
104
108
|
*/
|
|
105
109
|
const on = (event, callback) => {
|
|
@@ -115,7 +119,7 @@ exports.on = on;
|
|
|
115
119
|
* @param callback - The same function reference that was used in on()
|
|
116
120
|
* @example
|
|
117
121
|
* // Remove a specific listener
|
|
118
|
-
* tracelog.off('
|
|
122
|
+
* tracelog.off('event', myCallback);
|
|
119
123
|
*/
|
|
120
124
|
const off = (event, callback) => {
|
|
121
125
|
if (!app) {
|
package/dist/cjs/app.types.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { Mode, EventType, DeviceType, ScrollDirection, ErrorType, TagConditionOperator, TagLogicalOperator, TagConditionType, } from './types';
|
|
2
|
-
export type { ScrollData, ClickData, CustomEventData, MetadataType, WebVitalsData, ErrorData, PageViewData, UTM, EventData, AppConfig, ApiConfig, ExtendedEventsQueueDto, TagConfig, BaseEventsQueueDto, WebVitalType, SessionEndReason, } from './types';
|
|
2
|
+
export type { ScrollData, ClickData, CustomEventData, MetadataType, WebVitalsData, ErrorData, PageViewData, UTM, EventLocation, EventData, AppConfig, ApiConfig, ExtendedEventsQueueDto, TagConfig, BaseEventsQueueDto, WebVitalType, SessionEndReason, } from './types';
|
|
@@ -10,6 +10,7 @@ export declare class ScrollHandler extends StateManager {
|
|
|
10
10
|
constructor(eventManager: EventManager);
|
|
11
11
|
startTracking(): void;
|
|
12
12
|
stopTracking(): void;
|
|
13
|
+
private trySetupContainers;
|
|
13
14
|
private setupScrollContainer;
|
|
14
15
|
private processScrollEvent;
|
|
15
16
|
private shouldEmitScrollEvent;
|
|
@@ -21,14 +21,11 @@ class ScrollHandler extends state_manager_1.StateManager {
|
|
|
21
21
|
this.set('scrollEventCount', 0);
|
|
22
22
|
const raw = this.get('config').scrollContainerSelectors;
|
|
23
23
|
const selectors = Array.isArray(raw) ? raw : typeof raw === 'string' ? [raw] : [];
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
.filter((element) => element instanceof HTMLElement);
|
|
27
|
-
if (elements.length === 0) {
|
|
28
|
-
elements.push(window);
|
|
24
|
+
if (selectors.length === 0) {
|
|
25
|
+
this.setupScrollContainer(window);
|
|
29
26
|
}
|
|
30
|
-
|
|
31
|
-
this.
|
|
27
|
+
else {
|
|
28
|
+
this.trySetupContainers(selectors, 0);
|
|
32
29
|
}
|
|
33
30
|
}
|
|
34
31
|
stopTracking() {
|
|
@@ -45,6 +42,27 @@ class ScrollHandler extends state_manager_1.StateManager {
|
|
|
45
42
|
this.set('scrollEventCount', 0);
|
|
46
43
|
this.limitWarningLogged = false;
|
|
47
44
|
}
|
|
45
|
+
trySetupContainers(selectors, attempt) {
|
|
46
|
+
const elements = selectors
|
|
47
|
+
.map((sel) => this.safeQuerySelector(sel))
|
|
48
|
+
.filter((element) => element instanceof HTMLElement);
|
|
49
|
+
if (elements.length > 0) {
|
|
50
|
+
for (const element of elements) {
|
|
51
|
+
const isAlreadyTracking = this.containers.some((c) => c.element === element);
|
|
52
|
+
if (!isAlreadyTracking) {
|
|
53
|
+
this.setupScrollContainer(element);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (attempt < 5) {
|
|
59
|
+
setTimeout(() => this.trySetupContainers(selectors, attempt + 1), 200);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (this.containers.length === 0) {
|
|
63
|
+
this.setupScrollContainer(window);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
48
66
|
setupScrollContainer(element) {
|
|
49
67
|
// Skip setup for non-scrollable elements
|
|
50
68
|
if (element !== window && !this.isElementScrollable(element)) {
|
|
@@ -250,7 +250,7 @@ class SessionManager extends state_manager_1.StateManager {
|
|
|
250
250
|
}
|
|
251
251
|
};
|
|
252
252
|
this.beforeUnloadHandler = () => {
|
|
253
|
-
this.
|
|
253
|
+
this.endSession('page_unload');
|
|
254
254
|
};
|
|
255
255
|
// Handle tab visibility changes
|
|
256
256
|
document.addEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
@@ -75,6 +75,10 @@ export interface PageViewData {
|
|
|
75
75
|
search?: string;
|
|
76
76
|
hash?: string;
|
|
77
77
|
}
|
|
78
|
+
export interface EventLocation {
|
|
79
|
+
country: string;
|
|
80
|
+
country_code: string;
|
|
81
|
+
}
|
|
78
82
|
export interface VitalSample {
|
|
79
83
|
type: WebVitalType;
|
|
80
84
|
value: number;
|
|
@@ -94,6 +98,7 @@ export interface EventData {
|
|
|
94
98
|
session_end_reason?: SessionEndReason;
|
|
95
99
|
error_data?: ErrorData;
|
|
96
100
|
utm?: UTM;
|
|
101
|
+
location?: EventLocation;
|
|
97
102
|
tags?: string[] | {
|
|
98
103
|
id: string;
|
|
99
104
|
key: string;
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { TraceLogTestBridge } from './test-bridge.types';
|
|
2
2
|
declare global {
|
|
3
3
|
interface Window {
|
|
4
|
+
/**
|
|
5
|
+
* Flag to disable TraceLog initialization
|
|
6
|
+
* Set to true to prevent the library from running
|
|
7
|
+
*/
|
|
8
|
+
__traceLogDisabled?: boolean;
|
|
4
9
|
/**
|
|
5
10
|
* Testing bridge for E2E tests
|
|
6
11
|
* Only available when NODE_ENV=dev
|
package/dist/esm/api.d.ts
CHANGED
|
@@ -28,14 +28,14 @@ export declare const event: (name: string, metadata?: Record<string, MetadataTyp
|
|
|
28
28
|
* @param event - Event name to listen to
|
|
29
29
|
* @param callback - Function to call when event is emitted
|
|
30
30
|
* @example
|
|
31
|
-
* // Listen for
|
|
32
|
-
* tracelog.on('
|
|
33
|
-
* console.log('Event tracked:', data.type
|
|
31
|
+
* // Listen for tracked events
|
|
32
|
+
* tracelog.on('event', (data) => {
|
|
33
|
+
* console.log('Event tracked:', data.type);
|
|
34
34
|
* });
|
|
35
35
|
*
|
|
36
|
-
* // Listen for sent
|
|
37
|
-
* tracelog.on('
|
|
38
|
-
* console.log('Events sent:', data.
|
|
36
|
+
* // Listen for event queues being sent
|
|
37
|
+
* tracelog.on('queue', (data) => {
|
|
38
|
+
* console.log('Events sent:', data.events.length);
|
|
39
39
|
* });
|
|
40
40
|
*/
|
|
41
41
|
export declare const on: <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>) => void;
|
|
@@ -45,7 +45,7 @@ export declare const on: <K extends keyof EmitterMap>(event: K, callback: Emitte
|
|
|
45
45
|
* @param callback - The same function reference that was used in on()
|
|
46
46
|
* @example
|
|
47
47
|
* // Remove a specific listener
|
|
48
|
-
* tracelog.off('
|
|
48
|
+
* tracelog.off('event', myCallback);
|
|
49
49
|
*/
|
|
50
50
|
export declare const off: <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>) => void;
|
|
51
51
|
/**
|
package/dist/esm/api.js
CHANGED
|
@@ -18,6 +18,10 @@ export const init = async (appConfig) => {
|
|
|
18
18
|
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
|
19
19
|
throw new Error('This library can only be used in a browser environment');
|
|
20
20
|
}
|
|
21
|
+
// Check if TraceLog is disabled
|
|
22
|
+
if (window.__traceLogDisabled) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
21
25
|
// Already initialized - safe to return
|
|
22
26
|
if (app) {
|
|
23
27
|
debugLog.debug('API', 'Library already initialized, skipping duplicate initialization');
|
|
@@ -87,14 +91,14 @@ export const event = (name, metadata) => {
|
|
|
87
91
|
* @param event - Event name to listen to
|
|
88
92
|
* @param callback - Function to call when event is emitted
|
|
89
93
|
* @example
|
|
90
|
-
* // Listen for
|
|
91
|
-
* tracelog.on('
|
|
92
|
-
* console.log('Event tracked:', data.type
|
|
94
|
+
* // Listen for tracked events
|
|
95
|
+
* tracelog.on('event', (data) => {
|
|
96
|
+
* console.log('Event tracked:', data.type);
|
|
93
97
|
* });
|
|
94
98
|
*
|
|
95
|
-
* // Listen for sent
|
|
96
|
-
* tracelog.on('
|
|
97
|
-
* console.log('Events sent:', data.
|
|
99
|
+
* // Listen for event queues being sent
|
|
100
|
+
* tracelog.on('queue', (data) => {
|
|
101
|
+
* console.log('Events sent:', data.events.length);
|
|
98
102
|
* });
|
|
99
103
|
*/
|
|
100
104
|
export const on = (event, callback) => {
|
|
@@ -109,7 +113,7 @@ export const on = (event, callback) => {
|
|
|
109
113
|
* @param callback - The same function reference that was used in on()
|
|
110
114
|
* @example
|
|
111
115
|
* // Remove a specific listener
|
|
112
|
-
* tracelog.off('
|
|
116
|
+
* tracelog.off('event', myCallback);
|
|
113
117
|
*/
|
|
114
118
|
export const off = (event, callback) => {
|
|
115
119
|
if (!app) {
|
package/dist/esm/app.types.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { Mode, EventType, DeviceType, ScrollDirection, ErrorType, TagConditionOperator, TagLogicalOperator, TagConditionType, } from './types';
|
|
2
|
-
export type { ScrollData, ClickData, CustomEventData, MetadataType, WebVitalsData, ErrorData, PageViewData, UTM, EventData, AppConfig, ApiConfig, ExtendedEventsQueueDto, TagConfig, BaseEventsQueueDto, WebVitalType, SessionEndReason, } from './types';
|
|
2
|
+
export type { ScrollData, ClickData, CustomEventData, MetadataType, WebVitalsData, ErrorData, PageViewData, UTM, EventLocation, EventData, AppConfig, ApiConfig, ExtendedEventsQueueDto, TagConfig, BaseEventsQueueDto, WebVitalType, SessionEndReason, } from './types';
|
|
@@ -10,6 +10,7 @@ export declare class ScrollHandler extends StateManager {
|
|
|
10
10
|
constructor(eventManager: EventManager);
|
|
11
11
|
startTracking(): void;
|
|
12
12
|
stopTracking(): void;
|
|
13
|
+
private trySetupContainers;
|
|
13
14
|
private setupScrollContainer;
|
|
14
15
|
private processScrollEvent;
|
|
15
16
|
private shouldEmitScrollEvent;
|
|
@@ -18,14 +18,11 @@ export class ScrollHandler extends StateManager {
|
|
|
18
18
|
this.set('scrollEventCount', 0);
|
|
19
19
|
const raw = this.get('config').scrollContainerSelectors;
|
|
20
20
|
const selectors = Array.isArray(raw) ? raw : typeof raw === 'string' ? [raw] : [];
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
.filter((element) => element instanceof HTMLElement);
|
|
24
|
-
if (elements.length === 0) {
|
|
25
|
-
elements.push(window);
|
|
21
|
+
if (selectors.length === 0) {
|
|
22
|
+
this.setupScrollContainer(window);
|
|
26
23
|
}
|
|
27
|
-
|
|
28
|
-
this.
|
|
24
|
+
else {
|
|
25
|
+
this.trySetupContainers(selectors, 0);
|
|
29
26
|
}
|
|
30
27
|
}
|
|
31
28
|
stopTracking() {
|
|
@@ -42,6 +39,27 @@ export class ScrollHandler extends StateManager {
|
|
|
42
39
|
this.set('scrollEventCount', 0);
|
|
43
40
|
this.limitWarningLogged = false;
|
|
44
41
|
}
|
|
42
|
+
trySetupContainers(selectors, attempt) {
|
|
43
|
+
const elements = selectors
|
|
44
|
+
.map((sel) => this.safeQuerySelector(sel))
|
|
45
|
+
.filter((element) => element instanceof HTMLElement);
|
|
46
|
+
if (elements.length > 0) {
|
|
47
|
+
for (const element of elements) {
|
|
48
|
+
const isAlreadyTracking = this.containers.some((c) => c.element === element);
|
|
49
|
+
if (!isAlreadyTracking) {
|
|
50
|
+
this.setupScrollContainer(element);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (attempt < 5) {
|
|
56
|
+
setTimeout(() => this.trySetupContainers(selectors, attempt + 1), 200);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (this.containers.length === 0) {
|
|
60
|
+
this.setupScrollContainer(window);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
45
63
|
setupScrollContainer(element) {
|
|
46
64
|
// Skip setup for non-scrollable elements
|
|
47
65
|
if (element !== window && !this.isElementScrollable(element)) {
|
|
@@ -247,7 +247,7 @@ export class SessionManager extends StateManager {
|
|
|
247
247
|
}
|
|
248
248
|
};
|
|
249
249
|
this.beforeUnloadHandler = () => {
|
|
250
|
-
this.
|
|
250
|
+
this.endSession('page_unload');
|
|
251
251
|
};
|
|
252
252
|
// Handle tab visibility changes
|
|
253
253
|
document.addEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
@@ -75,6 +75,10 @@ export interface PageViewData {
|
|
|
75
75
|
search?: string;
|
|
76
76
|
hash?: string;
|
|
77
77
|
}
|
|
78
|
+
export interface EventLocation {
|
|
79
|
+
country: string;
|
|
80
|
+
country_code: string;
|
|
81
|
+
}
|
|
78
82
|
export interface VitalSample {
|
|
79
83
|
type: WebVitalType;
|
|
80
84
|
value: number;
|
|
@@ -94,6 +98,7 @@ export interface EventData {
|
|
|
94
98
|
session_end_reason?: SessionEndReason;
|
|
95
99
|
error_data?: ErrorData;
|
|
96
100
|
utm?: UTM;
|
|
101
|
+
location?: EventLocation;
|
|
97
102
|
tags?: string[] | {
|
|
98
103
|
id: string;
|
|
99
104
|
key: string;
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { TraceLogTestBridge } from './test-bridge.types';
|
|
2
2
|
declare global {
|
|
3
3
|
interface Window {
|
|
4
|
+
/**
|
|
5
|
+
* Flag to disable TraceLog initialization
|
|
6
|
+
* Set to true to prevent the library from running
|
|
7
|
+
*/
|
|
8
|
+
__traceLogDisabled?: boolean;
|
|
4
9
|
/**
|
|
5
10
|
* Testing bridge for E2E tests
|
|
6
11
|
* Only available when NODE_ENV=dev
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@tracelog/lib",
|
|
3
3
|
"description": "JavaScript library for web analytics and real-time event tracking",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.4.0",
|
|
6
6
|
"main": "./dist/cjs/public-api.js",
|
|
7
7
|
"module": "./dist/esm/public-api.js",
|
|
8
8
|
"types": "./dist/esm/public-api.d.ts",
|