Skip to content

Privacy & data collection

How Statable handles visitor privacy by default, which signals it respects, and what controls you have.

Cookieless by design

Statable doesn't set cookies, doesn't write to localStorage, and doesn't fingerprint browsers. Every page on a site running Statable can ship without a cookie banner in most jurisdictions.

Visitors are counted with a server-side daily hash: SipHash(siteID || ip || user_agent || date). The hash exists only in our database, rotates every UTC midnight, and can't be linked back to a specific person. See Unique visitors for the full mechanic.

Two consequences worth flagging:

  • Visitors are deduplicated within one calendar day, not across days. A reader who returns on three different days counts as three unique visitors.
  • No cross-site tracking is possible — the hash includes siteID, so the same browser visiting two Statable-tracked sites generates two unrelated hashes.

Do Not Track and Global Privacy Control

s.js checks the visitor's privacy signals before sending anything. The script silently does nothing when:

  • navigator.globalPrivacyControl === true — set by Brave, DuckDuckGo Privacy Browser, Firefox (when "Tell websites not to sell or share my data" is enabled), and a growing list of extensions. Required by CCPA in California.
  • navigator.doNotTrack (or window.doNotTrack / navigator.msDoNotTrack) returns '1' or 'yes' — the older DNT spec, still set by some users in browser preferences.

No event request leaves the browser, so the visit doesn't reach our ingest. Nothing to delete later because nothing was collected.

This is enforced in the script itself, not on the server. Honoring the signal at the source is the only way to make the promise honest.

Per-browser opt-out flag

Beyond DNT/GPC, the script also respects an explicit opt-out flag in localStorage:

localStorage.setItem('analytics_ignore', 'true')

When the flag is "true", the script silently does nothing. To re-enable:

localStorage.removeItem('analytics_ignore')

Per-browser only. Switching browser or device requires repeating the step. Useful for:

  • Excluding your own development visits.
  • Letting visitors opt out from a "Don't track me" link in your site's privacy controls.
  • Testing the opt-out flow before publishing it.

For team-wide exclusion (whole office, dynamic IPs that DNT can't catch), use the IP / hostname blocklist below.

IP and hostname blocklist

Site-side controls in Site settings → Blocklist:

  • IP addresses. Drop traffic from specific IPs or CIDR ranges before it's stored. Office IPs, monitoring tools, internal QA.
  • Hostnames. Allowlist the domains where the script is allowed to fire. Anything else is rejected at ingest, useful when staging/preview environments share a data-id with production.

Full mechanics: Blocklist (IPs & hostnames).

What we collect, and what stays out

  • No cookies, no localStorage IDs, no fingerprints. Visitor identity is a server-side daily hash, nothing else.
  • IP used, not stored. The visitor's IP is read once at ingest, fed into the daily-rotating hash, and used to derive country / region / city via Cloudflare's edge geolocation. It's not written to the event row, not surfaced in reports, not exposed through the API.
  • User-Agent parsed, not stored. Raw UA is turned into browser / OS / device buckets at ingest. The buckets land on the event row; the original UA string is dropped on the same path.
  • No PII fields. No emails, names, phone numbers, or account IDs are collected from form submits or the page.
  • No cross-site identity. Each siteID lives in its own hash space, so the same browser visiting two Statable-tracked sites generates two unrelated hashes.
  • No third-party data sharing. Stats stay on Statable's infrastructure. We don't sell, syndicate, or feed them to ad networks.

What you control as the site owner

ControlWhere it livesWhat it does
IP blocklistSite settings → Blocklist → IP addressesDrops traffic from listed IPs / CIDRs at ingest
Hostname allowlistSite settings → Blocklist → HostnamesOnly counts traffic from approved hostnames
Public dashboard toggleSite settings → General → Public AccessWhether anyone with the link can view your stats
Site deletionSite settings → Danger zone → Delete siteWipes every event, goal, property, and setting tied to the site
Account deletionSettings → Preferences → Delete accountWipes every site you own and the account itself

Visitor-side controls (DNT, GPC, opt-out flag) are independent of these — they take effect even if you've configured nothing.

Compliance notes

Statable is built so most teams can run analytics without a cookie banner under GDPR, ePrivacy, CCPA, and equivalents. The combination of cookieless tracking, daily-rotating hashes, IPs and User-Agents that don't reach storage, and respected DNT/GPC signals is the technical basis for that posture.

What's still on you:

  • A short privacy-policy line stating you use Statable for aggregate, cookieless analytics.
  • A region-specific assessment if your industry has stricter rules (healthcare, financial services, kids under 13).
  • Honoring deletion / access requests for any custom events or properties you chose to send (e.g. logged-in user IDs in prop_*).

For deeper background on the underlying laws, the Privacy & Compliance encyclopedia walks through GDPR, CCPA, lawful basis, consent, and related concepts.


Ready to take control of your web analytics? Try Statable free for 30 days — no credit card required, full feature access, GDPR-compliant by default. Start your free trial or view a live demo.