NextJS Analytics with Airtable

Published See discussion on Bluesky

I was recently looking for a quick and easy solution to track page hits on my personal site for another small feature add to the site (blog post on that when I get around to it!), and figured that I could probably spin up something very low-fidelity using NextJS's /api routes and Airtable.

To get started, you'll want to create a new Base on Airtable, and a new table within that. I opted to use an empty base as the starting point.

Inside the new table created, I'd recommend making the following changes:

  1. Rename the table, it starts off named as 'Table 1' which isn't all that easy to find, I called mine page-hits
  2. Set the primary column to something unique, I opted to name it id and set the type to Autonumber so I don't need to worry about conflicts
  3. Set the second column to be the url that the user is visiting
  4. Add a third column to track "hit counts" (each record will only have a value of 1 here, I use this to automatically rely on Airtable's Sum feature on columns), I called mine hits

Once you have your Airtable base and table setup, head over to api.airtable.com, and select the base that you just created.

From there, you'll want to change the right-hand-side code preview to JavaScript, and select "Show API key"

For now, grab your api key and now jump to your NextJS project.

Note: This guide assumes you have a NextJS project up and running already, and you at least know of /api routes

Within your NextJS project, if you don't yet have a .env.local file at the root of the project then create one, and add a new line that has some unique all-capitilized key name for the Airtable API key:

1AIRTABLE_API_KEY=your-key-here
1AIRTABLE_API_KEY=your-key-here

Replace your-key-here from the above snippet with the API key from the above Airtable api page

Next, you'll want to setup the api route that you will log to from the frontend of your site, for my site I named it pages/api/record-page.ts, but you can call it whatever!

Then you'll need to install the airtable NPM package:

1yarn add airtable
1yarn add airtable

Within the newly created api file, you'll need to import the airtable package:

1import airtable from 'airtable'
1import airtable from 'airtable'

and configure it with your API key and create the base:

1airtable.configure({
2 apiKey: process.env.AIRTABLE_API_KEY,
3})
4
5let base = airtable.base('your-base-id')
1airtable.configure({
2 apiKey: process.env.AIRTABLE_API_KEY,
3})
4
5let base = airtable.base('your-base-id')

You can find the base-id from the Airtable API page

Now you'll want to create the function that will handle the request from the frontend:

1export default function handler(req, res) {
2 let body = JSON.parse(req.body)
3
4 // Handle local dev reporting
5 if (body.url.includes('localhost')) {
6 res.statusCode = 200
7 res.setHeader('Content-Type', 'application/json')
8 res.end(JSON.stringify({ skipped: true }))
9 return
10 }
11
12 // handle creating the record on airtable
13 base('your-table-name')
14 .create([
15 {
16 fields: {
17 // pass the url
18 url: body.url,
19 // and set the hits to 1
20 hit: 1,
21 },
22 },
23 ])
24 .catch((err) => {
25 console.error(err)
26 })
27
28 res.statusCode = 200
29 res.setHeader('Content-Type', 'application/json')
30 res.end(JSON.stringify({ success: true }))
31}
1export default function handler(req, res) {
2 let body = JSON.parse(req.body)
3
4 // Handle local dev reporting
5 if (body.url.includes('localhost')) {
6 res.statusCode = 200
7 res.setHeader('Content-Type', 'application/json')
8 res.end(JSON.stringify({ skipped: true }))
9 return
10 }
11
12 // handle creating the record on airtable
13 base('your-table-name')
14 .create([
15 {
16 fields: {
17 // pass the url
18 url: body.url,
19 // and set the hits to 1
20 hit: 1,
21 },
22 },
23 ])
24 .catch((err) => {
25 console.error(err)
26 })
27
28 res.statusCode = 200
29 res.setHeader('Content-Type', 'application/json')
30 res.end(JSON.stringify({ success: true }))
31}

and that's it for the server-side code you need to create!

Finally, to use this api route you need to add some code to your _app.tsx file:

1// Import the next router
2import Router from 'next/router'
3
4Router.events.on('routeChangeComplete', () => {
5 fetch('/api/<your-api-route>', {
6 body: JSON.stringify({
7 // pass the current url to the api route
8 url: window.location.href,
9 }),
10 })
11})
1// Import the next router
2import Router from 'next/router'
3
4Router.events.on('routeChangeComplete', () => {
5 fetch('/api/<your-api-route>', {
6 body: JSON.stringify({
7 // pass the current url to the api route
8 url: window.location.href,
9 }),
10 })
11})

This code will add an event listener to the Next Router that will be called when the user has finished a client-side route change between pages.

In addition to the code above, you'll also want to handle tracking fresh page hits:

1// still within _app.tsx
2import { useEffect } from 'react'
3
4export default function App() {
5 // ...
6
7 useEffect(() => {
8 fetch('/api/<your-api-route>', {
9 body: JSON.stringify({
10 // pass the current url to the api route
11 url: window.location.href,
12 }),
13 })
14 }, [])
15
16 // ...
17}
1// still within _app.tsx
2import { useEffect } from 'react'
3
4export default function App() {
5 // ...
6
7 useEffect(() => {
8 fetch('/api/<your-api-route>', {
9 body: JSON.stringify({
10 // pass the current url to the api route
11 url: window.location.href,
12 }),
13 })
14 }, [])
15
16 // ...
17}

That should be it! With the above configured, you should now be able to see Airtable records created when a visitor lands on one of the routes for your NextJS site! Let me know what you thought about this blog post by tweeting at me or emailingme!