How to measure Next.js Web Vitals using an analytics tool

Subscribe to my newsletter and never miss my upcoming articles

Listen to this article

Introduction

This article is for both Beginners and Experienced developers with Next.js. Prior experience with any sort of analytics is NOT Required.

The Web Vitals are the key metrics that can help you to quantify the experience of your web site/app. Knowing these, you can take several steps to improve your web site/app as a developer.

Next.js is a react framework that makes you ready for production by providing many of the out-of-the-box features. Features like hybrid static and server rendering, smart bundling, route pre-fetching, and more you don't have to implement yourself.

A Next.js app will automatically keep track of the web vital metrics and give you back a report. You can take this report to feed into analytics tools (like Google Analytics) to get a better insight into it.

In this article, we will learn how to integrate the Next.js Web Vital report with a light-weight analytics app called, Quickmetrics.

An overview of the Web Vitals

Here is a quick overview of the web vitals,

  • Time to First Byte (TTFB): It refers to the time between the browser requesting a page and when it receives the first byte of information from the server.
  • First Contentful Paint (FCP): The time when the browser renders the first bit of content.
  • Largest Contentful Paint (LCP): It measures loading performance. For better user performance, LCP should occur within 2.5 seconds.
  • First Input Delay (FID): It measures interactivity. A better user experience should have a page FID of fewer than 100 milliseconds.
  • Cumulative Layout Shift (CLS): It measures visual stability. Pages should maintain a CLS of less than 0.1.

Read in-depth about the Web Vitals from here: https://web.dev/vitals/

There are some Next.js specific vitals as well,

  • Next.js-hydration: The amount of time it takes a page to start and finish hydrating the HTML.
  • Next.js-route-change-to-render: The amount of time it takes a page to start rendering after a route change.
  • Next.js-render: The amount of time it takes a page to finish rendering after a route change.

Read about the custom metrics from here: Next.js Custom Metrics

Setup an Analytics tool: Quickmetrics

Quickmetrics is a tool for custom metric collection with data visualization. We will use this tool to feed the web vitals data from a Next.js app. To get started, Sign Up with Quickmetrics. Select the free plan as it is very generous for our usage.

create_account.png Figure 1: Quickmetrics Create Account

After creating an account, log in and make a note of your API key. We will use that API key in the latter part of the article.

URL_Params.png Figure 2: API Key in the Access URL

A point to note, Vercel has excellent analytics support for Next.js applications. You can enable it by deploying your Next.js app to Vercel. By default, the option will be disabled but can be enabled per-project basis by navigating to the analytics tab. Visit this page to learn more about it.

Step 2: Your Next.js app

You can skip this section if you already have a Next.js application. In case, you don't, follow these steps to get things ready.

Browse to this GitHub Project and use the template to create a Next.js project for you.

GitHub Repo: Next.js Playground

use_this_template.png Figure 3: Create a Next.js project using template

Clone the new project to your computer drive and change the directory to it.

cd nextjs-analytics/

We will need Node.js and npm installed to run this project. Install dependencies using npm or yarn.

yarn install # Or, npm install

After the dependencies are installed successfully, use this command to run the application,

yarn dev # Or, npm run dev

You should see the message in the command prompt confirming the app is running on http://localhost:3000.

yarn_dev.png Figure 4: Successful run

Open a browser tab/window and access the app using the URL http://localhost:3000. Great, you should see a page like this,

first_page.png Figure 5: App runs successfully

Don't you think, the page is a bit empty? It would be great if we add some names, project descriptions, etc. Let's do that.

Create a file with the name .env.local at the root of your project folder with the following content,

NEXT_PUBLIC_NAME=Tapas Adhikary
NEXT_PUBLIC_FAKE_BLOG_NAME=My Fake Blog
NEXT_PUBLIC_ORIGINAL_BLOG_NAME=GreenRoots Blog
NEXT_PUBLIC_ORIGINAL_BLOG_LINK=https://blog.greenroots.com
NEXT_PUBLIC_TWITTER_LINK=https://twitter.com/tapasadhikary

Note: You can use the values of your choice. I have used these values for the example purpose.

Restart the yarn dev command. Refresh the page to see the changes appearing.

updated_page.png Figure 6: App running infro from the environment variables

Please Note: It is not necessary to get these details from the environment variables. We did that just to get us familiar with the environment variable handling in Next.js. We will use it for a more real purpose just now.

Step 3: Enable Analytics with Quickmetrics

Add a couple of more entries in the .env.local file,

NEXT_PUBLIC_QUICK_METRICS_API_KEY=EDiH_ZnU0IYxMlNtqfaesB
NEXT_PUBLIC_SEND_ANALYTICS=false

The NEXT_PUBLIC_QUICK_METRICS_API_KEY key is to specify the API Key you have noted down previously. The NEXT_PUBLIC_SEND_ANALYTICS is for our convenience to turn on/off analytics reporting.

Please Note: Next.js requires you to prefix NEXT_PUBLIC_ to your environment variables to make them available in the browser.

Alright, now open the file pages/_app.js file and add this code snippet.

To measure any of the supported metrics in the Next.js app, you will need to create a custom App component and define a reportWebVitals function.

export function reportWebVitals(metric) {
    switch (metric.name) {
      case 'FCP':
        // handle FCP results
        sendAnalytics(metric);
        break
      case 'LCP':
        sendAnalytics(metric);
        break
      case 'CLS':
        sendAnalytics(metric);
        break
      case 'FID':
        sendAnalytics(metric);
        break
      case 'TTFB':
        sendAnalytics(metric);
        break
      case 'Next.js-hydration':
        sendAnalytics(metric);
        break
      case 'Next.js-route-change-to-render':
        sendAnalytics(metric);
        break
      case 'Next.js-render':
        sendAnalytics(metric);
        break
      default:
        break
    }
  }

Last, please add the sendAnalytics function,

const sendAnalytics = ({ name, value }) => {
    if (process.env.NEXT_PUBLIC_SEND_ANALYTICS) {
        const url = `https://qckm.io?m=${name}&v=${value}&k=${process.env.NEXT_PUBLIC_QUICK_METRICS_API_KEY}`;

        // Use `navigator.sendBeacon()` if available, falling back to `fetch()`.
        if (navigator.sendBeacon) {
            navigator.sendBeacon(url);
        } else {
        fetch(url, { method: "POST", keepalive: true });
        }
    } else {
        console.warn('The Analytcs feature is disabled');
    }
};

Here we first check if the analytics is enabled. If yes, construct the URL as suggested in the Quickmetrics setting to pass the metric name, value, and API Key.

Note, we are using the Beacon Request as default. If it is not supported by the browser, we fallback to the fetch. If you are new to the Beacon, you can learn it from here:

Restart the yarn dev command and refresh the app a few times in the browser. You should be able to trace these requests from the debugger tool,

network.png Figure 7: Trace Requests

Inspect Metrics

Check the Quickmetrics Metric Page to inspect and perform some analytics on it.

A list of metrics information collected,

Mtric_1.png Figure 8: Metrics Information

You can drill-down to each of the metrics,

Mtric_2.png Figure 9: Metrics Drill-Down

You can customize them based on your needs,

Mtric_3.png Figure 10: Customize Visualization

Before we end...

All the source code used in the article can be found here,

Thank you for reading this far! Let’s connect. You can @ me on Twitter (@tapasadhikary) with comments, or feel free to follow.

Please like/share this article so that it reaches others as well. You may also like,

No Comments Yet