VoidhashDocs
DevelopersHelp centerGuidesAPI reference
Dashboard
Get started
Introduction
Quickstart
How Voidhash works
Glossary
Versions and releases
Concepts
Teams, projects and environments
API keys
Products and perks
Offers
Subscription lifecycle
People and identity
Events
Features
Paywalls in your app
Feature flags and A/B tests
Paywall components
Push notifications
Ad attribution in your app
Client SDKs
React Native
Swift
Kotlin
Web
Your backend
Node.js
PHP
Go
Rust
Other languages
Payment sources
Forward store notifications
Developer tools
CLI
MCP server
Query analytics with VoidQL

Events

What Voidhash records for analytics, which events are built in, and how to choose which ones a project stores.

An event is one thing a person did or that happened to them, recorded for analytics, such as opening the app, viewing a paywall or finishing a checkout. Analytics reports, funnels, A/B test results and alerts are all built from events.

Every event has:

FieldMeaning
eventThe name, such as $app_opened or checkout_started.
propertiesFlat key-value data about this event.
distinct_idThe distinct ID of the person it belongs to.
timestampWhen it happened, by the device clock.
uuidA unique ID. An event resent with the same uuid is stored once.
session_idThe session it happened in, when the SDK knows it.

Voidhash corrects each timestamp for the device's clock offset and clamps it to at most 24 hours before and 5 minutes after the event arrives.

Built-in events

Names starting with $ are reserved for events the SDKs and Voidhash record on their own.

EventRecorded whenSent by
$app_installedThe app launches for the first time after installMobile SDKs
$app_updatedThe app launches for the first time after a version changeMobile SDKs
$app_openedThe app cold-startsMobile SDKs
$app_backgroundedThe app moves to the backgroundMobile SDKs
$app_became_activeThe app returns to the foregroundMobile SDKs
$app_crashedThe app crashed; sent at the next launch, without a stack traceMobile SDKs
$screenA screen is viewedMobile SDKs
$pageviewA page is viewedWeb SDK
$pageleaveA page is leftWeb SDK
$outbound_clickA link to another site is clickedWeb SDK
$sign_outThe person signs outAll SDKs
$push_openedA push notification sent through Voidhash is openedMobile SDKs
$paywall_viewedA paywall is shownPaywalls
$paywall_purchase_startedA purchase starts from a paywallPaywalls
$paywall_close_interceptedA paywall's close was interceptedPaywalls
$experiment.exposedA person is assigned an A/B test variantVoidhash
$purchase.*, $subscription.*Revenue: purchases, renewals, cancellations, refunds and moreVoidhash
$setPerson attributes changeAll SDKs
$identifyAn anonymous ID is linked to a user ID; needs $previous_distinct_idEvent capture API

Mobile SDKs are Swift, Kotlin and React Native. Revenue events come only from Voidhash's own records of store events; the same names sent from a client are dropped.

Custom events

Record your own events for anything the built-in ones don't cover:

await voidhash.capture("checkout_started", properties: ["plan": .string("pro_monthly")])
voidhash.capture("checkout_started", mapOf("plan" to "pro_monthly"))
voidhash.client.capture("checkout_started", { plan: "pro_monthly" });
voidhash.track("checkout_started", { plan: "pro_monthly" });
  • Use snake_case names in the form object-action, such as checkout_started, and keep them stable: reports match names exactly.
  • Don't start a name with $. The SDKs send it, but Voidhash drops it.
  • Property values are strings, numbers, booleans or null.
  • Never put personal data you don't need, such as passwords or payment details, in properties.

Sessions

A session groups a person's events from one visit. It ends after 30 minutes without activity, and a new one starts on sign-out. On the web, tabs of the same site share a session.

How events reach Voidhash

  • Client SDKs queue events and send them in batches of 20, every 5 seconds, holding at most 1,000 events; the oldest are dropped first when the queue is full. See the analytics page of Swift, Kotlin, React Native or Web.
  • Your backend sends events with a server library or the event capture API, up to 100 events and 5 MB per request. Reuse an event's uuid when you retry, so it is stored once.

Each event lands in the environment of the key that sent it: a test key records test events, and a production key records production events, including those from store sandbox builds.

Consent

While analytics consent isn't granted, the SDKs collect no events, screens or attributes and drop any still queued. Purchases, access checks, identify, feature flags and paywalls keep working. Set consent with setAnalyticsConsent; see your SDK's analytics page and Web privacy.

Choose which events to store

Each project decides which events it stores, under Settings → Events in Studio:

  • Built-in events can be turned off one by one or by group, such as Revenue. Turning off Revenue stops all revenue, subscription and churn reporting, and turning off experiment exposure breaks A/B test results.
  • Custom events are all stored unless you block a name, such as checkout_started.

On Voidhash Cloud every built-in event is on by default. Self-hosted projects start with only $app_installed, Revenue and $set on. Changing the policy needs an admin or owner; from the terminal, use voidhash events policy (view, enable, disable, block, unblock), or the MCP tools get_ingest_policy and set_event_ingest.

Rejected events are gone

Voidhash drops a turned-off or blocked event when it arrives and counts it in the request's rejected total; the request still succeeds, so SDKs don't retry it. An event already in processing when you change the policy is rejected with the reason policy_rejected. Dropped events aren't stored and can't be recovered.

Check that events arrive

voidhash events tail follows a project's events live from the terminal, and Studio lists the latest ones under Activity → Analytics events. Studio's Data health page shows missing and rejected events; Event capture lists the limits and every rejection reason.

Next steps

  • Check your data: find missing and rejected events.
  • People and identity: how events join a person.
  • Track events from your SDK: Swift, Kotlin, React Native or Web.
  • Event capture API: send events from your backend.

Something wrong or missing on this page? Tell us by email or on Discord.

PreviousPeople and identityNextPaywalls in your app

On this page

Built-in eventsCustom eventsSessionsHow events reach VoidhashConsentChoose which events to storeCheck that events arriveNext steps