TL;DR

/* ------------------------------------------------------ */
/*          Collect `name` and `email` from users         */
/* ------------------------------------------------------ */

const options = {
token: '<TOKEN>'
collectUserData: true,
};

The Long Version

Collecting User Data

If you want to support non-logged-in users, this is the way to go.

Setting collectUserData to true will prompt the user to input a name and email before proceeding to chat.

Since any user can input any email, the user is considered non-verified and only has access to previous chats that were created on their device.

const options = {
  token: '<TOKEN>'
  collectUserData: true,
};

Programmatically Passing User Data

If your user is logged-in and you have their details, you can programmatically send user data in one of two ways:

From the Client/Browser

This method is sufficient in most cases, but is still considered non-verified because malicious users can intercept outgoing requests and impersonate someone else.

Any customData sent in this method will be saved as non_verified_custom_data so that it can be used with caution.

Similar to other non-verified methods, the user only has access to previous chats that were created on their device.

function getUserData() {
  // Your own logic to get the user data
}
const user = getUserData();

const options = {
  token: '<TOKEN>',
  user: {
    data: {
      name: user.name,
      email: user.email,
      avatarUrl: user.avatarUrl,
      customData: user.customData,
    },
  },
};

Server to Server

This is the only truly secure way of authentication; User data are sent from your server to ours, we save that data and give you back a token that can be used in the widget config.

Since this is a verified method, the user has access to all previous chats regardless of which device they were created on, as long as they were created through this verified method.

For more details on what also can be passed when authenticating a user, see the API reference.

/* ----------------------- Backend ---------------------- */
async function getOpenCXUserWidgetToken() {
  const response = await axios.post(
    'https://api.open.cx/widget/authenticate-user',
    {
      email: 'john@doe.com',
      name: 'John Doe',
      avatar_url: 'https://example.com/avatar.png',
      phone: '+1234567890',
      language: 'en',
      custom_data: {
        org_id: 'org_185938572649',
        vip: true,
        // ...
      },
    }
  )
  return response.data.token;
}

/* ---------------------- Frontend ---------------------- */
const userToken = // Call your backend and get the token you got from us

const options = {
  token: '<TOKEN>',
  user: {
    token: userToken,
  },
};

Anonymous (No Authentication)

This could only be useful if you do not care who your users are, or if you’re testing the widget.

Naturally, the user only has access to previous chats that were created on their device.

// Explicitly assigning `undefined` to `user`
const options = {
  token: '<TOKEN>'
  user: undefined
};

// Or simply omit the `user` property
const options = {
  token: '<TOKEN>',
};

Workspace Management

If you support multiple workspaces—in your dashboard or website—per user, you can pass the user’s workspace id. This way, sessions will be scoped by that externalId.

This works regardless of the authentication method you use (verified or non-verified).

const externalId = `${user.id}-${user.company.id}`;
// Or
const externalId = user.company.id;
// Or any other unique identifier for a workspace

/* ---------------- Server-to-Server Auth --------------- */
const options = {
  token: '<TOKEN>',
  user: {
    token: userToken,
    externalId: externalId,
  },
};

/* ------------------ Client-Side Auth ------------------ */
const options = {
  token: '<TOKEN>',
  user: {
    externalId: externalId,
    data: {
      name: user.name,
      email: user.email,
      avatarUrl: user.avatarUrl,
      customData: user.customData,
    },
  },
};