ZKRINET Docs
Byggblock

Statistik — cookiefri besöksstatistik

På Zkrinet: lägg till blocket under Byggblock i panelen — ett klick, din egen kod rörs inte och en ögonblicksbild tas först. Installationsstegen nedan gäller om du kör PocketBase själv, till exempel efter en export.

Besök, unika besökare, toppsidor, varifrån folk kommer och egna händelser ("Köp klickat") — utan cookies, utan localStorage och utan att IP-adresser sparas. Samma modell som Plausible använder.

Testat mot PocketBase 0.40.4.

Installation

Kopiera pb_hooks/ och pb_migrations/ till din PocketBase och starta om. Samlingen zk_statistik_dagar (aggregaten) dyker upp i adminpanelen.

Ligger PocketBase bakom en proxy (Cloudflare, nginx, Caddy …) måste du ställa in Inställningar → Trusted proxy så att PocketBase ser besökarens riktiga IP — annars ser alla besökare ut som proxyn och räknas som en och samma.

Klistra in i appen

<script>
(function () {
  var URL = "https://din-pocketbase.se/api/zk/statistik/besok"
  function skicka(data) {
    try {
      fetch(URL, { method: "POST", body: JSON.stringify(data), keepalive: true,
                   headers: { "Content-Type": "text/plain" } })   // text/plain = ingen CORS-förfrågan i förväg
    } catch (_) {}
  }
  function sida() { skicka({ sida: location.pathname, referrer: document.referrer }) }
  sida()
  // Appar med egen routing (React/Vue/Svelte): räkna även när adressen byts utan omladdning.
  var push = history.pushState
  history.pushState = function () { push.apply(this, arguments); sida() }
  addEventListener("popstate", sida)
  // Egna händelser: window.zkHandelse("Köp klickat")
  window.zkHandelse = function (namn) { skicka({ sida: location.pathname, handelse: namn }) }
})()
</script>

Snutten sätter ingen cookie, skriver inget i webbläsaren och läser inget därifrån.

Läsa statistiken

GET /api/zk/statistik?fran=2026-10-01&till=2026-10-31     (superuser)

Utan fran/till = de senaste 30 dagarna (UTC). Högst 367 dagar per fråga.

const s = await pb.send("/api/zk/statistik", { query: { fran: "2026-10-01", till: "2026-10-31" } })
// { fran, till, besok, unika,
//   dagar:         [{ dag, besok, unika }],
//   toppsidor:     [{ sida, besok, unika }],          // topp 20
//   toppreferrers: [{ referrer, besok, unika }],      // domän; "(direkt)" = ingen referrer, "(okänd)" = gick inte att läsa
//   handelser:     [{ handelse, antal, unika }] }
  1. Varje dygn (UTC) slumpas ett nytt salt. Det ligger i en intern tabell som inte är en samling och inte nås via API:t.
  2. Besökaren blir SHA-256(dagens salt + IP + User-Agent + värd). IP och User-Agent finns bara i minnet under anropet.
  3. Hashen sparas under dygnet så att samma besökare inte räknas två gånger. Sedan raderas saltet (vid första besöket nästa dygn, och av gallringen varje timme) och hasharna gallras.
  4. Kvar blir bara aggregat: antal per dag, sida, referrer-domän och händelse.

Sparas aldrig: IP-adress, User-Agent, cookies, frågesträngar (?epost=… och #… tas bort från sidans adress), hela referrer-adresser (bara domänen).

PocketBase egen aktivitetslogg sparar som standard IP och User-Agent för varje anrop. Besöksrutten är därför undantagen från loggen ($apis.skipSuccessActivityLog()) och svarar alltid 202, även vid trasig indata, så att den aldrig hamnar där. Testat: efter besök, botar, DNT, trasig indata och takträffar finns besökarens IP och User-Agent inte i någon tabell i data.db eller auxiliary.db.

Vad som inte räknas

Inställningar (miljövariabler)

VariabelStandard
ZK_STATISTIK_TAK300Räknade anrop per besökare och dygn
ZK_STATISTIK_MAX_NYCKLAR2000Olika sidor (och referrers, händelser) per dygn
ZK_STATISTIK_RADATA_DAGAR1Dagar som hasharna sparas (1 = bara i dag). Saltet raderas alltid efter dygnet oavsett.
ZK_STATISTIK_AGGREGAT_DAGAR00 = aggregaten sparas för alltid; annars antal dagar

Gallringen körs varje timme (cron) och kan köras för hand: POST /api/zk/statistik/gallra (superuser).

Juridik — läs det här

Vi är inte jurister. Modellen ovan är samma som Plausible och liknande verktyg bygger på för att slippa samtyckesbanner: ingen information lagras eller läses i besökarens enhet (ePrivacy-direktivets artikel 5.3 — i Sverige lagen om elektronisk kommunikation 9 kap. 28 §), och det som sparas är aggregat som inte går att knyta till en person.

Men var ärlig mot dig själv om två saker:

Bedömningen av om detta räcker för just din tjänst — ePrivacy, GDPR och eventuella nationella regler — ägs av dig som kund. Är du osäker, fråga en jurist.

Begränsningar

Testa

./bank.py statistik

12 tester: samma besökare samma dag = 1 unik (annan IP/webbläsare = ny), nästa dag = ny besökare och gårdagens salt raderat (dagen och saltet manipuleras i databasen), att byte av salt ensamt räcker för en ny hash, att IP och User-Agent inte finns i någon tabell i någon databasfil (med en kontroll som bevisar att sökningen faktiskt ser PocketBase-loggen), DNT/GPC, botar, att bara superuser läser, taket per besökare, sidor/referrers/händelser (frågesträngar bort, intern navigering), datumintervall, gallring av rådata med aggregaten kvar, tak på antal sidor, trasig indata. Skydden är mutantverifierade: varje skydd har brutits med flit och fångats av minst ett test.