Skip to content

Conversation

@rahul-mixpanel
Copy link

Allow customers to provide their own device_id at SDK initialization instead of the SDK auto-generating a UUID.

Key features:

  • New MixpanelOptions.Builder.deviceId(String) method to set custom ID
  • Custom device_id is preserved across reset() calls
  • Validates IDs: rejects null, empty, or '$' prefix (falls back to UUID)
  • SDK still prepends "$device:" for distinct_id (matching current behavior)
  • Raw custom ID sent as $device_id in events

Files changed:

  • MixpanelOptions.java: Added deviceId field and builder method
  • PersistentIdentity.java: Added custom ID storage, validation, and preservation
  • MixpanelAPI.java: Wired options.getDeviceId() in constructor
  • CustomDeviceIdTest.java: Added instrumented tests for all scenarios

🤖 Generated with Claude Code

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for custom device IDs at SDK initialization, allowing customers to provide their own device identifiers instead of relying on auto-generated UUIDs.

Changes:

  • Added MixpanelOptions.Builder.deviceId(String) method for setting custom device IDs at initialization
  • Implemented validation logic to reject null, empty, or '$'-prefixed IDs with fallback to UUID generation
  • Enhanced PersistentIdentity to preserve custom device IDs across reset() calls

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
MixpanelOptions.java Added deviceId field and builder method to accept custom device IDs
PersistentIdentity.java Implemented validation, storage, and preservation logic for custom device IDs
MixpanelAPI.java Wired custom device ID from options during SDK initialization
CustomDeviceIdTest.java Added comprehensive test coverage for custom device ID scenarios

Comment on lines 292 to 294
// Preserve custom device ID if one was set
String preservedCustomId = mHasCustomDeviceId ? mCustomDeviceId : null;
boolean hadCustomId = mHasCustomDeviceId;
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable preservedCustomId can be null when mHasCustomDeviceId is false, making the null check on line 304 redundant. Consider simplifying by only preserving if mHasCustomDeviceId is true, or clarify the intent of the dual condition.

Copilot uses AI. Check for mistakes.
Allow customers to provide their own device_id at SDK initialization
instead of the SDK auto-generating a UUID.

Key features:
- New MixpanelOptions.Builder.deviceId(String) method to set custom ID
- Custom device_id is preserved across reset() calls
- Validates IDs: rejects null, empty, or '$' prefix (falls back to UUID)
- SDK still prepends "$device:" for distinct_id (matching current behavior)
- Raw custom ID sent as $device_id in events

Files changed:
- MixpanelOptions.java: Added deviceId field and builder method
- PersistentIdentity.java: Added custom ID storage, validation, and preservation
- MixpanelAPI.java: Wired options.getDeviceId() in constructor
- CustomDeviceIdTest.java: Added instrumented tests for all scenarios

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@rahul-mixpanel rahul-mixpanel force-pushed the feature/custom-device-id branch from bb1ad8d to 3e1e0ad Compare January 12, 2026 07:27
rahul-mixpanel and others added 2 commits January 12, 2026 13:06
Address PR review comment: clarify the behavior when setCustomDeviceId()
is called after identities have already been loaded. The custom ID will
be stored but only takes effect after the next clearPreferences() call.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Address PR review comment: simplify the redundant conditional logic.

Changes:
- Remove ternary conditional that was confusing
- Unconditionally save and restore custom device ID state
- Add clearer comment explaining why we preserve these in-memory fields
- Use 'final' for local variables to indicate they won't change

The previous code had a redundant check (hadCustomId && preservedCustomId != null)
since preservedCustomId would be null when hadCustomId was false. The new code
unconditionally preserves and restores the state, which is simpler and equally safe.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
this.superProperties = builder.superProperties;
this.featureFlagsEnabled = builder.featureFlagsEnabled;
this.featureFlagsContext = builder.featureFlagsContext;
this.deviceId = builder.deviceId;
Copy link

@ketanmixpanel ketanmixpanel Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

customDeviceId would suit better here?

*
* @return The custom device ID, or null
*/
public String getDeviceId() {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in iOS getAnynomousId returns the device id. Check if there is need of creating new getter

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.

3 participants