feat(audience): add persistent device_id that survives logout#801
Merged
Conversation
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>
5f70796 to
d7c1b6f
Compare
bkbooth
approved these changes
Jun 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Players who log out and back in were previously unrecognisable to the CDP — their
anonymousIdrotated on logout, severing the link to prior session history. This PR adds adeviceIdUUID that solves that: it is stable across logins and logouts, only cleared when the player fully opts out of tracking.deviceIdis generated once on first init (at Anonymous+ consent), stored alongsideanonymousIdin the on-device identity file, and sent on every event. On logout (Reset()),anonymousIdrotates as before butdeviceIdis 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 existinganonymousIdis preserved and a freshdeviceIdis generated.Test plan
deviceIdis non-null and non-empty at Anonymous and Full consentdeviceIdis null at None consent, no file writtendeviceIddiffers fromanonymousId(distinct UUIDs)deviceIdis stable across multiple calls in the same sessiondeviceIdpersists across a simulated restart (cache clear + reload from disk)deviceIdsurvivesReset()(logout);anonymousIdrotatesdeviceIdis wiped bySetConsent(None)(opt-out)deviceIdis present on track, identify, and alias events at Anonymous+ consentdeviceIdis absent from events when consent is NoneanonymousIdpreserved,deviceIdgenerated, file rewritten to JSONCloses SDK-538