Contactar con soporte

Respondemos por correo, normalmente en dos días.

Google reCAPTCHA revisa este envío frente a abusos; se transmiten datos a Google. El script se carga solo al abrir el formulario.

← Todas las entradas

Counting without a cookie

A visitor counter has one awkward job: it has to tell two visits apart. If it cannot, then one person reloading a page ten times looks like ten people, and the number on your site is fiction.

The usual solution is a cookie. This site does not use one. Here is what it does instead, and why the honest version of that sentence took some work to earn.

The cookie nobody asked for

Until this year, every request to the counter started a PHP session. That is one line of code, it looks harmless, and it meant that every visitor to every site using a Stats4U counter received a session cookie — set by us, on your page, without either of us intending it.

The session was never used for anything. The proof was easy to find once anyone looked: the directory where sessions are stored contained zero files. It had been setting a cookie on other people's websites, for years, to hold data that was never written and never read.

It is gone from the counting path. A session is now started only when someone creates or reconfigures a counter — an action they took deliberately, on this site.

What replaced it

Visitors are told apart by a hash. Five things go in:

  • the IP address
  • the user agent
  • the counter ID
  • today's date
  • a secret that changes every day

Out comes 16 bytes, which is what gets stored. It is kept for two days and then deleted. The IP address itself is never written down at any point.

Two visits from the same person on the same day to the same counter produce the same 16 bytes, so the second one is recognised as a repeat. Tomorrow the same person produces something completely different, because the date and the secret have both changed. That is the whole mechanism.

Why the secret rotates

This is the part that is easy to get wrong, and it was wrong here until this year.

The old version used one permanent secret. That still produced different hashes for different people, which sounds fine. But it meant that anyone holding that secret could take a suspected IP address and recompute its hash for any day in the archive — turning a table of anonymous 16-byte values back into a record of who visited what, going back as far as the data went.

The secret now changes daily and the old ones are deleted after two days. Once that has happened the calculation cannot be run any more, by anybody. That includes whoever runs this site, which is the point: a protection that depends on the operator's good behaviour is not a protection, it is a promise.

The screen resolution, and a lesson about deleting things

Screen resolution used to be collected. It is a classic fingerprinting signal and it was not worth what it cost, so it was taken out of the script that runs on your page.

That was not enough, and the reason is worth knowing if you build anything for other people's websites. The script is served with a cache lifetime of seven days, so old copies stayed live in visitors' browsers for a week after the change. Worse, some sites do not link to the script at all — they pasted a copy of it into their own pages years ago, and that copy will keep doing exactly what it did on the day it was pasted, forever.

So the resolution kept arriving. The fix was to make the server refuse the value, regardless of who sends it. Removing a data collection from the client only stops new clients. Removing it from the server stops it immediately.

Check it yourself

None of this is worth much as an assertion, so here is the command:

  • curl -sk -D - -o /dev/null 'https://www.stats4u.net/index.php?action=pic&s4uid=1' | grep -i set-cookie

No output means no cookie was set.

One closing caution, the same one as always: this describes what the software does. Whether it satisfies the rules that apply to you, where you live, is a question for somebody qualified to answer it, and this is not that answer.