shortkit uses a two-phase identity model that enables personalization from the first session while supporting cross-device engagement for authenticated users.
How identity works
Phase 1: Anonymous
On first SDK initialization:
SDK generates a unique device ID (UUID v4)
All engagement events are keyed to this anonymous ID
Feed personalization begins immediately based on device-level signals
Phase 2: Identified
When your app authenticates a user:
You call setUserId() with your app’s user identifier
SDK sends an identity resolution event to the backend
Anonymous device engagement merges with the identified profile
Future events are keyed to the identified user
Implementation
Setting user identity
Call setUserId() when your user authenticates:
iOS
Android
React Native
Web
// When user logs in
func handleLogin ( user : User) {
// Your authentication logic
authenticateUser (user)
// Associate identity with shortkit
shortkit. setUserId (user. id )
}
// When user logs in
fun handleLogin (user: User ) {
// Your authentication logic
authenticateUser (user)
// Associate identity with shortkit
shortkit. setUserId (user.id)
}
// When user logs in
async function handleLogin ( user : User ) {
// Your authentication logic
await authenticateUser ( user );
// Associate identity with shortkit
shortkit . setUserId ( user . id );
}
// When user logs in
async function handleLogin ( user : User ) {
// Your authentication logic
await authenticateUser ( user );
// Associate identity with shortkit
shortkit . setUserId ( user . id );
}
Clearing identity
Call clearUserId() when the user logs out:
iOS
Android
React Native
Web
func handleLogout () {
// Your logout logic
clearSession ()
// Clear shortkit identity
shortkit. clearUserId ()
}
fun handleLogout () {
// Your logout logic
clearSession ()
// Clear shortkit identity
shortkit. clearUserId ()
}
function handleLogout () {
// Your logout logic
clearSession ();
// Clear shortkit identity
shortkit . clearUserId ();
}
function handleLogout () {
// Your logout logic
clearSession ();
// Clear shortkit identity
shortkit . clearUserId ();
}
When clearUserId() is called:
A new anonymous device ID is generated
The identified profile remains intact for future logins
New engagement starts fresh on the anonymous profile
Choosing a user ID
Requirements
The user ID must be:
Unique : One ID per user within your organization
Persistent : Same ID across sessions and devices
Stable : Doesn’t change over user lifecycle
Recommendations
Good identifiers
Database primary key (user_12345)
UUID (550e8400-e29b-41d4-a716-446655440000)
Hashed email (sha256:abc123...)
Avoid
Raw email addresses (PII)
Phone numbers (PII)
Session tokens (not persistent)
Sequential IDs (guessable)
Never pass personally identifiable information (PII) as the user ID. Use an opaque identifier from your system.
Example user IDs
// Good: Database ID
shortkit . setUserId ( "user_12345" );
// Good: UUID
shortkit . setUserId ( "550e8400-e29b-41d4-a716-446655440000" );
// Good: Hashed email (if you must use email)
const hashedEmail = await sha256 ( user . email . toLowerCase ());
shortkit . setUserId ( `email: ${ hashedEmail } ` );
// Bad: Raw email
shortkit . setUserId ( "[email protected] " ); // Don't do this
Identity resolution
When setUserId() is called, the backend performs identity resolution:
What happens
Lookup : Check if the user ID exists in the system
Merge : Link the anonymous device profile to the identified user
Consolidate : Merge engagement history from anonymous session
Engagement merging
Anonymous session data is merged into the identified profile:
Watch history
Topic affinities
Interaction patterns
This means:
Users don’t “start over” when they log in
Personalization is continuous
Cross-device engagement combines
Multiple devices
When the same user logs in on multiple devices:
Each device’s anonymous session merges on login
Engagement history combines across devices
Feed personalization reflects all device activity
User switching
If a user logs out and a different user logs in:
// User A logs out
shortkit . clearUserId ();
// User B logs in
shortkit . setUserId ( "user_b_id" );
What happens:
clearUserId() generates a new anonymous ID
User A’s profile is preserved (not deleted)
User B’s setUserId() triggers identity resolution
Feed now reflects User B’s preferences
Anonymous-only mode
If your app doesn’t have user authentication, shortkit works entirely in anonymous mode:
Each device gets a unique identifier
Personalization is device-level only
No cross-device engagement tracking
Still provides meaningful personalization
You don’t need to call any identity methods; anonymous mode is the default.
Privacy considerations
Data stored
For each user profile, shortkit stores:
User ID (your identifier)
Linked device IDs
Topic affinities (computed from engagement)
Engagement statistics (aggregate metrics)
shortkit does not store:
Personally identifiable information (unless you pass it as user ID)
Authentication credentials
Raw engagement event logs (beyond retention period)
Data subject requests
For GDPR/CCPA compliance:
Export user data:
curl -X POST https://api.shortkit.dev/v1/users/{userId}/export \
-H "Authorization: Bearer sk_live_your_secret_key"
Delete user data:
curl -X DELETE https://api.shortkit.dev/v1/users/{userId} \
-H "Authorization: Bearer sk_live_your_secret_key"
See Data export guide for details.
Troubleshooting
Identity not persisting
Symptom : User preferences reset on app restart
Causes :
setUserId() not called after app restart
User ID changing between sessions
Solution : Call setUserId() on every app launch when user is authenticated:
// On app startup
if ( isUserLoggedIn ()) {
shortkit . setUserId ( currentUser . id );
}
Anonymous engagement not merging
Symptom : User’s pre-login engagement doesn’t affect personalization
Causes :
setUserId() called before SDK initialization
Multiple SDK instances
Solution : Ensure SDK is initialized before calling setUserId():
// Correct order
shortkit . initialize ({ apiKey : '...' , config : { ... } });
// Later, when user logs in
shortkit . setUserId ( user . id );
Next steps