DEV Community

Bridget Amana
Bridget Amana

Posted on

How to Add a Clickable Visitor Counter to Your Website

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:

<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>
Enter fullscreen mode Exit fullscreen mode

2. The CSS: Styling the Counter

Let’s add some simple styling to make the counter look clean and centered. Here’s the 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;
}
Enter fullscreen mode Exit fullscreen mode

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:

// 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');
    }
  });
});
Enter fullscreen mode Exit fullscreen mode

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:
   {
     "totalClicks": 0,
     "clickedIPs": []
   }
Enter fullscreen mode Exit fullscreen mode
  1. After saving the bin, copy the Bin ID from the bin details page.
  2. Go to 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.

Top comments (0)