How improved INP scores @redBus pulled up sales.

Amit Kumar
redbus India Blog
Published in
8 min readMar 29, 2023
What is Interaction to next paint? INP …

The browser world is getting better and better everyday , we have a full blown web pages now which does a full set of transactions with all features which a product can plan for native apps ……

Major challenge on browser world was, when you give so much load on your JavaScript to power all features which can slow down your site and give bad user experience. Off-course you can use webpack or other tools to split chunks or dynamic loads etc but its difficult to manage and reduce unused code.

Thankfully we have full set of web vitals matrix which tells us the pain points of our sites and helps us to make it better…

There are 6 major vitals but we will constrain our discussion to one latest vitals (INP)we will talk majorly about this.

What is INP ?

What is Interaction to next paint

Web developers were struggling to fix other vitals and that is still in progress….we have this new bomb 😊 on us.

But trust me guys this is one of the very interesting vital and helps to understand user experience and bottle necks in it.

Definition by web dev:

Interaction to Next Paint (INP) is an experimental metric that assesses responsiveness. When an interaction causes a page to become unresponsive, that is a poor user experience. INP observes the latency of all interactions a user has made with the page, and reports a single value which all (or nearly all) interactions were below. A low INP means the page was consistently able to respond quickly to all – or the vast majority – of user interactions.

So basically it means that how is your webpage responding to major user interaction, if your page is not getting stuck on users interaction and performs smoothly in response to these interaction then mostly your INP is low.

To define it in one line:-

The Interaction to Next Paint measures the time taken between the user click or any event by user and the presentation of the next intractable frame on webpage.

You can think about this in terms of interaction latency. Based on this you can also categories it in two aspects.

  1. Latency caused by blocking JS at client side which can cause delay in rendering.
  2. Latency caused by a subsequent API call which is tied up to that event triggered by user and is mandatory to create next frame.

@redBus browser world I was very confident on my application that INP is pretty good and it was good also till I saw the numbers for 95th percentile of users , my confidence went a bit lower when I broke down in network categories……

As this is a very new and interesting topic at the time when I am writing this article I would like to break it down into 4 major categories:-

  1. How to identify INP ?
  2. Impact areas created by INP on system(frontend and backend)?
  3. final outcome impact to user and business.
  4. Exact redBus use-cases samples for both client side interaction latency and API based latency.

How to identify INP?

There are multiple ways to identify the INP scores in your page.. I will briefly describe few of them and then we will discuss how redBus worked on it’ INP scores.

  1. Use a JS module https://unpkg.com/web-vitals@3.1.0/dist/web-vitals.attribution.js?module” This lib is good enough to start finding your INP scores in your webpages.

Lets immediately start with a sample code:-

<script>
import { onINP, onFCP, onCLS, onFID, onLCP } from 'https://unpkg.com/web-vitals@3.1.0/dist/web-vitals.attribution.js?module';

const sendDataToLogRUM = (metrics, metricName) => {
const { attribution, id, value, rating } = metrics;
if((metricName === 'INP' && value < 40) || (metricName === 'CLS' && value < 0.1)) return;
const {eventType, eventTarget, element, largestShiftTarget } = attribution;
const stringifiedAttribution = JSON.stringify({
eventType,
eventTarget,
element,
largestShiftTarget
});
const vitalData = {
id,
value: value.toFixed(3),
rating,
attribution: stringifiedAttribution,
};
if(value > 0 && window.yourxxxxApm) {
const transaction = window.yourxxxxxxxApm.startTransaction(metricName, 'custom', { managed: true })
transaction.addLabels(vitalData);
setTimeout(() => {
transaction.end()
/**
* This would also end the managed transaction once all the blocking spans are completed and
* transaction would also contain other timing information and spans similar to auto
* instrumented transactions like `page-load` and `route-change`.
*/
}, 1000)
}
};

onFCP((metrics) => sendDataToLogRUM(metrics,'FCP'));
onFID((metrics) => sendDataToLogRUM(metrics,'FID'));
onLCP((metrics) => sendDataToLogRUM(metrics,'LCP'));
onCLS((metrics) => sendDataToLogRUM(metrics,'CLS'),{reportAllChanges: true});
onINP((metrics) => sendDataToLogRUM(metrics,'INP'),{reportAllChanges: true});
</script>

