Mar 3, 2024

Adding analytics to your website.

Adding analytics using NextJS and Redis.

#Step-by-Step Tutorial: Adding Website Analytics using Redis and TypeScript in Next.js

In this tutorial, we'll walk through the process of integrating website analytics into a Next.js portfolio blog using Redis and TypeScript. Website analytics help track page views, visitor locations, and timestamps, providing valuable insights into user engagement.

#Prerequisites

Before we begin, ensure you have the following:

  1. Node.js and npm: Make sure you have Node.js and npm installed on your machine.
  2. Next.js Project: Set up a Next.js project with TypeScript.
  3. Redis: Redis should be installed and running locally or accessible via a Redis service.

#Step 1: Setting Up Redis Configuration

Redis is a powerful in-memory data store that we'll use to store our website analytics data. We'll start by configuring Redis for our Next.js project.

lib/redis.ts
import { Redis } from '@upstash/redis'

// Create a Redis instance
export const redis = new Redis({
  url: process.env.REDIS_URL!,
  token: process.env.REDIS_KEY!,
})

In this code:

  • We import the Redis class from the @upstash/redis package.
  • We create a new instance of Redis, passing in the Redis URL and authentication key obtained from your Redis provider.

#Step 2: Implementing Analytics Tracking

Now, let's implement the functionality to track page views and retrieve analytics data.

lib/analytics.ts
"use server"

import { redis } from './redis'

// Function to track page views
export async function trackPageView(page: string, country?: string) {
    try {
        // Prepare event data
        const eventData = { page, country, timestamp: new Date().toISOString() }
        // Store event data in Redis list
        await redis.lpush('pageviews', JSON.stringify(eventData))
    } catch (error) {
        console.error('Error tracking page view:', error)
    }
}

// Function to retrieve page views
export async function getPageViews() {
    try {
        // Retrieve page views from Redis list
        const pageviews = await redis.lrange('pageviews', 0, -1)
        // Parse each page view event
        return pageviews.map((pv: string) => JSON.parse(pv))
    } catch (error) {
        console.error('Error getting page views:', error)
        return []
    }
}

Here:

  • We define functions to track page views (trackPageView) and retrieve page view data (getPageViews) from Redis.
  • When tracking a page view, we store the page URL, country (if available), and timestamp in a JSON format in a Redis list.
  • When retrieving page views, we fetch the data from the Redis list and parse each page view event.

#Step 3: Adding Middleware for Tracking

Next, let's add a middleware to track page views on each request to our Next.js application.

middleware.ts
import { NextRequest, NextResponse } from 'next/server'
import { trackPageView } from './lib/analytics'

export default async function middleware(req: NextRequest) {
    try {
        // Track page view for each incoming request
        await trackPageView('/', req.geo?.country)
    } catch (err) {
        console.error(err)
    }

    return NextResponse.next()
}

// Define middleware matcher
export const matcher = {
    matcher: ['/'],
}

Here:

  • We define a middleware that intercepts incoming requests and tracks the page view using the trackPageView function we defined earlier.
  • We use req.geo?.country to get the country of the visitor, if available, and pass it to the trackPageView function along with the page URL.

#Step 4: Displaying Analytics Data

Finally, let's create a page to display the analytics data retrieved from Redis.

analytics/page.tsx
"use client"

import { getPageViews } from '@/lib/analytics'
import { useEffect, useState } from 'react'

export default function Analytics() {
    const [pageviews, setPageviews] = useState<any[]>([])

    // Function to fetch and set page views
    const fetchPageViews = async () => {
        const pageviews = await getPageViews();
        setPageviews(pageviews)
    }

    useEffect(() => {
        // Fetch page views on component mount
        fetchPageViews()
    }, []);

    return (
        <div>
            <h1>Analytics</h1>
            <ul>
                {pageviews.map((pv, index) => (
                    <li key={index}>
                        Page: {pv.page} | Country: {pv.country} | Timestamp: {pv.timestamp}
                    </li>
                ))}
            </ul>
        </div>
    )
}

In this code:

  • We fetch page view data from the server using the getPageViews server action and set it in the component's state.
  • We use React's useEffect hook to fetch page views when the component mounts.
  • We render the page view data in a list format, displaying the page URL, country, and timestamp for each page view event.

#Conclusion

Congratulations! You've successfully integrated website analytics using Redis and TypeScript into your Next.js project. This implementation allows you to track page views, visitor locations, and timestamps, providing valuable insights into user engagement. Feel free to customize and expand upon this implementation to suit your specific requirements and analytics needs.