You may already be familiar with the Time To Interactive (TTI) metric, which corresponds to how long it takes a page to be ready to respond to user input. But there is another metric to measure how responsive your page actually is when real users try to interact with it.
[Introduced by Google earlier this year] (https://developers.google.com/web/updates/2018/05/first-input-delay), this metric is called First Input Delay (FID). What exactly is this metric, how does it differ from TTI, how might you go about tracking it, and how can you improve it? These are all questions we’ll look at in this post.
Difference between FID and TTI
So what’s the difference between FID and TTI? Although they are both related to the interactivity of a page, there’s one huge difference:
-
TTI can be calculated without users. It measures how long it takes your page to be ready for interaction. It’s based on how long the main JavaScript thread is tied up, and how soon it would have the capacity to deal with user interaction.
-
FID requires users to be calculated. It measures the actual amount of delay real users experience when trying to interact with your page. It’s not just when the page could respond to a user’s input, but a measurement of what actually happens when someone interacts with the page—say by clicking or touching a button.
One other thing to note is these two metrics may not always be directly correlated. If your users take their time in trying to interact with the page, you may see some low FID numbers in spite of a high TTI. Or you could have a lower TTI, but still experience higher FID numbers if your users try to interact with the page before it’s ready.
Measuring FID
Gathering the data
So how do you track FID on a given page? The concept itself is pretty simple. You add a listener for the interaction events you want to track (like click
, mousedown
, keydown
, pointerdown
, touchstart
, etc.), and then calculate how long it takes to call the handler after the beginning of the event.
function fidHandler(event) {
var now = performance.now();
var delay = now - event.timeStamp;
// Record delay...
// Remove unneeded listeners, and take care of any other cleanup
}
element.addEventListener('click', fidHandler);
How you go about adding the needed code to track these numbers is up to you.
-
If you’re already using a RUM (Real-TIme User Measurement) service, it may already be tracking this metric. For instance, [SpeedCurve started incorporating this number] (https://speedcurve.com/blog/first-input-delay/) into their reports earlier this summer.
-
Or, you could use an existing JavaScript library that is set up to track it, such as Google’s [First Input Delay] (https://github.com/GoogleChromeLabs/first-input-delay) library or [perfume.js] (https://zizzamia.github.io/perfume/#/first-input-delay/).
-
Or, you could roll your own.
Storing the data
Once you’re ready to start gathering the data, you’ll also need to figure out where you want to store it. A popular choice is to use your analytics package to store the numbers from the tracked interactions.
For instance, if you’re using Google’s First Input Delay library, you could send off the event information with something like this:
// See https://developers.google.com/web/updates/2018/05/first-input-delay
perfMetrics.onFirstInputDelay(function(delay, evt) {
ga('send', 'event', {
eventCategory: 'Perf Metrics',
eventAction: 'first-input-delay',
eventLabel: evt.type,
eventValue: Math.round(delay),
nonInteraction: true
});
});
Looking at the results
Once you start storing the FID data you want to track, it’s time to assess the numbers you see. You want them to be as small as can be, just a few milliseconds if possible.
One tip in analyzing your results is to not just look at the “average” number, but to check your FID at various percentiles. Google’s recommendation is to keep an eye on the 99th percentile:
“In fact, we recommend specifically focusing on the 99th percentile, as that will correspond to the particularly bad first experiences users are having with your site.” (source)
Looking at the experience of users on the far end of the performance distribution can expose issues that should be addressed, but which get overlooked in just looking at the “average” result.
Note: For those using Google analytics, their Reporting API, as well as their Query Explorer, provide additional tools for custom or complex reporting.
Improving FID
Once you know your FID numbers, how do you go about decreasing them? Ideally, you would be able to offload as many tasks as possible from the main JavaScript thread so that it would be free to respond to user interactions.
The best resource I’ve read on how to approach this is “Idle Until Urgent", by Philip Walton. In it, he details the pattern he uses for deferring non-critical tasks, yet still making an allowance for them to be called on-demand if the situation requires. He’s bundled up the code he uses as a package called Idlize, which is publicly available.
Regardless of whether you end up using his package or not, the article itself is well worth a read.
Real experience of real users
Although there are plenty of other performance metrics out there, FID is different than some in that it measures the actual experience of real users. High FID corresponds to real delays that people are experiencing. And these delays take place at the time we least want them to—at the very moment the user is trying to interact with the page.
Lowering FID means lowering the pain and frustration caused by unexpected delays. We may not know when the user will choose to interact with our page, but we should do what we can to make sure it’s ready whenever they decide to.
Resources
- First Input Delay – Overview of FID on the Google Developers’ site
- Idle Until Urgent – Great article by Philip Walton which details the idle-until-urgent pattern
- Idlize – Helper classes and methods for implementing the idle-until-urgent pattern