Identify customers

Link anonymous purchase history to accounts in your authentication system.

Voidhash creates an anonymous distinct ID on first launch and persists it, so purchases and events work before anyone signs in. If your app has accounts, call identify() after authentication. Access then follows the customer across devices.

Identify after sign-in

Pass a stable identifier from your backend, plus optional profile fields:

try await voidhash.identify(externalUserId: user.id, email: user.email, name: user.name)

Use an opaque, unique ID such as a UUID. Do not use an email address or a sequential database ID as the primary identifier.

When an anonymous customer signs in, Voidhash moves their purchase history and entitlements to the identified person. Events captured before the switch stay attributed to the anonymous identity.

Follow authentication state

Wait until your authentication system has finished loading. Then call identify(user.id) for a signed-in user, or signOut() once sign-out is confirmed. A loading session is not a signed-out session; resetting during startup discards the persisted identity before authentication restores it.

Identity changes are ordered by the SDK, including calls during initialization. Repeating identify() for the same ID without profile changes leaves the session and cached state intact. Switching directly between accounts does not merge them. Events and queued transactions retain the identity that captured them, and purchases retain the identity that started them.

No declarative identity prop, additional provider, or app-side identity queue is needed.

Sign out

Sign out of Voidhash after your own sign-out completes:

await voidhash.signOut()

This records a sign-out event when automatic lifecycle events are enabled, then starts a fresh anonymous identity and session. Shared caches and pending deliveries survive. reset() remains available with the same behavior.

Set customer attributes

Write profile traits for the current person:

try await voidhash.setPersonAttributes([
    "email": .string("ada@example.com"),
    "name": .string("Ada Lovelace"),
    "plan_source": .string("referral"),
])

The SDK writes the traits server-side and returns the updated person.

Attribute values can be strings, numbers, booleans, or nil. email and name map to built-in person fields. Other keys become custom traits.

Read the distinct ID

Read the distinct ID of the current identity, anonymous or identified:

let distinctId = await voidhash.getDistinctId()

This is useful in support logs, and when you correlate a client session with your backend.

Anonymous or identified?

Which setup fits depends on how your app handles accounts.

  • No accounts. Keep the automatically generated anonymous identity.
  • Optional accounts. Let purchases work anonymously, then identify after sign-in.
  • Account required. Identify immediately after restoring your app session.

Next steps