Track Video Impressions in Next.js with Supabase

Banner for a MediaJam post

Emmanuel Ugwu

Tracking impressions is one of the most effective techniques for determining how well media content performs. An individual can determine which content and information users are most interested in depending on the number of impressions.

A lot of applications now have either Google or Fathom analytics integrated for tracking impressions, but the increasing presence of ad-blockers interferes with the generated reports — and more often than not, the statistics collected by these providers are inaccurate. However, these inaccurate reports can be solved by creating an impression tracker using a serverless database.

A serverless database is any database that embodies the core principles of the serverless computing paradigm, such as little to no manual server management and instant access. The benefit of doing so is obtaining a more accurate count of impressions.

This article demonstrates how to track video impressions using Next.js and Supabase — a serverless database.

CodeSandbox and GitHub

The completed project is on CodeSandbox. Fork it to get started quickly.

The source code is on GitHub.


To get the most out of this article, the following requirements apply:

  • A basic understanding of CSS, JavaScript, and React.js.
  • A Supabase account — Create one here.
  • A Cloudinary account — Create one here.

What is Supabase?

Supabase is an open-source Firebase alternative. Supabase is a set of tools that helps developers build projects faster by handling the backend functions.

Behind the scenes, Supabase uses the PostgreSQL database. It is regarded widely as one of the best tools based on Postgres, a highly scalable relational database. The platform develops a REST API from the database's tables and columns. Its autogenerated APIs include built-in features like filtering and sorting.

Project setup and installation

Create a Next.js app in a new folder by running the following command in your terminal:


1npx create-next-app <project-name>

Navigate into the project directory and install Cloudinary React SDK and Supabase dependencies.

1cd <project-name>
2 npm install cloudinary-react @supabase/supabase-js

Running npm run dev starts the project on the local development server at https://localhost:3000 in our browser.

Setting up a video in Cloudinary

After successfully creating an account, Cloudinary will redirect us to our account's dashboard page, where we can upload the demo video.


Set a name and password for the new project and click on the “New Project" button to create the project, as shown below.


As the project is being built, we’ll create the database for the video impressions by clicking on the database icon shown on the sidebar. After that, click on the “New” button at the top right of the screen to create a table for the database.


Navigate to the SQL editor and create a query tab to add a stored procedure to our database. A stored procedure allows us to add or extend functionality to the database.


Add the code snippet below to the new query to create the stored procedure for our database.

1create function increment (row_id int)
2 returns void as
3 $$
4 update pages
5 set views = views + 1
6 where id = row_id;
7 $$
8 language sql volatile;

Let's break down the query above.

  • The query creates an increment function, with the row id as an argument.
  • set views = views + 1 updates/increases the video impressions value called views in the database table by 1.

Then, click the “RUN” button to create the function. Later we’ll utilize the function to update the video impressions.

Accessing the API URL and API Key

To link the Supabase database to our demo application, we’ll head to Supabase’s homepage, where we can access our Supabase project’s API URL and API Key as shown below:


We need to create a .env file in the app’s root directory to store the API URL and API Key.


Next, we’ll create a file called Supabase.js in pages/components and then add the following code:

2 import { createClient } from "@supabase/supabase-js";
4 export const supabase = createClient(
7 );

Implementing the video player

To access the video for the demo application, import the required components from Cloudinary React SDK to pages/components/index.js as shown below.

1import {Video, CloudinaryContext} from 'cloudinary-react';

Then, in the CloudinaryContext component, apply the Cloud name from our Cloudinary account details on the dashboard page and also include the name of the video in the Video component:

1<CloudinaryContext cloud_name="ugwutotheeshoes">
2 <div>
3 <Video
4 publicId="production_ID_3959604_vnbhqn"
5 width="850px"
6 height="450px"
7 controls
8 innerRef={videoRef}
9 onEnded={endFunction}
10 />
11 </div>
12 </CloudinaryContext>

We’ll also apply some configuration parameters to the video, as shown above. Each of the parameters does the following:

  • publicId - This holds the name of the demo video.
  • width and height - Displays the video with a width of 850px and a height of 450px
  • controls - Gives the video a set of controls such as play, pause, skip, fullscreen, etc.
  • innerRef - This is just another attribute on the custom component in Cloudinary.
  • onEnded - This triggers a function after the video finishes.

After configuring the video player, our demo application will look like this:


Updating the video impressions

Next, we’ll import the Supabase.js file to access the API URL and API Key, then use the onEnded event to update the video impressions in Supabase using the code snippet below.

2 import {supabase} from "./supabase";
4 export default function Home() {
5 const endFunction = async () => {
6 const { data} = await supabase.rpc('increment', { row_id: 1 })
7 };
8 // ....
9 }

The onEnded event occurs when the video has reached the end. The event invokes a function or message when the video ends.

In this instance, we’ll call the endFunction function using a Supabase Remote Procedure Call (RPC) after the video ends. This function call updates the video impressions, as shown below.


After testing our demo application, it should look like this:


Emmanuel Ugwu

Software Engineering | Technical Writing | Web Development

I am a software engineer who is passionate about REST API's and building fast and scalable applications. I also write articles and other technical content to guide developers in the tech community.