URL: https://docs.dixa.io/docs/dixamessenger/web/flow-variables

# Flow variables

Flow variables let your website pass information about a visitor into Dixa Messenger, such as an order id or the contents of a cart. Your Messenger flows can use the values in messages, conditions and HTTP requests, and Mim, Dixa's AI agent, can use them in its actions.

There are two kinds of flow variables. Use token variables for any value your flow has to trust, such as an API token for the user.

|                             | Browser variables                                                                                           | Token variables                                                                         |
| --------------------------- | ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| Set with                    | the `flowVariables` option of [`init`](https://docs.dixa.io/docs/dixamessenger/web/interfaces/initpayload.md#flowvariables), or `updateFlowVariables` | the `flow_variables` claim of a [JWE token](https://docs.dixa.io/docs/dixamessenger/web/authentication.md#generating-a-jwe-token) |
| Visitors                    | all, anonymous ones included                                                                                | verified users                                                                          |
| The visitor can change them | yes                                                                                                         | no: your backend creates and encrypts the token                                         |
| Same key in both            | loses                                                                                                       | wins                                                                                    |
| Values reach the flow       | HTML-escaped                                                                                                | as sent                                                                                 |

Passing browser variables with `init`:

```ts
_dixa_.invoke('init', {
  messengerToken: '[YOUR_MESSENGER_TOKEN]',
  flowVariables: {
    orderId: 'A-1002',
    cart: { items: [{ sku: 'X1', qty: 2, price: 19.95 }], total: 39.9 },
    isReturning: true,
  },
});
```

Passing token variables, as part of the payload you encrypt (see [Generating a JWE token](https://docs.dixa.io/docs/dixamessenger/web/authentication.md#generating-a-jwe-token)):

```ts
const payload = {
  jti: '123e4567-e89b-12d3-a456-426614174000',
  iat: 1516239022,
  email: 'example@email.com',
  name: 'John Doe',
  flow_variables: {
    member_tier: 'gold',
    api_session_token: '...',
  },
};
```

## Using variables in a flow

Every variable is available under the key you sent, and your flow can't tell which kind it is, so read [Security](#security) before a step relies on one. With the `init` example above:

- `{{scope:orderId}}` in a message prints `A-1002`.
- `{{scope.cart.items[0].sku}}` prints `X1`. Text inside `{{ }}` that doesn't start with `scope:` or `system:` is read as a CEL expression, which is how you reach inside objects and arrays. `{{scope:cart}}` prints the whole object as JSON.
- In a condition, use CEL: `scope.isReturning == true` or `scope.cart.total > 30.0`.

The variables are written when a conversation starts, before the first step of the flow runs. They share the scope with the variables your flow creates, so if the flow sets a variable with the same name, the flow's value replaces the one you sent for the rest of the conversation. Pick names your flow doesn't use, unless you want your value to act as a starting value.

## Updating variables

- `updateFlowVariables` replaces the browser variables at any time, without restarting the messenger and without changing the visitor's identity. Pass the whole set every time: the new map replaces the old one, and `{}` clears it. See the [`updateFlowVariables` command](https://docs.dixa.io/docs/dixamessenger/web/commands.md#updateflowvariables-payload) and the [promise-based method](https://docs.dixa.io/docs/dixamessenger/web/promisebasedapi.md#updateflowvariablespayload-recordstring-flowvariablevalue-promisevoid).

  ```ts
  _dixa_.invoke('updateFlowVariables', { orderId: 'A-1003', isReturning: true });
  ```

- Calling `init` again with `flowVariables` also replaces them, and calling it without the option keeps them.
- `purgeUserIdentity` clears them, and so does `setUserIdentity` with `{ type: 'anonymous' }`, which purges the identity.
- Token variables come from the latest valid token the messenger received, with `init` or `setUserIdentity`. A new token replaces all of the previous token's variables, and a token without the `flow_variables` claim clears them, so include the claim in every token you create.
- When a key is set both ways, the token's value wins.
- Changes reach conversations that start afterwards. A conversation that is already open keeps the values it started with.

## Values and limits

- A value can be any JSON value: a string, number, boolean, null, array or object. There is no limit on the number of variables.
- A key starts with a letter from a to z, upper or lower case, followed by any number of those letters, digits and underscores. `orderId` and `member_tier` work; `order-id`, `2fa` and `størrelse` don't.
- Numbers are stored as decimals. In CEL, `scope.visits + 1` fails, so write `scope.visits + 1.0`. Messages print whole numbers without decimals. Numbers must be between `Number.MIN_SAFE_INTEGER` and `Number.MAX_SAFE_INTEGER`, JavaScript's safe integer range, so send larger ids as strings.
- A variable set to `null` isn't stored, and neither is an object field set to `null`. A value with `null` inside an array is ignored as a whole.
- Values can be nested up to 64 levels deep.
- An object or array can be up to 102,400 characters of JSON, counted with its numbers written as decimals (`2` counts as `2.0`). For browser variables, the count is taken after HTML escaping. Strings, numbers and booleans have no size limit of their own.
- The message that identifies the visitor to Dixa, including a verified user's token, must fit in 32,768 bytes. When it doesn't, the messenger leaves out browser variables from the end of the map until it fits. `updateFlowVariables` has a 32,768-byte budget of its own.
- The messenger checks browser variables against the key, number, nesting and size rules: it leaves out one that breaks a rule, names its key in the console and still starts. Dixa checks token variables and the `null` rules itself, and leaves out a variable that fails without telling the browser.
- Browser variables reach your flows HTML-escaped: `&`, `<`, `>`, `"` and `'` become entities, so `M&S` arrives as `M&amp;S`. That makes them safe to show in a message, but a condition has to compare against the escaped text. Token variables arrive exactly as you sent them.
- If a conversation's browser and token variables together are too large for the internal message that starts its flow, the conversation starts without them.

## Security

Anyone who can load your website can set browser variables, verified users included. Use them as inputs, such as ids and locales, and never to decide what a visitor may see or do.

Pass a value your flow has to trust as a token variable, such as the order id a flow uses to look up order details, and include it in every token you create: the visitor can't change it, and it wins over a browser variable with the same key. Before a step uses it, check that `{{system:auth_level}}` is `verified`, because without a verified token every variable is a browser variable. Otherwise, the API your flow calls has to check that the value belongs to the user.

## Lifetime

Flow variables belong to the messenger session. Every conversation that starts in the session gets them, and they aren't saved on the contact the way contact custom attributes are.

## Availability

Messenger automations can't read flow variables.
