Every blog post on my site tracks and displays unique views. I accomplish this by using a Redis Set where the key is a blog slug, and the value contains hashed IP addresses. Since Redis Sets only allow unique values, we'll never count a visitor more than once.
Limitations
There are a few things to consider when using Redis as a data store. In many ways, Redis is meant to be used as a cache that would lose data during a restart or power outage. However, that's not always true. Persistence can be configured to ensure write operations are written to disk. Many cloud services offer this persistent functionality as the default. I'm using Upstash as my cloud Redis store, so I did not worry about persistence.
The second limitation is using IP addresses to track unique users. Users behind a shared router would only count as one view. Or, users being a service like iCloud Private Relay or any type of proxy will have rolling IP addresses that could cause inflated view counts. No option is perfect, but I think using hashed IP addresses is a simple solution without too many compromises.
Things You'll Need to Do
For this example, you'll need to sign up for a free account with Upstash. You'll also need to have a basic understanding of Next.js works. Next.js has built-in API routing, and I'll be utilizing this functionality.
- Sign up for Upstash (Redis cloud service)
- Read the Next.js docs (understand how pages and API routes work)
- Clone the demo repo
Download Dependencies
Run yarn
in your terminal after you've signed up for your free Upstash account and checked out the code.
Environment Variable
Within the root directory of the repo is a file called .env-template
. Rename that file to .env.local
. Then, you'll need to set the value of REDIS_URL
, which can be found on the Upstash dashboard.
Start Your Local Server
It's time to run...
yarn dev
Assuming you don't already have a Node server running, go to http://localhost:3000 in your browser (if you do, your server may be running on another port like 3001, 3002, etc.).
When the Page Loads
First, handleLogView()
is called from a useEffect on page load and sends a POST
to our API api/logView.js
. The post sent a sample slug that's hard-coded as 'example-slug'. I pull the slug from the blog post URL dynamically on my site.
Next, a second function is called, handleGetViewCount()
. This function calls the /api/viewCount API endpoint, which returns the number of IP addresses in our Redis Set. Redis has built-in functions to count how many values are in a set.
Now, if you go to your Upstash dashboard, you can view the new Set created from our API call. You should see a set with the key 'example-slug' and a value of '::1'. ::1 is the default localhost IP address. If this were published on a web server, it'd contain your IP address.
Final Thoughts
We've utilized Redis' standard functionality and speed with very little code to create a view counter. For simplicity, the example uses a hard-coded slug, so you'll want to dynamically pull in the URL slug to ensure the page has its own key and IP addresses. The example also does not hash the IP addresses. You'll want to use a hash with a salt for privacy reasons. It's not a good idea to store plain text IP addresses.