How to measure Next.js Web Vitals using an analytics tool
Tags: javascript, react, analytics, webdev
Published: 2020-12-02 05:31:36

# 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](https://web.dev/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](https://nextjs.org/) 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/](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](https://nextjs.org/docs/advanced-features/measuring-performance#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](https://app.quickmetrics.io/signup). Select the free plan as it is very generous for our usage.

> ![create_account.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1606302861245/vnzDvb9Ke.png?border=1,CCCCCC&auto=compress)
*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](https://cdn.hashnode.com/res/hashnode/image/upload/v1606302881826/drZt-M5MU.png?border=1,CCCCCC&auto=compress)
*Figure 2: API Key in the Access URL*

A point to note, [Vercel](https://vercel.com/docs) 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](https://nextjs.org/analytics) 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](https://github.com/atapas/nextjs-playground)

> ![use_this_template.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1606302541147/c77qGABnA.png?border=1,CCCCCC&auto=compress)
*Figure 3: Create a Next.js project using template*

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

```shell
cd nextjs-analytics/
```

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

```shell
yarn install # Or, npm install
```
After the dependencies are installed successfully, use this command to run the application,

```shell
yarn dev # Or, npm run dev
```
You should see the message in the command prompt confirming the app is running on [http://localhost:3000](http://localhost:3000).

> ![yarn_dev.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1606303188520/wBkf2ZWo5.png?border=1,CCCCCC&auto=compress)
*Figure 4: Successful run*

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

> ![first_page.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1606303276455/6CRh7IlBe.png?border=1,CCCCCC&auto=compress)
*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,

```shell
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](https://cdn.hashnode.com/res/hashnode/image/upload/v1606303576907/AuHjh8VF7.png?border=1,CCCCCC&auto=compress)
*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,

```shell
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.

```js
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,

```js
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:

> [How To Log User Activities Using The Beacon Web Api](https://blog.greenroots.info/how-to-log-user-activities-using-the-beacon-web-api-ckgq6s7k0094do9s15udf767u)

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](https://cdn.hashnode.com/res/hashnode/image/upload/v1606304237735/LLT1EIlsO.png?border=1,CCCCCC&auto=compress)
*Figure 7: Trace Requests*

# Inspect Metrics
Check the [Quickmetrics Metric Page](https://app.quickmetrics.io/metrics) to inspect and perform some analytics on it.

A list of metrics information collected,

> ![Mtric_1.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1606304461224/mFrfaQmkb.png?border=1,CCCCCC&auto=compress)
*Figure 8: Metrics Information*

You can drill-down to each of the metrics,

> ![Mtric_2.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1606304472155/wZs3Fm53O.png?border=1,CCCCCC&auto=compress)
*Figure 9: Metrics Drill-Down*

You can customize them based on your needs,

> ![Mtric_3.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1606304482154/avv5yA2Uw.png?border=1,CCCCCC&auto=compress)
*Figure 10: Customize Visualization*

# Before we end...

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

{% github atapas/nextjs-analytics %}

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

Please like/share this article so that it reaches others as well. You may also like,
- [10 lesser-known Web APIs you may want to use](https://blog.greenroots.info/10-lesser-known-web-apis-you-may-want-to-use-ckejv75cr012y70s158n85yhn)
- [How to log user activities using the Beacon Web API?](How to log user activities using the Beacon Web API?)
- [JAMstack for All: An Introduction](https://blog.greenroots.info/jamstack-for-all-an-introduction-cke2fxc5800jvabs15lhn4a9x)