Data Model
All four event sources share a single Event table. The eventSource column distinguishes them. Source-specific metadata lives in the properties JSON column.
Field Mapping
TrackedVisitor
TrackedVisitor stores site-scoped profile data separately from analytics events: an opaque externalId, display name, lifecycleStage, and customerSince. First-touch attribution remains derived from the person's earliest pageview, so changing a date range never rewrites acquisition history.
Privacy
BetterMeter is designed from the ground up to respect user privacy. No consent banners needed. GDPR compliant by default.
No cookies
Anonymous tracking uses no cookies or local storage. Fingerprinting remains off unless explicitly enabled.
Explicit identity only
Calling identify() opts that site into storing the supplied opaque ID in local storage so it survives later sessions; reset() removes it. Avoid emails and direct personal data, and apply your own consent requirements.
Hashed identifiers
IP addresses are HMAC-SHA-256 hashed with a server-side visitor secret. The raw IP is never stored. Daily visitor hashes rotate every 24 hours, while a stable per-site visitor hash enables visitor profiles without exposing the original IP.
No automatic PII collection
Analytics events do not automatically collect names, emails, request bodies, or raw IP addresses. Optional profile names and opaque IDs are supplied deliberately by an operator; SDK IDs are hashed by default and sensitive property keys are redacted.
Fire-and-forget
Analytics calls are async and never throw. A network failure silently drops the event. Analytics should never break the host application.
Opt-out
Set disabled: true in the SDK config or BETTERMETER_DISABLED=1 as an environment variable.
Open pipeline
Every event goes through the same processEvent() function. You can audit exactly what is collected and stored.