Statistik: Zähler statt Protokoll, deshalb ohne Einwilligung
"Wieviel wann wo wie die Seite benutzt" - naheliegend wäre ein Analysewerkzeug gewesen, das eine Einwilligung braucht und damit genau die Besucher verliert, die ablehnen. Also andersherum: eine Messung, die niemanden wiedererkennt. Gespeichert wird ein Zähler je (Tag, Stunde, Pfad, Status, Verweis-Domain), kein Datensatz je Aufruf. Keine IP-Adresse, keine Kennung, kein Cookie - auch nicht gehasht, denn der Hash einer IP-Adresse bleibt ein Personenbezug. Ein Test liest die Spaltenliste der Tabelle und vergleicht sie mit dieser Zusage, damit sie beim nächsten Ausbau nicht unbemerkt fällt. Vom Verweis bleibt nur der Host: die volle Adresse kann einen Suchbegriff oder einen Namen tragen. Gezählt wird auf kernel.terminate, nach der Antwort - die Messung darf keine Anfrage verlangsamen, und ein Fehler beim Zählen kostet einen Zähler, nicht eine Seite. Nur GET auf HTML mit 200 oder 404; Verwaltung, Assets, Feed, Sitemap und Einwilligungsseite sind ausgenommen, erkennbare Maschinen über ihre Kennung. Das ist eine Heuristik, deshalb heißt die Zahl auf dem Bildschirm nicht "Besucher". Erfundene Crawler-Adressen laufen gesammelt unter (sonstige), sonst wächst die Tabelle mit jedem geprobten Pfad. Die Diagramme zeichnet der Server als SVG mit Klassen statt Stilattributen: kein Diagrammwerkzeug, kein Skript, und die Richtlinie bleibt streng. Die Zahlen stehen zusätzlich in einer Tabelle, weil ein Balken für einen Screenreader nichts ist. Was die Zahlen nicht sagen, steht auf dem Bildschirm: Aufrufe statt Besucher, keine Verweildauer, keine Absprungrate, kein Klickweg, kein Land. Das ist die Folge der Entscheidung, nicht eine Lücke. Aufbewahrung: nach 60 Tagen werden die Stunden eines Tages verschmolzen, nach 425 Tagen gelöscht - gut ein Jahr, damit der Vorjahresmonat vergleichbar bleibt. cms:stats:prune macht beides und gehört in einen Cronjob. 279 PHP-Tests / 1119 Assertions unter PHP 8.2.12 und 8.4.22, axe auf zwölf Verwaltungsbildschirmen ohne Verstöße. Dabei kam eine PHP-8.4-Verwarnung zu fputcsv() heraus, jetzt mit ausdrücklichem Escape-Parameter. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ee446f1ea1
commit
99bad61179
18 files changed
+858
-7
No files matched your search
@@ -419,3 +419,23 @@ Umut: „datenschutz und Impressum einbauen sind keine option“. Richtig – in
|
||||
- Beide werden **von jeder Seite verlinkt**, aus dem Template und nicht aus dem Fußbereich. Der Fußbereich ist ein frei bearbeitbares Blockdokument; ein Pflichtlink, den man versehentlich löschen kann, ist kein Pflichtlink. Die Links liegen mit dem Link „Einwilligung ändern“ in einem benannten Landmark – loser Text außerhalb aller Landmarks ist auch das, was axe zu Recht beanstandet.
|
||||
|
||||
Eine Pfadangabe wird beim Speichern geprüft: zeigt sie auf eine Seite, die es nicht gibt, wird sie abgewiesen.
|
||||
|
||||
## ADR 034 – Statistik: Zähler statt Protokoll (12.09.2026)
|
||||
|
||||
Umut wollte wissen, „wieviel wann wo wie die Seite benutzt“ wird. Die naheliegende Lösung – ein Analysewerkzeug einbinden – hätte eine Einwilligung gebraucht, und damit hätte die Messung genau die Besucher verloren, die ablehnen. Also andersherum gebaut: eine Messung, die niemanden wiedererkennt und deshalb keine Einwilligung braucht.
|
||||
|
||||
**Gespeichert wird ein Zähler, kein Datensatz je Aufruf.** Eine Zeile je `(Tag, Stunde, Pfad, Status, Verweis-Domain)`, die hochgezählt wird. Es gibt keine Spalte, aus der eine Person hervorgeht: keine IP-Adresse, keine Kennung, kein Cookie – **auch nicht gehasht**, denn der Hash einer IP-Adresse bleibt ein Personenbezug. Ein Test prüft die Spaltenliste der Tabelle gegen genau diese Zusage, damit sie beim nächsten Ausbau nicht unbemerkt verletzt wird.
|
||||
|
||||
Vom Verweis bleibt nur der Host. Die vollständige Adresse, aus der jemand kam, kann einen Suchbegriff, einen Namen oder ein Token tragen – die wird nicht gespeichert.
|
||||
|
||||
**Gezählt wird nach der Antwort**, auf `kernel.terminate`: die Messung darf keine Anfrage verlangsamen, und ein Fehler beim Zählen darf keine Seite zerstören. Ein Ausfall kostet einen Zähler, nicht eine Seite. Gezählt werden nur GET-Anfragen auf HTML mit Status 200 oder 404; Verwaltung, Assets, Feed, Sitemap und die Einwilligungsseite sind ausgenommen.
|
||||
|
||||
**Erfundene Adressen laufen gesammelt.** Ein 404 behält seine Adresse nur, wenn sie aussieht wie eine Adresse dieser Website. Crawler probieren tausende Pfade wie `/wp-admin/setup-config.php`; jeder würde sonst eine eigene Zeile bekommen. Alles andere wird zu `(sonstige)`.
|
||||
|
||||
**Maschinen werden über die Kennung ausgeschlossen, und das ist eine Heuristik.** Wer sich als Browser ausgibt, wird mitgezählt. Die Zahl heißt deshalb „Aufrufe, die sich nicht als Maschine gemeldet haben“ – so steht es auch auf dem Bildschirm, weil eine Zahl mit falschem Namen schlimmer ist als eine fehlende.
|
||||
|
||||
**Die Diagramme zeichnet der Server** als SVG mit Klassen statt Stilattributen. Kein Diagrammwerkzeug, kein Skript, und die Richtlinie bleibt unangetastet – die Verwaltung verbietet Inline-Stile, ein Test prüft, dass im SVG keines steht. Die Zahlen selbst stehen zusätzlich in einer Tabelle, denn ein Balken ist für einen Screenreader nichts.
|
||||
|
||||
**Der Preis steht auf dem Bildschirm.** Aufrufe statt Besucher, keine Verweildauer, keine Absprungrate, kein Klickweg, kein Land. Das ist keine Lücke, sondern die Folge der Entscheidung: all das braucht Wiedererkennung. Wer es braucht, braucht eine Einwilligung – die Gruppe `statistics` dafür gibt es schon, sie wäre dann ein eigener Baustein.
|
||||
|
||||
**Aufbewahrung:** nach 60 Tagen werden die Stunden eines Tages zu einer Zeile verschmolzen, nach 425 Tagen wird gelöscht. Gut ein Jahr, damit ein Vergleich mit dem Vorjahresmonat möglich bleibt. `cms:stats:prune` macht beides und ist für einen Cronjob gedacht.
|
||||
Reference in new issue
Block a user