Skip to content

Commit 13c91fe

Browse files
committed
vitals redo
1 parent b8099e3 commit 13c91fe

File tree

1 file changed

+27
-80
lines changed

1 file changed

+27
-80
lines changed
Lines changed: 27 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,106 +1,53 @@
11
import { type Metric, onCLS, onFCP, onINP, onLCP, onTTFB } from "web-vitals";
22
import type { BaseTracker } from "../core/tracker";
3-
import { generateUUIDv4, logger } from "../core/utils";
3+
import { logger } from "../core/utils";
4+
5+
type WebVitalMetricName = "FCP" | "LCP" | "CLS" | "INP" | "TTFB";
6+
7+
type WebVitalSpan = {
8+
sessionId: string;
9+
timestamp: number;
10+
path: string;
11+
metricName: WebVitalMetricName;
12+
metricValue: number;
13+
};
414

515
export function initWebVitalsTracking(tracker: BaseTracker) {
616
if (tracker.isServer()) {
717
return;
818
}
919

10-
const metrics: {
11-
fcp: number | undefined;
12-
lcp: number | undefined;
13-
cls: number | undefined;
14-
inp: number | undefined;
15-
ttfb: number | undefined;
16-
} = {
17-
fcp: undefined,
18-
lcp: undefined,
19-
cls: undefined,
20-
inp: undefined,
21-
ttfb: undefined,
22-
};
20+
const sentMetrics = new Set<WebVitalMetricName>();
2321

24-
const sendVitals = () => {
25-
if (!Object.values(metrics).some((m) => m !== undefined)) {
22+
const sendVitalSpan = (metricName: WebVitalMetricName, metricValue: number) => {
23+
if (sentMetrics.has(metricName)) {
2624
return;
2725
}
26+
sentMetrics.add(metricName);
2827

29-
const clamp = (v: number | undefined) =>
30-
typeof v === "number" ? Math.min(60_000, Math.max(0, v)) : v;
31-
32-
const payload = {
33-
eventId: generateUUIDv4(),
34-
anonymousId: tracker.anonymousId,
35-
sessionId: tracker.sessionId,
28+
const span: WebVitalSpan = {
29+
sessionId: tracker.sessionId ?? "",
3630
timestamp: Date.now(),
37-
fcp: clamp(metrics.fcp),
38-
lcp: clamp(metrics.lcp),
39-
cls: clamp(metrics.cls),
40-
inp: metrics.inp,
41-
ttfb: clamp(metrics.ttfb),
42-
url: window.location.href,
31+
path: window.location.pathname,
32+
metricName,
33+
metricValue,
4334
};
4435

45-
logger.log("Sending web vitals", payload);
46-
47-
tracker.sendBeacon(payload);
36+
logger.log(`Sending web vital span: ${metricName}`, span);
37+
tracker.sendBeacon(span);
4838
};
4939

5040
const handleMetric = (metric: Metric) => {
51-
switch (metric.name) {
52-
case "FCP":
53-
metrics.fcp = Math.round(metric.value);
54-
break;
55-
case "LCP":
56-
metrics.lcp = Math.round(metric.value);
57-
break;
58-
case "CLS":
59-
metrics.cls = metric.value; // CLS is a score, not ms, so keep decimals if needed, but usually small
60-
break;
61-
case "INP":
62-
metrics.inp = Math.round(metric.value);
63-
break;
64-
case "TTFB":
65-
metrics.ttfb = Math.round(metric.value);
66-
break;
67-
default:
68-
break;
69-
}
70-
logger.log(`Web Vitals Metric: ${metric.name}`, metric.value);
41+
const name = metric.name as WebVitalMetricName;
42+
const value = name === "CLS" ? metric.value : Math.round(metric.value);
43+
44+
logger.log(`Web Vital captured: ${name}`, value);
45+
sendVitalSpan(name, value);
7146
};
7247

7348
onFCP(handleMetric);
7449
onLCP(handleMetric);
7550
onCLS(handleMetric);
7651
onINP(handleMetric);
7752
onTTFB(handleMetric);
78-
79-
setTimeout(() => {
80-
sendVitals();
81-
}, 4000);
82-
83-
const report = () => {
84-
sendVitals();
85-
};
86-
87-
let reportTimeout: number | undefined;
88-
const debouncedReport = (immediate = false) => {
89-
if (reportTimeout) {
90-
window.clearTimeout(reportTimeout);
91-
}
92-
if (immediate) {
93-
report();
94-
} else {
95-
reportTimeout = window.setTimeout(report, 1000);
96-
}
97-
};
98-
99-
document.addEventListener("visibilitychange", () => {
100-
if (document.visibilityState === "hidden") {
101-
debouncedReport(true);
102-
}
103-
});
104-
105-
window.addEventListener("pagehide", () => debouncedReport(true));
10653
}

0 commit comments

Comments
 (0)