How to Add a Clickable Visitor Counter to Your Website

How to Add a Clickable Visitor Counter to Your Website

posted 3 min read

I was thinking of something fun and interactive to add to my portfolio and a clickable counter that visitors could use to leave a little "I was here" message felt like a great idea. It’s simple, engaging, and a great way to make your website feel a bit more personal. If this sounds like something you'd like to create, this guide will walk you through it step by step.

We’ll walk through building a fully functional view counter step by step. You don’t need to be an experienced developer to follow along. Let’s dive in!

1. The HTML: Building the Structure

First, we’ll set up the structure for the view counter. While you can use any icon or button style you like, I’ll be using an eye icon for this tutorial. Here’s the HTML code:

html
<div class="eye-counter">
  <button class="eye-button" aria-label="View counter">
    <svg viewBox="0 0 24 24" width="24" height="24" class="eye-icon">
      <path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/>
    </svg>
    <span class="view-count">0</span>
  </button>
</div>

2. The CSS: Styling the Counter

Let’s add some simple styling to make the counter look clean and centered. Here’s the CSS:

css
.eye-counter {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.eye-button {
  background: none;
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 1rem;
  border-radius: 20px;
  background-color: rgba(255, 255, 255, 0.1);
  color: #333;
  transition: transform 0.3s ease, background-color 0.3s ease;
}

.eye-button:hover {
  transform: scale(1.05);
  background-color: rgba(255, 255, 255, 0.2);
}

.eye-icon {
  fill: currentColor;
}

.view-count {
  font-size: 1rem;
  font-weight: bold;
}

This CSS centers the counter on the page and adds some hover effects for the button.

3. Bringing It to Life with Javascript

Now for the main event, making the counter work.
Here’s the JavaScript, broken down into functions to keep it simple:

javascript
// Run code after the page has loaded
document.addEventListener('DOMContentLoaded', async () => {
  const eyeButton = document.querySelector('.eye-button');
  const viewCount = document.querySelector('.view-count');

  const BIN_URL = 'https://api.jsonbin.io/v3/b/YOUR_BIN_ID'; // Replace with your bin URL
  const API_KEY = 'YOUR_API_KEY'; // Replace with your API key

  // Function to get the visitor's IP address
  async function getVisitorIP() {
    try {
      const response = await fetch('https://api.ipify.org?format=json');
      const data = await response.json();
      return data.ip;
    } catch (error) {
      console.error('Error fetching IP:', error);
      return null;
    }
  }

  // Function to fetch data from JSONBin
  async function fetchBinData() {
    const response = await fetch(BIN_URL, {
      headers: {
        'X-Master-Key': API_KEY
      }
    });
    const result = await response.json();
    return result.record;
  }

  // Function to update data in JSONBin
  async function updateBinData(data) {
    await fetch(BIN_URL, {
      method: 'PUT',
      headers: {
        'Content-Type': 'application/json',
        'X-Master-Key': API_KEY
      },
      body: JSON.stringify(data)
    });
  }

  // Main logic
  const visitorIP = await getVisitorIP();
  if (!visitorIP) {
    eyeButton.classList.add('disabled');
    return;
  }

  const binData = await fetchBinData();
  viewCount.textContent = binData.totalClicks;

  if (binData.clickedIPs.includes(visitorIP)) {
    eyeButton.classList.add('disabled');
  }

  eyeButton.addEventListener('click', async () => {
    if (!eyeButton.classList.contains('disabled')) {
      binData.totalClicks += 1;
      binData.clickedIPs.push(visitorIP);

      await updateBinData(binData);

      viewCount.textContent = binData.totalClicks;
      eyeButton.classList.add('disabled');
    }
  });
});

Breaking It Down:

  1. Get Visitor IP: Fetches the visitor’s IP address using ipify.
  2. Fetch Bin Data: Retrieves the current total clicks and IP list from JSONBin.
  3. Update Bin Data: Updates the click count and IP list in JSONBin.
  4. Prevent Multiple Clicks: Checks if the visitor has already clicked and disables the button if so.

4. Setting Up JSONBin

If you’ve never used JSONBin before, don’t worry! Follow these steps:

  1. Go to JSONBin.io and sign up for a free account.
  2. Create a new bin with the following initial data:

    JSON

    {
      "totalClicks": 0,
       "clickedIPs": []
     } 
    
  1. copy the Bin ID from the bin details page after saving the bin.
  2. Enter your account settings to generate an API Key.
  3. Replace YOUR_BIN_ID and YOUR_API_KEY in the JavaScript code with your actual Bin ID and API Key.

That’s it! You’ve built a fun and interactive view counter. It’s a simple way to engage visitors and add a touch of personality to your site.

Feel free to visit my portfolio to see it in action.

If you read this far, tweet to the author to show them you care. Tweet a Thanks
This is great, however I would like the page update the numbers of views automatically without having to click the icon, it will be more fascinating
Really insightful article!
Great article with step by step instructions. Per Elmer comment, basic steps are given in this article by Bridget. On automatic updates, you can have a script on page load that calls the API to update the count. Tweaking here & there based on need, we should be taking care.
Thanks for the suggestion
That was initially the thought, but I wanted a bit of interaction from the viewer to make it more engaging
Thank you Mubaraq
This is very promising, Thank you

More Posts

What Happens When You Type a URL Into Your Browser? (Interview Question Guide)

Khiilara - Jan 2

A Web App to Showcase all your GitHub Projects

2KAbhishek - May 6, 2024

How Open Source is Shaping My Journey as a Developer

Anuj Kumar Sharma - Jan 7

Supercharge Your React App and Say Goodbye to Memory Leaks!

Ahammad kabeer - Jun 22, 2024

Mastering React: A Mindset for Component-Centric Development

Losalini Rokocakau - May 3, 2024
chevron_left