Idunworks Issue #01
I can has lingo?

Giving my tracker a country column without making it fat

Admin
Author

What this is about. I run my own small, cookieless analytics tracker, Muntra, on all the sites I host. You should probably too. Its dashboard has had a Countries table since day one, and it has been empty since day one, because nothing ever filled it in. This is the short story of filling it in.

Why. If you roll your own analytics, country is the first thing people ask for. It is also where "privacy-friendly" quietly turns into "we know which town you live in". I wanted the first without the second.

The brief

My one rule for Muntra is that it stays small. So I put it to my AI like this:

"The Muntra tracker should be kept minimalistic and fast, so weigh pros and cons. Is there anything else a tracker would need?"

The code already had a column, a daily rollup and an API for countries. The only missing piece was a TODO(geo) comment in the request handler. So this was one lookup, not a project.

MaxMind or DB-IP?

I also asked Gemini, who said what everyone says: MaxMind GeoLite2 is the industry standard, and DB-IP Lite is easier to automate. So I asked:

"DO we need thextra ummph in GeoLite2?"

No. GeoLite2's edge is at city level, and I only store the country. At country level they agree on nearly every address. The ones either gets wrong are mostly VPN and corporate-proxy users, and no database can place those. DB-IP Lite needs no account and no license key, so there is no new secret to keep on the server. Both use the same file format, so switching later means swapping one file, not the code.

The numbers

  • One country file, about 8 MB, loaded into memory and refreshed monthly by a cron job.

  • About 215 nanoseconds per lookup, next to a Redis write that already happens on every page view. Nobody will feel it.

  • The visitor's IP is still thrown away right after it is turned into a daily, salted hash. Muntra stores the two-letter country and nothing finer.

There was one subtle bit. The library normally maps the file into memory, and you have to close an old copy when a new month's file arrives. Close it while a request is still mid-lookup and the process crashes. Reading the whole file into memory instead means old copies are simply cleaned up by the garbage collector once nobody uses them. It costs 8 MB of RAM and removes a whole class of bug.

Google's DNS lives in Canada

I wanted to test against the real file, not just a toy one. That was worth it twice:

  1. The library's integrity check is "stricter than the spec", so a perfectly usable vendor file could have failed it, leaving geo switched off without anyone noticing. The real DB-IP file passed, in 0.3 seconds.

  2. My test said Google's public IPv6 DNS address is in the US. DB-IP says Canada. Neither is wrong: that address is served from many countries at once, so there is no single answer. The test now checks for a valid country code, not my guess.

What happened, and how else you could do it

Problem: an empty Countries table. Fix: a country-only lookup from a free, monthly IP database, hot-reloaded without a restart, with an "IP geolocation by DB-IP" credit on the dashboard as the license asks.

Other ways to get a country:

Approach

Better at

Costs

MaxMind GeoLite2

The standard, refreshed weekly, best at city level

An account, a license key on the server, license terms about deleting old copies

Browser time zone (Europe/Stockholm → SE)

No IP processing at all, nothing to download

It is a device setting, not a location, and some countries share a zone

Your CDN's country header

Free, no code

Only if you run behind that CDN. I don't.

City-level data

Prettier maps

On a small site, town plus browser plus day is close to naming the visitor. Not for a privacy-first tracker.

Rule of thumb: store the coarsest location that answers your question. For "where do my readers come from", that is the country.

Log in to like this article, or create an account .
0 reads

Comments

Log in to post comments. Log in
No comments yet. Be the first to comment.