Skip to content

Conversation

@garretto
Copy link

Summary

This PR adds support for distinct user IDs in the umIdentify() composable, addressing issue #138.

Umami v2.18.0+ supports identifying users with distinct IDs for tracking across sessions. The official tracker supports three function signatures:

  • umami.identify(id) - ID only
  • umami.identify(id, data) - ID with session data
  • umami.identify(data) - Data only (current behavior)

This PR implements all three signatures while maintaining full backward compatibility.

Changes

src/types.ts

  • Added optional id?: string field to IdentifyPayload interface

src/runtime/composables.ts

  • Added module-level identity variable to store distinct ID (matching official Umami tracker implementation)
  • Updated umIdentify() to accept (idOrData?: string | EventData, sessionData?: EventData)
  • Store identity when string ID is provided
  • Modified getPayload() to automatically include id in all subsequent events (pageviews, custom events)
  • Updated JSDoc with examples for all three usage patterns
  • Maintained backward compatibility - existing umIdentify(data) calls work unchanged

Implementation Details

This implementation matches the official Umami tracker's approach:

  • Identity stored in module closure variable (not localStorage)
  • Automatically included in all event payloads after identify() is called
  • Persists for the browser session (plugin re-establishes on page load)
  • Client-side only (respects existing SSR guards)

Usage Examples

// ID only (new)
umIdentify('user@example.com')

// ID with data (new)
umIdentify('user@example.com', { name: 'John', plan: 'pro' })

// Data only (existing - still works)
umIdentify({ name: 'John', plan: 'pro' })

Testing

Tested in production with user authentication flows:

  • ✅ Login identification with email as distinct ID
  • ✅ Session data (userId, name) attached correctly
  • ✅ Distinct ID automatically included in all subsequent events
  • ✅ Logout clears identity
  • ✅ Backward compatibility with data-only calls
  • ✅ TypeScript types are correct
  • ✅ No lint or build errors

Example payloads:

Identify call:

{"type":"identify","payload":{"id":"user@example.com","data":{"userId":"123","name":"John"},...}}

Subsequent event (auto-includes ID):

{"type":"event","payload":{"id":"user@example.com","name":"button-click",...}}

Fixes

Closes #138

🤖 Generated with Claude Code

garretto and others added 3 commits November 16, 2025 10:02
Support all 3 Umami identify signatures:
- umIdentify(id) - ID only
- umIdentify(id, data) - ID with session data
- umIdentify(data) - Data only (backward compatible)

Fixes ijkml#138

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unable to set distinct id

1 participant