Website Visitor Counter using Vanilla JavaScript

Learn to create a Unique Visitor Counter for your webpage using Vanilla Javascript only without any Analytics or Server Code

Website Visitor Counter using Vanilla JavaScript

Hello Fellow Developers👋

In this tutorial, we are going to make a Unique Visitor Counter for your website without using any Analytics Tools or Server code. We will be using a free API service and the localStorage to track unique users on the website. This counter can be used on smaller websites to keep a track of the number of unique visitors to that site or webpage.

Table of Contents

  1. What are Hit/Visitor Counters?
  2. How do Analytics and Visitor Counter Tools work?
  3. The Count API
  4. Building our Project
  5. What is Local Storage in a browser?

Prerequisites

  • Basic knowledge of Javascript
  • Knowledge of Fetch API and localStorage

What are Visitor Counters?

A web counter or hit counter is a computer software program that indicates the number of visitors or hits, a particular webpage has received. Once set up, these counters will be incremented by one every time the web page is accessed in a web browser.

Visitor counters keep track of how often a website is accessed and usually display the number of visitors at the bottom of the homepage. While the visual output of the user data generally only serves a representational purpose, many website operators also use the discovered visitor numbers for web analytics.

How do Analytics and Hit Counter work?

In most cases, a hit counter acts as an increment counter that counts the unique visits of users from different IP addresses. Also, if the same visitor visits the web page or reloads it, then the web counter does not increment the visitor hit. This is because it recognizes that the visitor is the same by recalling the generated IP address. A simple counter only performs counting the visitor hits that is related to the web page.

Now let's see how one of the most popular Analytics tools - Google Analytics work

Google Analytics works by relying on a small bit of Javascript Code that is placed on your website This code is activated when visitors arrive on your site. It allows Google to record important information about your site so that you can better understand your site visitors and build your business.

The code that you place on your website will look at three main sources of data and information. It will use:

  • First party cookies
  • The HTTP request that the browser sends
  • The browser and system information of the user

The process of collecting data for analytics follows the following steps:

  • The server responds by sending the page that is requested to the user’s browser. In this way, once the browser analyzes the data, it will contact other servers that will deal with some parts of the code of that requested page.
  • Next, the user’s browser that visits your page asks that code to Analytics. The platform is sent and saved in a file.
  • Once all the data has been collected, the code creates cookies on the visitor’s computer.
  • When the cookies are already defined, the code sends all that information to the Google Analytics server.
  • Then save the data in another file called File Logs and create a section of data in it for each page viewed. These data include aspects such as the date and time, the search engine where the visitor comes from, the number of visits, etc.
  • Finally, a detailed report will be generated for the owner.

The Count API

We will be using an API called Count API- a free counting service that can be used to track page hits and specific events. This API allows you to create simple numeric counters. It simplifies the operations to:

  • Create a counter and restrict its operations
  • Reset the value of a counter
  • Increment/decrement a counter

Each counter is identified inside a namespace with a key. The namespace needs to be uniquely identified, and thus using the domain name can easily be used as a namespace. If the namespace is not specified the key is assigned to the default namespace. Also, each time a key is updated its expiration is set to 6 months and so we don't have to worry about the expiration of the key.

Let's have a look at some of the endpoints that are available to use

  • /get/:namespace?/:key - The get endpoint gets the value of a key on the namespace.

    https://api.countapi.xyz/get/namespace/key200 { "value": 1234 }
    
  • /hit/:namespace?/:key - The hit endpoint provides increment by one counter directly. Each time it's requested the counter will increase by one. This endpoint will create a key if it doesn't exist and increment it by one on each subsequent request.

    https://api.countapi.xyz/hit/namespace/key200 { "value": 1235 }
    

    Note: The value was incremented on the hit request.

  • /set/:namespace?/:key?value=:value - The set endpoint sets the value of a key. The key must be created with enable_reset set to 1 (true). This endpoint will return the previous value before the assignation.

    https://api.countapi.xyz/set/test?value=23
     200 { "old_value": 42, "value": 23 }
    
  • /create - The create endpoint will create a key on the namespace. Various optional parameters such as key, namespace, value, enable_reset are available.

    https://api.countapi.xyz/create200 {"namespace":"default", "key":"6d5891ff-ebda-48fb-a760-8549d6a3bf3a", "value":0}
    

Lets Build

The hit endpoint increments the value every time it is requested and thus directly fetching the URL would increment the counter even if the page was refreshed since the Javascript code executes again. Thus we need to figure out a way if the user has already visited the website from their browser or not?

The solution - Using the LocalStorage of the browser.

What is the Local Storage?

The localStorage is a read-only property (A part of the HTML5 Web Storage API) of the window interface that allows us to access a Storage object for the Document's origin. The localStorage property stores data in a key-value pair in a web browser.

The stored data is saved across browser sessions and have no expiration date. localStorage data for a document loaded in a "private browsing" or "incognito" session is cleared when the last "private" tab is closed.

Let's see how to implement the counter.

Creating the main index.html file

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width,
         initial-scale=1.0" />
    <link rel="stylesheet" href="styles.css" />
    <title>Unique Visitor Counter</title>
  </head>
  <body>
    <div class="counter">
      <span>0</span>
      <span>0</span>
      <span>0</span>
      <span>0</span>
      <span>0</span>
      <span>0</span>
    </div>
    <div class="message">Unique Visits to this Page</div>
    <script src="./index.js"></script>
  </body>
