Skip to content

feat(audience): add persistent device_id that survives logout#801

Merged
nattb8 merged 1 commit into
mainfrom
feat/sdk-538-device-id
Jun 24, 2026
Merged

feat(audience): add persistent device_id that survives logout#801
nattb8 merged 1 commit into
mainfrom
feat/sdk-538-device-id

Conversation

@nattb8

@nattb8 nattb8 commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

Players who log out and back in were previously unrecognisable to the CDP — their anonymousId rotated on logout, severing the link to prior session history. This PR adds a deviceId UUID that solves that: it is stable across logins and logouts, only cleared when the player fully opts out of tracking.

deviceId is generated once on first init (at Anonymous+ consent), stored alongside anonymousId in the on-device identity file, and sent on every event. On logout (Reset()), anonymousId rotates as before but deviceId is preserved. On opt-out (SetConsent(None)), both are wiped. This matches the PostHog / Amplitude model of a stable device-level ID alongside a rotating user-level ID.

The identity file format migrates from the legacy plain-string UUID to JSON {"anonymousId":"...","deviceId":"..."} transparently on first read — the existing anonymousId is preserved and a fresh deviceId is generated.

Test plan

  • deviceId is non-null and non-empty at Anonymous and Full consent
  • deviceId is null at None consent, no file written
  • deviceId differs from anonymousId (distinct UUIDs)
  • deviceId is stable across multiple calls in the same session
  • deviceId persists across a simulated restart (cache clear + reload from disk)
  • deviceId survives Reset() (logout); anonymousId rotates
  • deviceId is wiped by SetConsent(None) (opt-out)
  • deviceId is present on track, identify, and alias events at Anonymous+ consent
  • deviceId is absent from events when consent is None
  • Legacy plain-string identity file is migrated: anonymousId preserved, deviceId generated, file rewritten to JSON
  • Migrated identity survives a cache-clear + reload (round-trip verified)

Closes SDK-538

@nattb8 nattb8 requested review from a team as code owners June 24, 2026 08:09
A new deviceId UUID is generated on first init and stored alongside
anonymousId in the identity file. Unlike anonymousId, it is not rotated
on Reset() (logout) — only wiped on SetConsent(None) (opt-out).

This lets the CDP reconnect a returning player to their prior session
history even after logout, matching the PostHog/Amplitude pattern of
a stable device-level ID alongside a rotating user-level ID.

The identity file migrates transparently from the legacy plain-string
format to JSON {"anonymousId":"...","deviceId":"..."} on first read.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@nattb8 nattb8 force-pushed the feat/sdk-538-device-id branch from 5f70796 to d7c1b6f Compare June 24, 2026 08:18
@nattb8 nattb8 merged commit 303280e into main Jun 24, 2026
39 checks passed
@nattb8 nattb8 deleted the feat/sdk-538-device-id branch June 24, 2026 23:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

2 participants