When users interact with your app anonymously, you see disconnected events. When you identify users, those events connect into a journey:Anonymous tracking:
Set the user ID once, and all future events include it:
Copy
// When user logs ingrain.setUserId('user_123');// All these events now belong to user_123grain.track('dashboard_viewed');grain.track('report_generated');grain.track('settings_updated');
const grain = createGrainAnalytics({ tenantId: 'your-tenant-id', userId: 'user_123'});// Events immediately track with this user IDgrain.track('app_opened');
This is convenient when you know the user ID upfront, like in server-side code or after authentication.
The SDK doesn’t persist user IDs automatically. When the page reloads, you need to set it again:
Copy
// On app load, restore user from your auth systemconst currentUser = getCurrentUser(); // Your auth logicif (currentUser) { grain.setUserId(currentUser.id);}
Why not persist automatically? User sessions are managed by your authentication system (Auth0, Firebase, etc.). Grain follows your lead instead of duplicating session logic.
You can track users anonymously first, then identify them later:
Copy
// Anonymous trackinggrain.track('landing_page_viewed');grain.track('signup_button_clicked');// User signs up - now identify themgrain.setUserId('user_123');// Identified trackinggrain.track('account_created');
Events before identification remain anonymous. Only events after setUserId() are associated with the user.