Identify users

By default, the widget treats every visitor as anonymous. Call identify to tell UserJot who the current user is. Their feedback, votes, and messages are then tied to their account.

Basic identification

uj.identify({
  user: {
    id: 'user-123',
    email: 'ada@example.com',
    firstName: 'Ada',
    lastName: 'Lovelace',
    avatar: 'https://example.com/avatar.jpg'
  }
});

user.id is required. Use a stable ID from your own system, like your database user ID. Do not use values that can change, like an email address or a display name.

Everything else is optional, but email is strongly recommended. It makes the identity easier to reconcile across UserJot surfaces.

When to call identify

Call identify once your app knows who the user is, usually right after your session loads. Calling it again with the exact same input is safe; the SDK skips the duplicate call as long as that session is still live. Once the session expires, the same input triggers a fresh call. Changing anything in the payload, including traits or email, always sends a fresh call, and a different user switches the session to that user.

When the user logs out of your app, call logout:

uj.logout();

A typical pattern:

if (user) {
  uj.identify({
    user: {
      id: user.id,
      email: user.email,
      firstName: user.firstName,
      lastName: user.lastName
    }
  });
} else {
  uj.logout();
}

Adding traits

Traits are custom attributes you attach to a user. They show up alongside the user in your dashboard and help you understand who is asking for what.

uj.identify({
  user: {
    id: 'user-123',
    email: 'ada@example.com',
    traits: {
      plan: 'pro',
      seats: 12,
      trialing: false
    }
  }
});

Trait values can be strings, numbers, booleans, or null.

Adding companies

If your product is B2B, you can attach the user's companies:

uj.identify({
  user: { id: 'user-123', email: 'ada@example.com' },
  companies: [
    {
      id: 'acme',
      name: 'ACME Inc.',
      domain: 'acme.com',
      traits: { plan: 'enterprise' }
    }
  ]
});

id is required for each company. Use a stable ID from your own system.

What identify returns

identify returns a promise with the result:

const result = await uj.identify({
  user: { id: 'user-123', email: 'ada@example.com' }
});
 
result.viewer;        // the identified user, or null
result.identityTrust; // 'signed' or 'unsigned'
result.warnings;      // anything the server ignored or adjusted

Check warnings during development. For example, if you send a field the server does not support, the warning tells you which one.

Identity and conversations

If Conversations is enabled, identity changes how the Messages surface behaves:

  • Identified users skip the visitor-details prompt entirely. Replies from your team reach them at their account email.
  • Anonymous visitors get guest conversations scoped to their browser, with optional contact capture depending on your widget settings.

One subtlety: if your workspace requires signed tokens, an unsigned identify does not work at all. The server rejects it with HTTP 403, the promise rejects with an IDENTIFY_FAILED error, and nothing from the call is applied — the visitor stays anonymous, with no prefilled contact details. Use signed identity to attach conversations to verified accounts.

Verified identity

A plain identify call is unsigned. It comes from the browser, so it can be tampered with. That is fine for many products, but if you want UserJot to trust the identity, or you want to require it, have your server sign the identity as a JWT.

That is covered in Signed identity.