Besucher zählen ohne Cookies und ohne JavaScript
- Matt
Dieser Blog ist eine statische Jekyll-Seite. Ich wollte wissen, welche Beiträge überhaupt gelesen werden, aber ohne Analysedienst, ohne Cookie-Banner und ohne JavaScript. Herausgekommen ist ein Zähler aus drei Teilen, der seit dem Sommer läuft.
Ein Pixel, ein Skript, eine Datei
Jede Seite bindet am Ende ein 1x1-Pixel ein, die eigene Adresse steht als Parameter dabei:
<img src="/counter.php?p=/2026/10/beispiel.html" alt="" width="1" height="1">
counter.php erhöht ein paar Zähler in einer JSON-Datei und liefert immer das gleiche transparente GIF aus. Die Datei liegt neben dem Webroot, nicht darin, damit der Deploy sie nicht löscht. Gezählt wird nur, was in einer beim Build erzeugten Liste aller Seiten steht. Sonst könnte jeder mit erfundenen Adressen die Datei aufblähen. Eine Sperre per flock verhindert, dass zwei gleichzeitige Aufrufe die Datei zerlegen.
Gespeichert werden ausschließlich Zahlen: je Seite, je Tag, je Stunde, mobil oder Desktop. Keine IP-Adresse, keine Browserkennung, kein Cookie. Wer Do Not Track oder Global Privacy Control sendet, wird gar nicht gezählt.
Ein Teil der Leser waren Bots
Die ersten Zahlen sahen erfreulich aus. Auffällig war nur, wie gleichmäßig sie verteilt waren: Fast jede Seite hatte mindestens acht Aufrufe, auch Seite 24 der Übersicht, die kein Mensch freiwillig ansteuert. Dazu kamen Tage mit dem Zehnfachen des Üblichen, ohne neuen Beitrag. Das waren Crawler, die Bilder mitladen.
Inzwischen sortiert der Zähler jeden Aufruf im Moment des Abrufs ein, ohne die Kennung zu speichern:
- Gibt sich der Abruf als Bot oder Werkzeug zu erkennen (
bot,crawl,curl,pythonund ähnliche), zählt er als Bot. - Fehlen die Merkmale eines Browsers, der ein Bild lädt, gilt er als verdächtig. Aktuelle Browser schicken dabei
Sec-Fetch-Dest: image, ältere zumindest einenAccept-Header mitimage/. - Nur alles andere landet in den Seitenzahlen.
Bots und Verdächtige werden nur pro Tag gezählt. So sieht man trotzdem, wie groß der Anteil ist.
Der Haken
Ehrlich gesagt beantwortet so ein Zähler weniger, als man hofft. Woher jemand kommt, sieht ein Pixel nicht: Dessen Referrer ist die eigene Seite, für die echte Herkunft bräuchte es JavaScript. Wiederholte Aufrufe derselben Person sind von verschiedenen Personen nicht zu unterscheiden, das ist der Preis dafür, nichts zu speichern. Und wer sich als Browser ausgibt und alle Header korrekt setzt, wird als Mensch gezählt.
Für meine eigentliche Frage reicht es trotzdem: Welche Beiträge werden gelesen? Überraschend oft nicht die neuesten .NET-Themen, sondern ältere Texte mit eigener Erfahrung. Wie der Blog gebaut wird, kam schon bei der Frage nach einem eigenen GitHub-Runner vor. Was genau gezählt wird, steht in der Datenschutzerklärung. Die Header für Fetch Metadata erklärt MDN, das Signal GPC die Spezifikation.