> ## Documentation Index
> Fetch the complete documentation index at: https://docs.botbrains.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Identify Users

> Learn how to identify, annotate, and manage user data securely

botBrains keeps track of your users by default. You can annotate additional user data via the Web SDK. New data will always overwrite old data.

<Note>
  We store phone numbers in E.164 (+4915168433056), but allow common variations such as +49 30 12345678 or +1 (415) 555-2671 for the input
</Note>

## Annotate Users

```javascript theme={null}
$botbrains.push(["set", "user.data", {
	first_name: "Liam",
	last_name: "van der Viven",
	email: "liam@botbrains.io",
	phone: "+4915168433056"
}]);
```

## Arbitrary Data

You can also annotate custom values with the `external_attributes` JSON. By default we merge external attributes, keeping unset values, to deactivate merging the top level keywords set `merge_external_attributes` to `false`

<Warning>
  The total JSON size of external\_attributes must be below 8KB.
</Warning>

```javascript theme={null}
$botbrains.push(["set", "user.data", {
	first_name: "Liam",
	last_name: "van der Viven",
	email: "liam@botbrains.io",
	phone: "+4915168433056",
	external_attributes: {
		"plan": "basic",
		"joined_on": "2024-01-01"
	},
	merge_external_attributes: true // default
}]);
```

## Session Continuity

A session allows users to retrieve their past conversations.

By default, botBrains enables **session continuity** within the **same browser** and **all subdomains**. This means botBrains will still identify a user who goes to your landing page on `www.acme.com` and then signs into `app.acme.com` as the same user.

You can opt-in to **cross device session continuity** by manually the user via the `user.identify` action in the SDK.

## User Identification

<Warning>
  User Identification must be implemented correctly on your part. Make sure to read the Security section to learn how.
</Warning>

```javascript theme={null}
$botbrains.push(["do", "user.identify", ["user_01234567890", {
	first_name: "Liam",
	last_name: "van der Viven",
	email: "liam@botbrains.io",
	phone: "+4915168433056",
	external_attributes: {
		"plan": "basic",
		"joined_on": "2024-01-01"
	}
}]]);
```

The `user_01234567890` key here is what we call the `external_id` of a user. Two users with the same `external_id` will be able to reach each others conversations.

### 🚨 Security 🚨 - READ THIS

<Warning>
  Not following these recommendations make the conversations of your users vulnerable to impersonation. botBrains does not take responsibility for misconfigured systems.
</Warning>

Since we allow you to explicitly set if users are the same or different and thus retrieve sensitive information such as past conversations, we need to be careful in choosing the `external_id`. You have two options:

1. **User-Specific Secret**

   Generate a random id, store it with your user, and send it to your frontend. Don't use or leak this anywhere.

2. **Verified User ID (✅ Recommended)**

   Possibly known ID that's added with a signature of a shared secret of your back end and the botBrains Platform.

## User-Specific Secret

You associate your user with a unique identifier (e. g. UUID) that other users should never know. Your app commonly leaks User Ids when it supports Teams, Collaborates, Share Links, and other features, so your `user_id` is usually a **bad choice.**

**Insecure External Ids are:**

* timestamps
* email
* phone
* serial identifiers (e. g. user id 38992)
* any text shorter than 16 characters (the system rejects these)

**Good External Ids are:**

* UUIDs
* anything with large entropy

### Verified User Id

<Tip>
  ✅ Recommended
</Tip>

Alternatively, we suggest you use user verification. User Verification works by signing the values you pass to the SDK on a back-end server and passing it through your frontend into the Web SDK.

The signature is the HMAC, that's the hash of your user identifier and a shared secret known to your back-end servers and the botBrains platform.

* We will share the verification secret with you on request, this is currently not expose through our platform

<Warning>
  The **Verification Secret** must never be sent to the frontend. The hash **must** be computed on the back end and send to the frontend, which invokes the Web SDK.
</Warning>

Below you will find example code of the business logic your back-end server needs to perform.

<Accordion title="Python">
  ```python theme={null}
  import hmac
  import hashlib

  def generate_hmac(secret_key: str, user_id: str) -> str:
      key = secret_key.encode()
      message = user_id.encode()

      hmac_digest = hmac.new(key, message, hashlib.sha256).hexdigest()
      return hmac_digest

  secret_key = "your_secret_key"
  user_id = "user_123456789"
  external_id_signature = generate_hmac(secret_key, user_id)
  print(secret_key, "+", user_id, "HMAC:", external_id_signature)
  ```
</Accordion>

<Accordion title="JavaScript Node">
  ```javascript theme={null}
  const crypto = require("crypto");

  function generateHmac(secretKey, userId) {
      return crypto.createHmac("sha256", secretKey).update(userId).digest("hex");
  }

  const secretKey = "your_secret_key";
  const userId = "user_123456789";
  const externalIdSignature = generateHmac(secretKey, userId);
  console.log(secretKey, "+", userId, "HMAC:", externalIdSignature);
  ```
</Accordion>

<Accordion title="PHP">
  ```javascript theme={null}
  function generate_hmac($secret_key, $user_id) {
      return hash_hmac('sha256', $user_id, $secret_key);
  }

  $secret_key = "your_secret_key";
  $user_id = "user_123456789";
  $external_id_signature = generate_hmac($secret_key, $user_id);
  echo "$secret_key + $user_id HMAC: $external_id_signature\n";
  ```
</Accordion>

On the client, you then call `user.identify` with `external_id_signature`. Note that we expect the hex-encoded version of the resulting 32 bytes of HMAC, totaling 64 characters.

```javascript theme={null}
$botbrains.push(["do", "user.identify", ["user_123456789", {
	first_name: "Liam",
	last_name: "van der Viven",
	email: "liam@botbrains.io",
	phone: "+4915168433056",
	external_attributes: {
		"plan": "basic",
		"joined_on": "2024-01-01"
	},
	// NEW!
	external_id_signature: "88dddece03a2ac2b6d724287cb2d6ca6de79c0e3428e6b75c510676262157649"
}]]);
```

Contact support [support@botbrains.io](mailto:support@botbrains.io) if you need help computing the HMAC in other programming languages.

## Verifying email and phone

You can also verify the email and phone of a user, using the same HMAC procedure shown above, just using the `email` and `phone` values instead of the `user_id`.

<Accordion title="Python">
  ```javascript theme={null}
  import hmac
  import hashlib

  def generate_hmac(secret_key: str, user_id: str) -> str:
      key = secret_key.encode()
      message = user_id.encode()

      hmac_digest = hmac.new(key, message, hashlib.sha256).hexdigest()
      return hmac_digest

  secret_key = "your_secret_key"
  phone = "+4915168433056"
  email = "liam@botbrains.io"
  phone_signature = generate_hmac(secret_key, phone)
  email_signature = generate_hmac(secret_key, email)
  print(phone_signature, email_signature)
  ```
</Accordion>

```javascript theme={null}
$botbrains.push(["do", "user.identify", ["user_123456789", {
	email: "liam@botbrains.io",
	phone: "+4915168433056",
	// ...
	phone_signature: "be9b0317ab56c0a76cc6dd16881f257704c5276ce440ac3307cf579dc5d7826b",
	email_signature: "d3763347cb7669fc04ff76cac2907cd5e3e0c12a560a1bf67b4baab8af2dad74"
}]]);
```

### Finish

We're happy to help you setup verified users, contact [support@botbrains.io](mailto:support@botbrains.io) to schedule a quick meeting.