</html>

Adding styles via styles.css

body {
  background: #237ccf;
  color: #fff;
  font-size: 24px;
  font-family: Verdana;
}
span {
  display: inline-block;
  padding: 10px 10px 6px;
  border-radius: 6px;
  background: #80b4e5;
  margin: 5px 5px;
  font-size: 5rem;
}
.counter{
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
}
.message {
  color: #ccc6e3;
    text-align: center;
    margin-top: 10px;
}

On creating the index.html and styles.css, the webpage looks like this.

Screenshot_20210522_160315.png

Now let's work on the Javascript Logic

const COUNT_URL = "https://api.countapi.xyz";
const NAMESPACE = "devppratik.github.io";
const KEY = "ef9f1af2-bac5-11eb-8529-0242ac130003";

const counter = document.querySelectorAll('span');

We start by setting the base URL, namespace and a unique key as constants. The namespace is the domain name of our website. Here I have used a UUID generated from Online UUID Generator Tool as my key for the namespace. Also, we select all the span tags from the DOM using the querySelectorAll method

const getCount = async () => {
  const response = await fetch(`${COUNT_URL}/get/${NAMESPACE}/${KEY}`);
  const data = await response.json();
  setValue(data.value);
};

const incrementCount = async () => {
  const response = await fetch(`${COUNT_URL}/hit/${NAMESPACE}/${KEY}`);
  const data = await response.json();
  setValue(data.value);
};

Next, we declare two async functions - getCount and incrementCount. The getCount function is used to fetch the current count from our unique COUNT URL and return the value whereas the incrementCount function is used to hit the endpoint to increment the visitor counter value

const setValue = (num) => {
  var str = num.toString().padStart(6, "0");
  for (let index = 0; index < str.length; index++) {
    const element = str[index];
    counter[index].innerHTML = element;
  }
};

After receiving the data, we declare a function to set the counter value on the DOM.

The padStart() method pads the current string with another string (multiple times, if needed) until the resulting string reaches the given length. The padding is applied from the start of the current string. Here we use the padStart function to convert the counter value to a 6 digit number by padding 0 to the start.

Then iterating over the loop we set the text inside each span tag using inner HTML to the value of the current element i.e the number at that index.

if (localStorage.getItem("hasVisited") == null) {
  incrementCount()
    .then(() => {
      localStorage.setItem("hasVisited", "true");
    })
    .catch((err) => console.log(err));
} else {
  getCount()
    .catch((err) => console.log(err));
}

To check if the user has already visited the website through the same browser or not, we check for a hasVisited key in the localStorage. If the key is null, that indicates the user has visited the webpage for the first time. Thus we create a key named hasVisited with a value of true and store it in the localStorage. Then we update the counter by calling the incrementCounter function.

If the user has already visited the website/webpage then the hasVisited key must be present in the localStorage and we do not increase the counter.

Full JS Code

const KEY = `ef9f1af2-bac5-11eb-8529-0242ac130003`;
const NAMESPACE = "devppratik.github.io";
const COUNT_URL = `https://api.countapi.xyz`;

const counter = document.querySelectorAll('span');

const getCount = async () => {
  const response = await fetch(`${COUNT_URL}/get/${NAMESPACE}/${KEY}`);
  const data = await response.json();
    setValue(data.value);
};

const incrementCount = async () => {
  const response = await fetch(`${COUNT_URL}/hit/${NAMESPACE}/${KEY}`);
  const data = await response.json();
  setValue(data.value);
};

const setValue = (num) => {
  var str = num.toString().padStart(6, "0");
  for (let index = 0; index < str.length; index++) {
    const element = str[index];
    counter[index].innerHTML = element;
  }
};

if (localStorage.getItem("hasVisited") == null) {
  incrementCount()
    .then(() => {
      localStorage.setItem("hasVisited", "true");
    })
    .catch((err) => console.log(err));
} else {
  getCount()
    .catch((err) => console.log(err));
}

The final counter after a few visits look like this Screenshot_20210522_183830.png

Drawback of this method

Nothing is perfect and there are a few drawbacks of tracking visitor count in this method.

  • The key value might get expired if the value is not updated during its lifetime period.
  • Since the CountAPI is public and also supports updating the value of a counter, someone can set the value of the counter to some arbitrary value.
  • If the user has Javascript or LocalStorage disabled then this method might not work.

One way of preventing this is to set the counter value in a Database Service like Firestore and then reading or updating the counter value.

But Hey! No one really opens up the Inspect Panel besides Web Developers to check which requests are being made or to clear the localStorage.😉

Conclusion

And Voilà, we have made a simple Unique Visitor Counter using only Vanilla Javascript. This is a very simple method for adding a visitor counter to small or personal websites. This method is easy to implement but It has very limited functionality.

Various other methods such as web counters that use IP addresses or analytics tools are available such as Google Analytics that are easy to set up and also provide a lot of other tools and features alongside hit counters. These provide a detailed report for every visit to the webpage.

So, are you going to use it on your next website? Let me know in the comments below! 😊 GitHub repository for the code - Visitor-Counter-JS Demo available here - Demo

If you liked this article, share it with others!

Thanks for reading 🤝🤝

I would ❤ to connect with you at Twitter | LinkedIn | GitHub

Let me know in the comment section if you have any doubt or feedback. Feedback is appreciated!!

See you in my next Blog article!! Stay Safe😷

Happy Learning! 😃😃