All Blog Articles

Build Your Own Bitly with Payload CMS | Part 1

Media
Sandro WegmannMay 14, 2025
Step-by-step guide to building a Bitly-style link tracker with Payload CMS, custom redirects, and data visualization.

In this article, we will explore how to create a link tracking system using Payload NextJS. This system is similar to Bitly but tailored for our own infrastructure. We'll dive into the entire process, covering everything from setting up collections to visualizing data with charts. This guide is based on a video by AllAboutPayload, and it’s the first part of a multi-part series.

For visual learners or those who prefer following along with video instruction, we’ve created a video tutorial covering this exact process. It offers additional context, real-time demonstrations, and helpful insights for each step of the build. Watch it here: https://www.youtube.com/watch?v=ufItUxAAipk


Table of Contents


What You Will Learn

  • Setting up a link tracking system using Payload CMS
  • Creating collections to store tracked links and clicks
  • Implementing custom Express routes for redirects
  • Visualizing data with Tremor charts


Getting Started

Before we begin, let’s outline our plan for creating this link tracking system. Our main goals are:

  1. Create a collection for tracked links.
  2. Store link clicks in a separate collection to avoid indefinite growth.
  3. Implement a custom Express route to handle redirects.
  4. Visualize link click statistics over various time frames.

We’ll use the Tremor charting library to visualize our data. If you haven't set up a Payload CMS project yet, ensure you have Tailwind CSS implemented, as this will be crucial for our styling.

Creating Collections

We will create two collections: one for tracked links and another for tracking link clicks. Let’s start with the tracked links collection.

In our collection, we will define the following attributes:

  • Slug: This will be used to create the shortened URL.
  • Name: For internal use, to identify the link.
  • Href: The actual URL that the slug will redirect to.

Here’s how to set it up:

We will give it a slug, labels, and for fields, we can give it a name just for our internal use. The most important two parts are the actual internal link, which we’ll call Slack, and the href, which is the actual link that it should call.


The second collection will store the link clicks. Here’s what we’ll include:

  • Tracked Link: Reference to the link that was clicked.
  • Timestamp: Automatically saved by Payload.

This separation is important because storing clicks directly in the link document can lead to performance issues as the number of clicks grows.


Setting Up the Server

Once our collections are created, we will need to configure our Payload CMS settings to include these collections. After that, we will start our development server to ensure everything is functioning correctly.

During this process, you may encounter errors related to relationships or undefined fields. It’s crucial to ensure all collections are correctly imported and defined.

payload-cms-collections-config-setup-server.jpg


Implementing the Redirect Functionality

Now that our collections are set up, it’s time to implement the functionality that will handle redirects. We will create a custom Express route that listens for GET requests on our defined slug.

Here’s how we’ll do it:

  1. Define a dynamic slug in the route.
  2. Fetch the corresponding tracked link from the database.
  3. Count the click and redirect the user to the href URL.


To fetch the link, we will use the local Payload API. This allows us to retrieve the link based on the slug provided in the URL. We must ensure the query correctly matches the slug, as this is a common source of errors.

fetch-link-slug-payload-cms-api-query.jpg


Counting Clicks

After successfully fetching the link, we will create a record in our tracked link clicks collection to register the click. This will help us gather statistics over time.

Visualizing Click Data

With our backend set up and functional, it’s time to visualize the link click data. We’ll use the Tremor library for this purpose. The first step is to install the library and create a custom component for our chart.


Creating the Chart Component

We will create a new component, LinkClickChart.jsx, and configure it to receive data from our tracked link clicks collection. This component will render a line chart displaying the number of clicks over time.


Fetching the Data for the Chart

We will set up a state to hold the link click data and use the useEffect hook to fetch this data when the component loads. It’s essential to format the data correctly so that it can be displayed in the chart.


Preparing Data for the Chart

The data structure we require for the chart is an array of objects, where each object contains a date and the corresponding number of clicks. If we have multiple clicks on the same day, we need to aggregate this data accordingly.

We can achieve this either on the client side or server side. However, for performance reasons, it’s better to handle this on the server side using MongoDB’s aggregation framework.

Creating the Aggregation Handler

We will create a new handler in our tracked link clicks collection for aggregating the data. This handler will use the MongoDB aggregation pipeline to format the data into the required structure.


Securing the Endpoint

To ensure our data is secure, we should protect our custom endpoint by implementing user authentication. We can check the rec.user object to verify if the user is authorized to access the endpoint.


Implementing Date Filters

To enhance our chart, we can add functionality to filter the data based on a date range. This will allow users to view statistics for different time periods, such as the last seven days or the last thirty days.

We will create a simple select field that lets users choose the date range they wish to view. Based on this selection, we will fetch the corresponding data from our backend.


Conclusion

This article provided an overview of building a link tracking system using Payload NextJS. We covered creating collections, implementing redirects, visualizing data with Tremor charts, and more. This is just the first part of the series, so stay tuned for the next installment where we will dive deeper into additional functionalities and optimizations.

FAQ

What is Payload CMS?

Payload CMS is a headless content management system that allows developers to create customizable applications with ease.

Can I use other charting libraries?

Yes, while we used Tremor in this tutorial, you can choose any charting library that suits your needs.

Is this project scalable?

Yes, this project can be scaled by optimizing the database queries and implementing caching strategies.

Where can I find more resources on Payload CMS?

You can visit the official Payload CMS documentation for more information and resources.

If you have any questions or would like to see more topics covered, feel free to reach out in the comments!