The Logging system which has been used here is ELK , you can send the data to your logging system as needed.@redBus we started taking this data at our logging system and we analyse the INP per page and per interaction and categorise it based on network also.

IT’s really amazing to analyse this data and understand users interaction issues. By the way it’s important to understand that you will not get exact issues or INP numbers from same events, but you will surely get a direction to look into.

Sample Data Collected at RUM :-

INP sample
Meta for the INP report collected.

2. Another approach to get this data is using webpack module.

import {onLCP, onFID, onCLS} from 'web-vitals';

onCLS(console.log);
onFID(console.log);
onLCP(console.log);

This is more preferred approach but the only point we need to focus on here is :- It will get added to all the bundles wherever you want to track the INP and integration effort is at all pages (depends on architecture.)

This brings us to next part:- Impact areas created by INP on system(frontend and backend)?

This might look a bit controversial but trust me this vitals will guide you in such a way that you may fix your api which powers your frontend. Changes which redBus did:-

  1. Optimised user’s first interaction points which is mandatory to navigate to next screen for booking.

2. Made our api lighter which are tied up to all user interactions.

3. Reduced API response time and data transferred over api calls, (This is use-case based), ex- On our search page user can see only 3 busses at once hence creating more search results can be deferred on demand which means on user scroll.

Exact redBus use-cases samples.

Lets see some use cases:-

  1. On click of date change by user on search page, we call all relevant data for that source and destination for next date. It was having bad INP.
INP date change use case.

2. On scroll of inventory redBus does a lazy load of inventory and calls next set of inventory from next offset(ex:- initial load batch 0–10 buses then next batch api response 11–20).

Fixes:
To improve the INP value and performance of the search page, we made several improvements, including:

  • Adding a debounced function call to scroll listener method calls and making one-time calculations out of scroll listener methods to reduce browser recalculations and repaint frequency.
  • You can also use the `requestAnimationFrame`, It tells the browser that you wish to perform an animation and requests that the browser calls a specified function to update an animation before the next repaint. The method takes a callback as an argument to be invoked before the repaint.
  • Fetching new batches of results on the second last card on the SRP page to improve UX and visual performance.
  • Decreasing the initial batch size of search results from 30 to 10 for all routes. After implementing just this change, we checked the 95 percentile of field data from ELK and found that the scores improved significantly from 870–900 to 350–370.

Conclusion:
By making several changes, including adding a debounced function call, changing the initial batch size, and improving the UX by fetching new results beforehand, we significantly improved the INP score and overall performance of the search page. The changes resulted in a smoother and faster user experience and improved performance.

3. Input Fields on Customer Info Page

Problem:
The onChange function on the input fields called the reducer for each change, resulting in unwanted re-rendering and poor INP values.

INP at client side

Fixes:
To improve the INP value of the input fields on the Customer Information page, we managed the state of input components locally and synced it with the redux store only when the onBlur event was triggered. This change reduced the number of re-renders and eliminated unwanted re-rendering caused by calling the reducer for each change.

INP at client side

Conclusion:
By managing the state of input components locally and syncing with the redux store only when the onBlur event was triggered, we significantly improved the INP value of the input fields by 72%. The change resulted in a faster and smoother user experience and eliminated unwanted re-rendering caused by calling the reducer for each change.

final outcome impact to user and business.

Here comes the most interesting part which is important for every one to understand what impact this can create.

redBus has not fixed all the INP related issues at different page of booking funnel, for different network divisions etc… but we have identified major bottleneck which blocks our user from travelling deeper into the booking funnel , this helped us to increase our page to page conversion rate but the major impact was when our CR improved by 6% - 7.2% approx for one our operating countries and decent increments are on other geo also.

Hopefully this would bring out the importance of having good user experience and INP helped us in solving it till great extent.

FINAL WORDS

To conclude, I would just say that if you really want to understand user interaction problems, then this vital is a perfect starting point. Analyse these numbers and you will get a clear indication about your users flow problems.

Follow me on https://amitkumar-v.medium.com/

Thanks for reading, have a great day!

Have a specific question? Drop us a tweet.

Co- Author:- https://harshkc.medium.com

--

--