Precision in Analytics - Implementing an IP-Based User Counter with Node.js and MongoDB

Roshan Paudel
21 Dec 2024

In today's digital landscape, understanding user behavior and engagement on your website is paramount to its success. To unlock precise insights, we delve into the realm of web analytics, presenting an insightful guide on building an advanced visitor counter. By harnessing the power of Node.js and MongoDB, we not only accurately track unique visitors but also integrate intelligent IP address tracking. Join us on this journey as we unravel the intricacies of user interaction, providing you with a comprehensive understanding of how to craft an intuitive visitor counter that empowers your web analytics strategy.

To prevent counting multiple visits from the same IP address and to ensure that the user count is accurate even when the app is deployed on the cloud, we can use a more robust data storage solution like a database. In this example, I'll use MongoDB to store visitor information.

Headers Containing IP Addresses

In web applications, IP addresses can be extracted from various headers to accurately identify the origin of requests, especially when the application is deployed behind proxies, load balancers, or content delivery networks (CDNs) like Cloudflare. Here are some common headers that may contain IP addresses:

  1. Remote Address (req.ip): This is the default property in Express.js that provides the IP address of the client making the request. However, it may not always reflect the true client IP address when requests pass through intermediaries like proxies or CDNs.
  2. X-Forwarded-For: This header is commonly used by proxies, load balancers, and CDNs to forward the original client IP address. It contains a comma-separated list of IP addresses, with the client's IP address being the first one and subsequent addresses representing intermediary nodes.
  3. CF-Connecting-IP: Cloudflare uses this header to convey the original client IP address to the origin server. It provides the actual client IP address when the request is routed through Cloudflare's network.
  4. Other Custom Headers: In addition to the above, custom headers may also be used to convey IP addresses, depending on the specific setup of the infrastructure. These headers need to be configured and handled appropriately within the application code.

By inspecting these headers in the request object, applications can accurately determine the IP address of the client making the request, ensuring reliable tracking of visitor information and enabling functionalities such as access control, logging, and analytics. However, it's crucial to handle these headers securely and validate user input to prevent security vulnerabilities such as IP spoofing or injection attacks.

X-Forwarded-For: Most commonly used and reliable header for extracting the client's IP address in scenarios where req.ip returns null. It's prevalent in a wide range of setups, including those using proxies, load balancers, and CDNs.

Let's proceed with the modifications:

Step 1: Setting Up MongoDB

  1. Install MongoDB: Make sure you have MongoDB installed and running. If not, follow the official instructions to install it:
  2. Create a MongoDB Database: Create a new database in MongoDB to store visitor information. For example, you can name it visitor_counter.

Step 2: Implementing the Visitor Counter with MongoDB

Install Dependencies: 

Install the necessary dependencies including expressmongoose, and dotenv for managing environment variables:

npm install express mongoose dotenv

Create a .env file: 

Create a .env file in your project directory and add your MongoDB connection string:


Update app.js: Update the app.js file to include MongoDB integration and IP-based visit tracking:

const express = require('express');
const mongoose = require('mongoose');
const app = express();
const port = process.env.PORT || 3000;

// Connect to MongoDB
mongoose.connect(process.env.MONGODB_URI, { useNewUrlParser: true, useUnifiedTopology: true });
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'MongoDB connection error:'));

// Define a schema for visitor data
const visitorSchema = new mongoose.Schema({
  ipAddress: String,
  visitedAt: { type: Date, default: },

// Create a model using the schema
const Visitor = mongoose.model('Visitor', visitorSchema);

app.use(async (req, res, next) => {
  let ipAddress = req.ip; // Default to req.ip

  // Check Cloudflare headers for real client IP address
  if (req.headers['cf-connecting-ip']) {
    ipAddress = req.headers['cf-connecting-ip'];
  } else if (req.headers['x-forwarded-for']) {
    // Use X-Forwarded-For header if available
    ipAddress = req.headers['x-forwarded-for'].split(',')[0];

  // Check other custom headers if needed

  const existingVisitor = await Visitor.findOne({ ipAddress });

  if (!existingVisitor) {
    // Create a new visitor entry
    const newVisitor = new Visitor({ ipAddress });


app.get('/', async (req, res) => {
  const visitorCount = await Visitor.countDocuments();
  res.send(`Total visitors: ${visitorCount}`);

app.listen(port, () => {
  console.log(`Server started on http://localhost:${port}`);

Step 3: Testing the Visitor Counter

Run the Server: In your terminal, run:

node app.js
  1. Access the Website: Open your web browser and navigate to http://localhost:3000. You should see a message indicating the total number of unique visitors.
  2. Access from the Same IP: Open a new tab in your browser or use a different device to access the website. The visitor count should increase only once for each unique IP address.

With these modifications, you've implemented a visitor counter that accurately tracks unique visitors using their IP addresses and stores the data in a MongoDB database. This approach ensures that even when the app is deployed on the cloud, the visitor count remains accurate. Remember to replace <username><password><mongodb_host>, and <mongodb_port> in your .env file with your actual MongoDB credentials and server details.

Share this article in social media

© 2024 Roshan Paudel