Interactions
This script is part of the Web Vitals Chrome Extension (opens in a new tab) and allows you to track all interactions as you click around the page to help improve INP.
Snippet
const valueToRating = (score) =>
score <= 200 ? "good" : score <= 500 ? "needs-improvement" : "poor";
const COLOR_GOOD = "#0CCE6A";
const COLOR_NEEDS_IMPROVEMENT = "#FFA400";
const COLOR_POOR = "#FF4E42";
const RATING_COLORS = {
good: COLOR_GOOD,
"needs-improvement": COLOR_NEEDS_IMPROVEMENT,
poor: COLOR_POOR,
};
const observer = new PerformanceObserver((list) => {
const interactions = {};
for (const entry of list
.getEntries()
.filter((entry) => entry.interactionId)) {
interactions[entry.interactionId] = interactions[entry.interactionId] || [];
interactions[entry.interactionId].push(entry);
}
// Will report as a single interaction even if parts are in separate frames.
// Consider splitting by animation frame.
for (const interaction of Object.values(interactions)) {
const entry = interaction.reduce((prev, curr) =>
prev.duration >= curr.duration ? prev : curr,
);
const value = entry.duration;
const rating = valueToRating(value);
const formattedValue = `${value.toFixed(0)} ms`;
console.groupCollapsed(
`Interaction tracking snippet %c${formattedValue} (${rating})`,
`color: ${RATING_COLORS[rating] || "inherit"}`,
);
console.log("Interaction target:", entry.target);
for (let entry of interaction) {
console.log(
`Interaction event type: %c${entry.name}`,
"font-family: monospace",
);
// RenderTime is an estimate, because duration is rounded, and may get rounded down.
// In rare cases it can be less than processingEnd and that breaks performance.measure().
// Lets make sure its at least 4ms in those cases so you can just barely see it.
const adjustedPresentationTime = Math.max(
entry.processingEnd + 4,
entry.startTime + entry.duration,
);
console.table([
{
subPartString: "Input delay",
"Time (ms)": Math.round(entry.processingStart - entry.startTime, 0),
},
{
subPartString: "Processing time",
"Time (ms)": Math.round(
entry.processingEnd - entry.processingStart,
0,
),
},
{
subPartString: "Presentation delay",
"Time (ms)": Math.round(
adjustedPresentationTime - entry.processingEnd,
0,
),
},
]);
}
console.groupEnd();
}
});
observer.observe({
type: "event",
durationThreshold: 0, // 16 minimum by spec
buffered: true,
});