From e8f254b1ceeca19d294bb44f07c3b25056d1e723 Mon Sep 17 00:00:00 2001 From: Barry Pollard Date: Tue, 5 Mar 2024 17:10:29 +0000 Subject: [PATCH] Cap TTFB in attribution --- src/attribution/onFCP.ts | 14 +++++++++++++- src/attribution/onLCP.ts | 17 +++++++++++++++-- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/attribution/onFCP.ts b/src/attribution/onFCP.ts index f2257d21..0501228d 100644 --- a/src/attribution/onFCP.ts +++ b/src/attribution/onFCP.ts @@ -31,9 +31,21 @@ const attributeFCP = (metric: FCPMetric): void => { const navigationEntry = getNavigationEntry(); const fcpEntry = metric.entries[metric.entries.length - 1]; + // Should always have an fcpEntry to be able to attribute + if (!fcpEntry) return; + if (navigationEntry) { const activationStart = navigationEntry.activationStart || 0; - const ttfb = Math.max(0, navigationEntry.responseStart - activationStart); + // Cap at 0 and ignore negative responseStart, future responseStart, + // or responseStart after LCP + const ttfb = Math.max( + 0, + navigationEntry.responseStart <= 0 || + navigationEntry.responseStart > performance.now() || + navigationEntry.responseStart - activationStart > fcpEntry.startTime + ? 0 + : navigationEntry.responseStart - activationStart, + ); (metric as FCPMetricWithAttribution).attribution = { timeToFirstByte: ttfb, diff --git a/src/attribution/onLCP.ts b/src/attribution/onLCP.ts index fcea5625..7a9ce22b 100644 --- a/src/attribution/onLCP.ts +++ b/src/attribution/onLCP.ts @@ -33,13 +33,26 @@ const attributeLCP = (metric: LCPMetric) => { if (navigationEntry) { const activationStart = navigationEntry.activationStart || 0; const lcpEntry = metric.entries[metric.entries.length - 1]; + + // Should always have an lcpEntry to be able to attribute + if (!lcpEntry) return; + const lcpResourceEntry = lcpEntry.url && performance .getEntriesByType('resource') .filter((e) => e.name === lcpEntry.url)[0]; - const ttfb = Math.max(0, navigationEntry.responseStart - activationStart); + // Cap at 0 and ignore negative responseStart, future responseStart, + // or responseStart after LCP + const ttfb = Math.max( + 0, + navigationEntry.responseStart <= 0 || + navigationEntry.responseStart > performance.now() || + navigationEntry.responseStart - activationStart > lcpEntry.startTime + ? 0 + : navigationEntry.responseStart - activationStart, + ); const lcpRequestStart = Math.max( ttfb, @@ -55,7 +68,7 @@ const attributeLCP = (metric: LCPMetric) => { ); const lcpRenderTime = Math.max( lcpResponseEnd, - lcpEntry ? lcpEntry.startTime - activationStart : 0, + lcpEntry.startTime - activationStart, ); const attribution: LCPAttribution = {