Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 8s
Build & Deploy / 🧪 QA (push) Successful in 2m25s
Build & Deploy / 🏗️ Build (push) Successful in 3m59s
Build & Deploy / 🚀 Deploy (push) Successful in 15s
Build & Deploy / 🧪 Post-Deploy Verification (push) Successful in 4m55s
Build & Deploy / 🔔 Notify (push) Successful in 2s
Nightly QA / call-qa-workflow (push) Failing after 45s
- Add WebVitalsTracker component using useReportWebVitals - Report LCP, CLS, FID, FCP, TTFB, and INP as Umami events - Include rating (good/needs-improvement/poor) for meaningful metrics
55 lines
1.8 KiB
TypeScript
55 lines
1.8 KiB
TypeScript
'use client';
|
|
|
|
import { useReportWebVitals } from 'next/web-vitals';
|
|
import { useAnalytics } from './useAnalytics';
|
|
|
|
/**
|
|
* WebVitalsTracker component.
|
|
*
|
|
* Captures Next.js Web Vitals and reports them to Umami as custom events.
|
|
* This provides "meaningful" page speed tracking by measuring real user
|
|
* experiences (LCP, CLS, INP, etc.).
|
|
*/
|
|
export default function WebVitalsTracker() {
|
|
const { trackEvent } = useAnalytics();
|
|
|
|
useReportWebVitals((metric) => {
|
|
const { name, value, id, label } = metric;
|
|
|
|
// Determine rating (simplified version of web-vitals standards)
|
|
let rating: 'good' | 'needs-improvement' | 'poor' = 'good';
|
|
|
|
if (name === 'LCP') {
|
|
if (value > 4000) rating = 'poor';
|
|
else if (value > 2500) rating = 'needs-improvement';
|
|
} else if (name === 'CLS') {
|
|
if (value > 0.25) rating = 'poor';
|
|
else if (value > 0.1) rating = 'needs-improvement';
|
|
} else if (name === 'FID') {
|
|
if (value > 300) rating = 'poor';
|
|
else if (value > 100) rating = 'needs-improvement';
|
|
} else if (name === 'FCP') {
|
|
if (value > 3000) rating = 'poor';
|
|
else if (value > 1800) rating = 'needs-improvement';
|
|
} else if (name === 'TTFB') {
|
|
if (value > 1500) rating = 'poor';
|
|
else if (value > 800) rating = 'needs-improvement';
|
|
} else if (name === 'INP') {
|
|
if (value > 500) rating = 'poor';
|
|
else if (value > 200) rating = 'needs-improvement';
|
|
}
|
|
|
|
// Report to Umami
|
|
trackEvent('web-vital', {
|
|
metric: name,
|
|
value: Math.round(name === 'CLS' ? value * 1000 : value), // CLS is a score, multiply by 1000 to keep as integer if preferred
|
|
rating,
|
|
id,
|
|
label,
|
|
path: typeof window !== 'undefined' ? window.location.pathname : undefined,
|
|
});
|
|
});
|
|
|
|
return null;
|
|
}
|