Tracking user activity on a website is a common requirement for many developers. Whether you are looking to track page views, increment view counts, or manage cookies to store user preferences, it’s essential to implement these features correctly.
In this guide, we will walk through the process of setting up page view tracking in a Next.js 14 application using both server-side and client-side logic. We will increment a view count in a Prisma database and manage cookies to prevent users from repeatedly incrementing views. By the end of this guide, you’ll have a working system to track and store page views in Next.js.
In Next.js, you can mix Server Components and Client Components to handle different functionalities. For page view tracking, we will need to:
Increment the view count on the server-side when a user visits the page.
Set a cookie to track whether the user has viewed the page.
Prevent repeated view tracking for the same user using cookies and local storage.
We will achieve this by separating the logic into server-side and client-side components. The server will handle database operations, while the client will manage cookies and local storage.
Before diving into the code, ensure that you have the following:
Next.js 14 project set up.
Prisma ORM configured with a database (e.g., PostgreSQL, MySQL).
A table in your database to store the blog data, including view counts.
Here’s a simple Prisma model to store blog data:
model Blog {
id Int @id @default(autoincrement())
slug String @unique
title String
content String
coverImage String
reads Int @default(0)
}
In Next.js 14, we can use Server Components to handle tasks like fetching data from a database and checking if a user has viewed a page before. Server-side logic will handle the view count increment in the database.
To check whether the user has already viewed the blog, we use the cookies API provided by Next.js. This function will verify if the user has a cookie indicating they’ve already viewed the page.
import { cookies } from "next/headers";
// Function to check if the blog has been viewed by checking the cookie
export async function checkIfViewed(slug) {
const cookieStore = cookies();
const hasViewed = cookieStore.get(`viewed-${slug}`);
return hasViewed ? true : false;
}
This function will be responsible for incrementing the view count in the Prisma database every time a blog is viewed.
import prisma from "@/lib/prisma";
// Function to increment the view count for a specific blog post
export async function incrementClick(blogId) {
try {
await prisma.Blog.update({
where: { id: blogId },
data: { reads: { increment: 1 } },
});
} catch (error) {
console.log("Error incrementing views:", error);
} finally {
await prisma.$disconnect();
}
}
Once the server-side check is complete, the client-side logic will be responsible for setting cookies and storing the view status in the browser’s localStorage to prevent repeated view counting.
This component will run on the client side. It will set a cookie to track whether the user has viewed the blog, and also interact with localStorage and fetch to increment the view count.
"use client"; // Mark this as a Client Component
import { useEffect } from "react";
export default function ClientSideLogic({ slug, blogId }) {
useEffect(() => {
const setViewedCookie = async () => {
try {
// Set the viewed cookie and increment views
await fetch("/api/set-viewed-cookie", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ slug }),
});
// Set localStorage to mark as viewed so we don't repeat the action
localStorage.setItem(`viewed-${slug}`, "true");
// Increment the view count
await fetch(`/api/increment-views`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ blogId }),
});
} catch (error) {
console.error("Error during the view increment:", error);
}
};
// Run the function to set cookie and increment views
setViewedCookie();
}, [slug, blogId]);
return null; // This component does not need to render anything
}
Now that we have our ClientSideLogic
component, we will trigger it from the Server Component to handle the view increment and cookie setting only if the blog has not been viewed before.
import prisma from "@/lib/prisma";
import { checkIfViewed } from "./checkIfViewed";
import ClientSideLogic from "@/components/ClientSideLogic";
export default async function Blog({ params }) {
const blog = await prisma.Blog.findUnique({
where: { slug: params.slug },
});
const hasViewed = await checkIfViewed(params.slug);
if (!blog) {
return <p>Blog not found</p>;
}
return (
<div className="mt-4">
<h1 className="text-4xl font-bold">{blog.title}</h1>
<div
className="prose-headings:font-title font-default prose mt-4 dark:prose-invert focus:outline-none"
dangerouslySetInnerHTML={{ __html: blog.content }}
></div>
{/* Client-side logic to set viewed cookie and increment views */}
{!hasViewed && <ClientSideLogic slug={params.slug} blogId={blog.id} />}
</div>
);
}
In this guide, we walked through how to implement page view tracking and cookie management in a Next.js 14 application. We used a combination of Server Components and Client Components to ensure that the logic is executed in the correct environment.
By separating the client-side logic (cookies, localStorage, and view count increment) from the server-side logic (fetching blog data and updating the database), we ensure that our application is both performant and scalable. Additionally, this approach ensures that views are only counted once per user by leveraging cookies and localStorage.
With these steps, you can implement similar functionality to track views and manage cookies across your Next.js app!
🔥 Found this blog post helpful? 🔥
If you enjoyed this article and found it valuable, please show your support by clapping 👏 and subscribing to my blog for more in-depth insights on web development and Next.js!
Subscribe here: click me
Your encouragement helps me continue creating high-quality content that can assist you on your development journey. 🚀
👨💻 Programmer | ✈️ Love Traveling | 🍳 Enjoy Cooking | Building cool tech and exploring the world!
View more blogs by me CLICK HERE
Loading related blogs...
In this newsletter we provide latest news about technology, business and startup ideas. Hope you like it.