Skip to content

Commit

Permalink
Cap TTFB in attribution (#440)
Browse files Browse the repository at this point in the history
* Cap TTFB in attribution

* Refactor

* Tidy up

* Review feedback
  • Loading branch information
tunetheweb authored Mar 19, 2024
1 parent 8058a00 commit 398f331
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 10 deletions.
6 changes: 5 additions & 1 deletion src/attribution/onFCP.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import {getBFCacheRestoreTime} from '../lib/bfcache.js';
import {getLoadState} from '../lib/getLoadState.js';
import {getNavigationEntry} from '../lib/getNavigationEntry.js';
import {isInvalidTimestamp} from '../lib/isInvalidTimestamp.js';
import {onFCP as unattributedOnFCP} from '../onFCP.js';
import {
FCPMetric,
Expand All @@ -32,8 +33,11 @@ const attributeFCP = (metric: FCPMetric): void => {
const fcpEntry = metric.entries[metric.entries.length - 1];

if (navigationEntry) {
const responseStart = navigationEntry.responseStart;
if (isInvalidTimestamp(responseStart)) return;

const activationStart = navigationEntry.activationStart || 0;
const ttfb = Math.max(0, navigationEntry.responseStart - activationStart);
const ttfb = Math.max(0, responseStart - activationStart);

(metric as FCPMetricWithAttribution).attribution = {
timeToFirstByte: ttfb,
Expand Down
8 changes: 6 additions & 2 deletions src/attribution/onLCP.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import {getNavigationEntry} from '../lib/getNavigationEntry.js';
import {getSelector} from '../lib/getSelector.js';
import {isInvalidTimestamp} from '../lib/isInvalidTimestamp.js';
import {onLCP as unattributedOnLCP} from '../onLCP.js';
import {
LCPAttribution,
Expand All @@ -31,6 +32,9 @@ const attributeLCP = (metric: LCPMetric) => {
const navigationEntry = getNavigationEntry();

if (navigationEntry) {
const responseStart = navigationEntry.responseStart;
if (isInvalidTimestamp(responseStart)) return;

const activationStart = navigationEntry.activationStart || 0;
const lcpEntry = metric.entries[metric.entries.length - 1];
const lcpResourceEntry =
Expand All @@ -39,7 +43,7 @@ const attributeLCP = (metric: LCPMetric) => {
.getEntriesByType('resource')
.filter((e) => e.name === lcpEntry.url)[0];

const ttfb = Math.max(0, navigationEntry.responseStart - activationStart);
const ttfb = Math.max(0, responseStart - activationStart);

const lcpRequestStart = Math.max(
ttfb,
Expand All @@ -55,7 +59,7 @@ const attributeLCP = (metric: LCPMetric) => {
);
const lcpRenderTime = Math.max(
lcpResponseEnd,
lcpEntry ? lcpEntry.startTime - activationStart : 0,
lcpEntry.startTime - activationStart,
);

const attribution: LCPAttribution = {
Expand Down
25 changes: 25 additions & 0 deletions src/lib/isInvalidTimestamp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

export const isInvalidTimestamp = (timestamp: DOMHighResTimeStamp) => {
// 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
return timestamp <= 0 || timestamp > performance.now();
};
9 changes: 2 additions & 7 deletions src/onTTFB.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import {bindReporter} from './lib/bindReporter.js';
import {initMetric} from './lib/initMetric.js';
import {isInvalidTimestamp} from './lib/isInvalidTimestamp.js';
import {onBFCacheRestore} from './lib/bfcache.js';
import {getNavigationEntry} from './lib/getNavigationEntry.js';
import {
Expand Down Expand Up @@ -77,13 +78,7 @@ export const onTTFB = (onReport: TTFBReportCallback, opts?: ReportOpts) => {
if (navEntry) {
const responseStart = navEntry.responseStart;

// 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;
if (isInvalidTimestamp(responseStart)) return;

// The activationStart reference is used because TTFB should be
// relative to page activation rather than navigation start if the
Expand Down

0 comments on commit 398f331

Please sign in to comment.