Skip to content

fix(js-sdk): identify user on init when userId is present#1331

Open
jagannalla wants to merge 2 commits into
jitsucom:newjitsufrom
jagannalla:fix/1250-sdk-initial-userid
Open

fix(js-sdk): identify user on init when userId is present#1331
jagannalla wants to merge 2 commits into
jitsucom:newjitsufrom
jagannalla:fix/1250-sdk-initial-userid

Conversation

@jagannalla
Copy link
Copy Markdown

Summary

This PR fixes Jitsu Issue #1250 where the browser JS SDK parsed the userId from HTML script data-attributes (data-user-id or window.jitsuConfig.userId) into the configuration object but never automatically registered the user state or sent it with early events on startup.

Root Cause

In libs/jitsu-js/src/browser.ts, script attributes successfully parsed data-user-id into getConfiguration().userId. However, in libs/jitsu-js/src/index.ts's createUnderlyingAnalyticsInstance(), the SDK never checked for opts.userId during startup, leading to:

  1. jitsu.page() and early events being fired without the user ID.
  2. jitsu.user().id (via jitsu.getState()) returning undefined until a manual identify() was called.

Changes Made

  1. Type Definitions: Added userId?: string option to JitsuOptions in types/protocols/analytics.d.ts for first-class type safety.
  2. Auto-Identification Logic:
    • Pre-set __user_id inside the storage wrapper right before the underlying analytics package instantiates, allowing client.user().id to return the configured ID synchronously on startup.
    • Automatically trigger a.identify() during SDK startup to dispatch the identify payload to the server.
  3. Unit Tests: Added a robust test suite test auto-identification on init inside libs/jitsu-js/__tests__/node/nodejs.test.ts verifying all scenarios (configuration storage, user state population, auto-triggering identify dispatch, and automatic attachment to subsequent track events).

Verification

Ran the unit test suite inside an isolated Docker container:

  • All 12 unit tests passed with 100% success (duration: 13.29s).

Closes #1250

jitsu-code-review[bot]
jitsu-code-review Bot previously approved these changes Jun 1, 2026
Copy link
Copy Markdown

@jitsu-code-review jitsu-code-review Bot left a comment

Choose a reason for hiding this comment

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

Reviewed the JS SDK init-userId change in libs/jitsu-js/src/index.ts, the new node test coverage, and the JitsuOptions type update. I found two actionable issues worth addressing: one around unhandled promise rejection risk on init-time auto-identify, and one around user state/privacy/reset behavior when opts.userId is backfilled in user().

Comment thread libs/jitsu-js/src/index.ts Outdated
if (opts.privacy?.disableUserIds || opts.privacy?.dontSend) {
storage.reset();
} else if (opts.userId) {
a.identify(opts.userId);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

a.identify(opts.userId) returns a Promise, but this call is fire-and-forget. With errorPolicy: "rethrow", send() can throw on network/non-OK responses, which makes this an unhandled rejection during SDK initialization. Can we await/catch this (or explicitly void ...catch(...)) so init-time auto-identify doesn’t introduce unhandled async errors?

Comment thread libs/jitsu-js/src/index.ts Outdated
},
user() {
const u = analytics.user();
if (u && !u.id && opts.userId) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Question: should this fallback ignore privacy/reset state? Right now it re-injects opts.userId into client.user().id even after storage.reset() or when privacy.disableUserIds is enabled, so callers can still observe an ID even though IDs were disabled/cleared.

@jagannalla
Copy link
Copy Markdown
Author

Thanks for the review. I've pushed a new commit addressing both points:

  1. Unhandled Rejection: Added an autoIdentify option flag to the startup identify call so that initialization-time failures are caught and logged as warnings instead of throwing process-crashing rejections under errorPolicy: "rethrow".
  2. Privacy/Reset Leak: Updated the user() fallback method to return a copy of the state instead of mutating in-place, and added checks to ensure the initial userId is not returned if reset() is called or if privacy flags are enabled.

Added corresponding unit tests for these cases and verified that the entire test suite passes. Let me know if everything looks good!

Copy link
Copy Markdown

@jitsu-code-review jitsu-code-review Bot left a comment

Choose a reason for hiding this comment

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

Reviewed the changes between f0efd99 and 6e25078 in jitsu-js (analytics plugin, SDK init path, typings, and added Node tests).\n\nI focused on correctness around auto-identification initialization, privacy/reset behavior, and async error handling for identify/track/page calls. I did not find actionable bugs or regressions in the current diff.

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.

userId not POSTed despite existing in config

2 participants