Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: LCP attribution can include resourceLoadDelay attribution timings far greater than the LCP value in cases where onTTFB discards the navigation data #439

Closed
vanderhoop opened this issue Mar 5, 2024 · 1 comment · Fixed by #440

Comments

@vanderhoop
Copy link
Contributor

vanderhoop commented Mar 5, 2024

Expected behavior: the LCP attribution's resourceLoadDelay does not exceed the reported LCP value.

Actual behavior: the resourceLoadDelay can currently exceed the reported LCP value in cases where onTTFB would discard the navigation data as untrustworthy.


Example data from a real page view:

const reported = {
  lcp: 2000,
  lcpAttributionResourceLoadDelay: 17653.7,
  // note the discrepancy between onTTFB and lcpAttributionTTFB
  onTTFB: null,
  lcpAttributionTTFB: 3300.3,
  // FWIW, the resource below has a `Timing-Allow-Origin: *` header
  lcpAttributionResourceUrl: "https://lh3.googleusercontent.com/qE-ZWFf6Q8GMIXN8_dCUU118GmoS43Uc8qW4GKTU64PyuLgqnj5QBpSH14W7UJH3OgXqo-5q_MwG5VWOBSdR_yE=h800-c",
  lcpAttributionResourceLoadTime: 0,
  lcpAttributionCallbackPerformanceNowTimestampForDebugging: 2000,
}

Suspicion:

At the moment, onTTFB issues an early return of undefined in a handful of cases:

web-vitals/src/onTTFB.ts

Lines 80 to 86 in 8058a00

// In some cases no value is reported by the browser (for
// privacy/security reasons), and in other cases (bugs) the value is
// negative or is larger than the current page time. Ignore these cases:
// https://github.com/GoogleChrome/web-vitals/issues/137
// https://github.com/GoogleChrome/web-vitals/issues/162
// https://github.com/GoogleChrome/web-vitals/issues/275
if (responseStart <= 0 || responseStart > performance.now()) return;

However, the resourceLoadDelay relies on navigation (TTFB) data without the protections issued above:

resourceLoadDelay: lcpRequestStart - ttfb,

It should be noted that the calculation of resourceLoadDelay can end up relying on the navigation entry for both sides of the subtraction seen above due to the derivation of lcpRequestStart

const lcpRequestStart = Math.max(
ttfb,
// Prefer `requestStart` (if TOA is set), otherwise use `startTime`.
lcpResourceEntry
? (lcpResourceEntry.requestStart || lcpResourceEntry.startTime) -
activationStart
: 0,
);

Where activationStart is

const activationStart = navigationEntry.activationStart || 0;

Some initial options that spring to mind:

  1. Apply the guard clause seen in onTTFB within onLCP attribution such that it discards all LCP data as untrustworthy in these cases
  2. Apply the guard clause seen in onTTFB within onLCP attribution such that only the TTFB-dependent attribution fields are either a) discarded or b) clamped somehow
@tunetheweb
Copy link
Member

Nice details (though a replication would of course be better).

Should be fixed in #440

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants