Why Your Analytics Are Lying to You
GoatCounter says: 72 visitors this week.
My Caddy server logs say: 778 requests from 503 unique IPs.
That's not a small discrepancy. That's a factor of 7.
What Happened
I use GoatCounter for my website analytics. It's privacy-friendly, open source, no cookie banner needed. Perfect for a small project like mine.
But GoatCounter โ like every JavaScript-based analytics tool โ has a fundamental problem: It only counts visitors whose browsers actually execute the JavaScript.
Who's not being counted?
- Anyone with an adblocker (uBlock Origin, Pi-hole, etc.)
- Anyone with JavaScript disabled
- Search engine crawlers
- RSS readers
- CLI tools like
curlorwget - Link previews from messaging apps
The Hard Numbers
Here's my traffic over the last 8 days โ Caddy server logs vs. GoatCounter:
| Date | Caddy (Unique IPs) | GoatCounter | Invisible |
|---|---|---|---|
| Mar 02 | 16 | ~3 | ~81% |
| Mar 03 | 65 | ~8 | ~88% |
| Mar 04 | 146 | ~12 | ~92% |
| Mar 05 | 157 | ~14 | ~91% |
| Mar 06 | 94 | ~10 | ~89% |
| Mar 07 | 132 | ~11 | ~92% |
| Mar 08 | 92 | ~8 | ~91% |
| Mar 09 | 76 | ~6 | ~92% |
On average, I'm seeing only ~9% of my actual traffic in GoatCounter.
Why This Matters
If you're making decisions based on analytics โ and what solo founder isn't? โ you're making them based on maybe 10% of reality.
In my case, looking at GoatCounter alone, I would have thought: "72 visitors per week. Nobody cares." The server logs tell a different story: over 500 different IPs visited my site in 8 days.
Sure, some of those are bots. Crawlers, scanners, the usual suspects. But even if half are bots โ that's still 3-4x more real visitors than GoatCounter shows.
What I Learned
- JavaScript analytics systematically undercount your traffic. I knew this in theory, but I didn't expect a 7-10x gap.
- Server logs are the truth. If you have your own server, Caddy/Nginx logs are the most reliable traffic source. No blockers, no JS issues, every request is captured.
- Use both together. GoatCounter shows you behavior (pageviews, referrers, browsers). Server logs show you the real numbers. The combination is more powerful than either alone.
- Don't give up based on one data source. If I'd only looked at GoatCounter, I might have thought nobody cares about the blog. The server logs show: people are showing up.
My Setup
For the nerds โ here's how I track both:
GoatCounter: A single script tag, self-hosted via Caddy reverse proxy. No cookie banner needed, GDPR-friendly.
Server logs: Caddy writes JSON logs. Once a day I parse them with a small Python script: count unique IPs, bot detection (User-Agent filtering), page ranking.
# The core is this simple
cat access.log | python3 -c "
import json, sys
from datetime import datetime
ips = set()
for line in sys.stdin:
entry = json.loads(line)
ip = entry['request']['client_ip']
ips.add(ip)
print(f'{len(ips)} unique IPs')
"
Not glamorous, but it works.
What This Means for My Experiment
I'm now on day 8. 503 different IPs visited my site โ without me actively promoting it anywhere. No Reddit post, no Hacker News, no Twitter. Just a website on the internet and a few search engines that found it.
That makes me cautiously optimistic. If hundreds of visitors show up without any promotion, what happens when I actually launch?
The answer to that is coming soon. ๐ฆฆ