Docs/Privacy·
.md

How Shipabase counts visitors without cookies or stored IPs

What the SDK sends, how visitors are counted, and what you should never send.

What is stored in the browser#

Nothing. No cookies, localStorage, sessionStorage or IndexedDB. The session ID lives in memory only.

What the SDK sends#

The event name, your props, and coarse system info: locale, time zone, OS name and version, browser engine and major version, app version, SDK version, a debug flag, the page path (never the query string; IDs become :id on the server), and the traffic source of the page load (the utm_source parameter, or the referring site’s host, never a full URL). Visits from AI assistants such as ChatGPT, Perplexity or Claude are recognized automatically.

How visitors are counted#

IP addresses and User-Agents are never stored or logged. For each request, the server uses them for a moment to derive a country and an anonymous visitor ID, then discards them. The visitor ID is computed exactly like this:

visitor ID
visitor_id = sha256(salt + app_id + ip + user_agent).hexdigest()[:16]
  • salt is 32 random bytes (64 hex characters) generated on the server, one per calendar day, the same for every app. It is never sent to the browser and never stored with events.
  • The day is the visitor’s local day, taken from the time zone the SDK sends (UTC if there is none). The same visitor keeps the same ID from their midnight to the next, then gets a new one, so visitors can’t be followed from one day to the next.
  • Each salt expires at 00:00 UTC two days after its day starts, once that day has ended in every time zone, and is then deleted. Without the salt, nobody can recompute a hash or link it back to an IP.
  • app_id is your app’s internal ID: the same person gets unrelated IDs in two different apps.
  • Only the first 16 hex characters (64 bits) of the SHA-256 digest are kept.
  • Over 7, 30 or 90 days, a visitor who comes back on another day counts again.

Stored, not stored, derived then discarded#

DataStatusDetails
IP addressDerived then discardedUsed for the visitor ID, the country and an in-memory rate limit (keyed by a non-reversible hash), then dropped. Never written to the database or logs.
User-AgentDerived then discardedUsed for the visitor ID, to filter bots, and for OS and browser engine when the SDK didn’t send them. Never stored.
Time zoneDerived then discardedOnly picks the visitor’s local day, and so the salt. Never stored.
Daily saltNot stored with eventsKept server-side, apart from events, and deleted about two days later.
Visitor IDStored16 hex characters, valid for one local day in one app.
CountryStoredTwo-letter code, looked up from the IP in a local GeoIP database (no third-party call).
Session IDStoredGenerated in memory by the SDK (start time plus a random suffix). Never written to the device.
EventStoredEvent name, your props, page path, traffic source, locale, OS, browser engine, app and SDK version, debug flag.
Cookies, localStorage, device IDsNot storedNothing is written to the visitor’s device.
Query string, hash, full referrer URLNot storedOnly the path and the referring host (or utm_source) are sent.

For the product-level overview, see the privacy page.

Nothing is stored on the visitor’s device, so this setup typically needs no cookie banner under the GDPR and ePrivacy rules. You stay responsible for what you send: keep props anonymous and Shipabase stays anonymous too. See Props & privacy.