Adding view count to your Nextjs Blog

100lvlmaster

Navin Kodag

Posted on November 7, 2021

Adding view count to your Nextjs Blog

Alright lads, this will be a quick one. I want to add the views count functionality on my personal portfolio website's blog section.

ready.gif

Expected behavior:

  • Blogs Page : List of blogs -> Show count.
  • Blog Page : Particular Article -> Show count and Increment count.

How to achieve:

  • Use supabase to store count by slug
  • Stored procedure to increment count

Tools that I'll need:

  • supabase : open source firebase alternative
  • swr : data fetching

Setting up supabase table :

Create a table views with schema like such:

  • slug -> text -> primary key
  • created_at -> timestamp -> now()
  • count -> int2

Updating count:

  • Fetch count
  • Increment one
  • Fetch count again

Now we can reduce this to one db call using stored procedures:
stored-procedure.png

create function increment (slug_text text)
returns void as
$$
update views
set count = count + 1
where slug = slug_text;
$$
language sql volatile;
Enter fullscreen mode Exit fullscreen mode

In NextJs:

We'll define a route for ease:
- /api/view/{slug}
and then we'll use the POST request to register a view and GET to increment the view count.
Our handler code will look like this:
views.ts

import { createClient, PostgrestError } from "@supabase/supabase-js";
const supabase = createClient(
process.env.SUPABASE_URL,
process.env.SUPABASE_KEY
);
interface SupabaseResult {
    data?: { count: number };
    error?: PostgrestError;
}
///
const getViews = async (slug: string): Promise<number> => {
const { data: views, error }: SupabaseResult = await supabase
.from("views")
.select(`count`)
.match({ slug: slug })
.single();
if (error && error.details.includes(`0 rows`)) {
    const { data, error }: SupabaseResult = await supabase
    .from(`views`)
    .insert({ slug: slug, count: 1 }, { returning: `representation` })
    .single();
    return data.count;
    }
    if (!views) {
    return 0;
    }
    return views.count;
    };
///
    const registerView = async (slug: string): Promise<void> => {
    const { data, error } = await supabase.rpc("increment", {
    slug_text: slug,
    });
};
export { getViews, registerView };
Enter fullscreen mode Exit fullscreen mode
  • /api/view/[slug].ts
// /api/view/[slug].ts
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import { getViews, registerView } from "lib/views";
import type { NextApiRequest, NextApiResponse } from "next";
interface Data {
    message?: string;
    status?: number;
    count?: number;
}

///
export default async function handler(
req: NextApiRequest,
res: NextApiResponse<Data>
): Promise<void> {
const slug = req.query.slug.toString();
///
if (!slug) {
    return res.status(400).json({ message: `invalid slug` });
}
if (req.method == `POST`) {
    await registerView(slug);
}
const count = await getViews(slug);
return res.status(200).json({ count: count });
}
Enter fullscreen mode Exit fullscreen mode

ViewCounter Component

  • view_counter.tsx
import fetcher from "lib/fetcher";
import { Views } from "lib/types";
import { useEffect } from "react";
import useSWR from "swr";

interface Props {
    slug: string;
}

const ViewCounter = ({ slug }: Props) => {
const { data } = useSWR<Views>(`/api/views/${slug}`, fetcher);
useEffect(() => {
    const registerView = () =>
    fetch(`/api/views/${slug}`, {
        method: "POST",
    });
    registerView();
}, [slug]);

return (
    <span>{`${
    (data?.count ?? 0) > 0 ? data.count.toLocaleString() :"–––"
    } views`}</span>
    );
};

export default ViewCounter;
Enter fullscreen mode Exit fullscreen mode

Our views in action:
view_counter.png
view_count.png

The code of this project lives at : https://github.com/100lvlmaster/100lvlmaster.in


You can find me at: https://100lvlmaster.in

💖 💪 🙅 🚩
100lvlmaster
Navin Kodag

Posted on November 7, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Adding view count to your Nextjs Blog
supabase Adding view count to your Nextjs Blog

November 7, 2021