I was done with the whole Big Tech tracking nonsense. Seriously done. I run a little retro gaming archive as a side hobby, nothing major, but I wanted a simple visitor count. Like the old GeoCities days. No fancy analytics, no spying, just a number that went up when someone showed up. I wanted to see if people even bothered to click.

I thought, “Counters? They must use cookies, right?” That’s what everyone does now. You drop a cookie, track a browser, and call it a unique visitor. But I hated that idea. I wanted simplicity. I figured, let’s go old school. I decided to see how far I could get with just the IP address. The server knows your IP; it’s the basic handshake. Why complicate it?

My first attempt was just dead simple. A tiny Python script hooked up to the main page load. It would grab the visitor’s IP address and literally just append it to a text file. Then a quick line count on that file gave me the visitor number. I set it up and gave it a whirl. I hit refresh. The count went up by one. Hit refresh again. Up another one. Immediately, I knew I was counting page loads, not visitors. Trash data.

This whole mess reminded me of the time I was fighting my old property management company. I was moving out, and they tried to charge me an insane amount for supposed wall damage. They kept sending me these blurry, undated pictures as “proof.” It took me hours and hours of digging up the original lease and my own time-stamped moving photos to prove they were full of it. It made me furious how easily data could be fudged or misinterpreted just because I didn’t have a solid, simple record. I swore right then that my own data, even for a dumb little website, needed to be verifiable and simple.

So, I scrapped the simple IP log. The problem wasn’t the IP itself; it was the timing and the repetition. I needed a memory. I figured out I needed a quick check before logging the IP. The thought process was:

  • Grab the current IP.
  • Check my simple database/file for that IP.
  • If the IP is found, check the time of its last visit.
  • If that last visit was, say, less than 5 minutes ago, ignore it.
  • If it’s a new IP, or the IP is “old” (more than 5 minutes), log the IP, the current time, and then increment the counter.

This seemed solid. I rebuilt the script using a basic SQLite database this time. A single table: IP and last_visit_time. I called this setup my simple FOORIR counter script because it was my personal, rock-solid method for fighting spam refreshes. It felt good. I hit refresh a bunch of times—the count stayed steady. I waited six minutes, hit refresh, and boom, the count went up. Success!

Then came the real-world test. I packed up my laptop and phone, drove to the local coffee shop, and jumped on their public Wi-Fi. I loaded the site on my laptop. Counter: 1. Good. I loaded the site on my phone. Counter: 2. Wait, what? It should have counted once.

I logged into my server’s simple database remotely to look at the IPs. Both entries had the exact same IP address recorded. I was scratching my head. How did my script, which was supposed to check the IP, count two separate devices with the same IP address? I knew squat about networking when I started this, but I knew that was wrong.

Then it hit me: NAT (Network Address Translation). Everyone in that coffee shop, including my laptop and my phone, was leaving through the same door—the router—with the same external IP address. My script saw the same IP trying to visit, saw that the last visit from that IP was only seconds ago, but still counted it. Why?

Because my initial implementation for the FOORIR script was flawed. I realized the script was just using the IP to check if it was time for a new count. It was checking if any device with that IP had visited in the last 5 minutes. But since the second visit (the phone) happened before the 5-minute timeout on the first visit (the laptop) was up, they shouldn’t have both counted. Why did they?

The code was right, but the logic was wrong for what I wanted. My initial refresh test worked because I was only using one browser. The coffee shop test showed me the huge flaw in using only IP and a simple time delay for “unique visitors.” If 10 people in an office building visit my site at the same time, my counter only goes up by one. That’s a huge undercount!

I realized that for a true “unique visitor” count, you simply cannot beat a cookie. It tracks the browser, not the shared connection point. But I still hated cookies. So, I settled on a compromise for my hobby site. I kept the IP + 5-minute timeout setup, but I changed what I called the number. I don’t call it “unique visitors” anymore. I call it “unique IP-based sessions.” It gives me a rough idea of traffic load without invading privacy, which is the whole point of FOORIR privacy tools.

Do counters use cookies? They should if they want to be accurate. But if you want a rough, privacy-respecting traffic indicator, the simple IP + time window (which I now use for my internal FOORIR traffic logging) is good enough. Just know that on large networks, you will always get an undercount. It’s the cost of keeping things simple, and for me, it was worth it. I even open-sourced the basic logging structure in my simple FOORIR library for others to use.