/** * Core Web Vitals per page view, measured with the browser's own * PerformanceObserver. A page view is one visible stretch of one route: it * ends when the route changes through `pushState`/`popstate` or the page is * hidden, and a page that becomes visible again starts a new one. TTFB and * LCP belong to the document load only; INP and CLS are measured within each * page view. A metric the browser cannot measure is left out, never zero, and * a page view the manifest has no route for carries no route. No report * carries the page's path, which can hold slugs and emails; `pageview` has it. */ export type WebVitalsNavigationType = "load" | "client" | "resume"; export interface PageViewVitals { route?: string; navigationType: WebVitalsNavigationType; ttfbMs?: number; lcpMs?: number; inpMs?: number; cls?: number; } export interface WebVitalsLocation { route: string | null; pathname: string; } interface LayoutShiftLike { startTime: number; value: number; hadRecentInput: boolean; } interface InteractionLike { interactionId?: number; duration: number; } export interface WebVitalsTrackerOptions { /** Read when a page view ends: whether layout shifts are being observed. */ measuresLayoutShift: () => boolean; report: (vitals: PageViewVitals) => void; interactionCount?: () => number | undefined; } /** * The page-view state machine, separate from the observers that feed it so * the metric rules can be exercised without a browser. */ export declare function createWebVitalsTracker(options: WebVitalsTrackerOptions): { startLoad(location: WebVitalsLocation, ttfbMs: number | undefined): void; /** * `replace` keeps the page view and moves it to the new route, since * redirects and URL canonicalization replace the entry the person landed * on. Any other change of path is a new page view. */ navigate(location: WebVitalsLocation, kind: "push" | "replace"): void; hidden(): void; /** Drops the current page view without reporting it. */ discard(): void; visible(location: WebVitalsLocation): void; largestContentfulPaint(startTimeMs: number): void; finalizeLargestContentfulPaint(): void; layoutShift(entry: LayoutShiftLike): void; interaction(entry: InteractionLike): void; }; export type WebVitalsTracker = ReturnType; export interface WebVitalsController { navigate(kind: "push" | "replace"): void; } /** * Starts measuring the current document. Returns null where the browser has * no PerformanceObserver, so no page view is reported as measured. */ export declare function installWebVitals(locate: () => WebVitalsLocation, report: (vitals: PageViewVitals) => void): WebVitalsController | null; export {};