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

# Variables and context

> Pass app state into flows with SDK context, and read or write a flow's variables at runtime.

Flows are dynamic: a screen can greet the user by name, show a premium-only price, or branch on whether the user has onboarded. That data comes from two places: **SDK context** you pass in, and **variables** the flow defines in the editor. This page covers how the two connect and how to read or write variables from your app.

## SDK context

SDK context is a flat key/value map you provide at [configure](/expo-sdk/configuration) time. It is the bridge between your app's state and a flow's variables, and it also feeds audience targeting.

```tsx theme={null}
FlowPilot.configure({
  apiKey: 'fp_live_...',
  appId: 'your-app-id',
  context: {
    'user.id': 'user_123',
    'user.name': 'Jordan',
    'user.is_premium': false,
    'user.plan': 'free',
  },
});
```

Keys are plain strings, conventionally dot-namespaced (`user.is_premium`) to match how variables reference them. Values can be strings, numbers, booleans, or arrays.

### How context reaches a variable

In the editor, a variable can be sourced from SDK context. Such a variable carries an SDK `path`; when a session initializes, the store reads the context entry whose key equals that `path`. If the context has no matching key, the variable falls back to its constant source, then its default value, then its type's zero value (`''`, `0`, `false`, or `[]`).

So a variable sourced from `user.is_premium` reads `context['user.is_premium']`. The key in your context must match the variable's SDK path **exactly**.

<Note>
  There is no public `updateContext` method on `FlowPilot` in this build, and no per-present context argument. Context is read at configure time and when each session is created. To change identity or attributes (for example after login), call `FlowPilot.configure(...)` again with the new `context` before presenting the next flow. See [Configuration](/expo-sdk/configuration).
</Note>

## Variable value types

A flow variable has one of four types. At runtime, values are one of these TypeScript types:

```ts theme={null}
type VariableTypeName = 'string' | 'number' | 'boolean' | 'list';

type VariableValue =
  | string
  | number
  | boolean
  | string[]
  | number[]
  | boolean[];
```

A `list` variable also declares its item type (`string`, `number`, or `boolean`) in the editor.

## Reading and writing variables at runtime

On the declarative path you hold a `FlowSession`, whose `variableStore` is public. Use it to read or write variables from host code (for example to seed a value before you hand the session to the presenter, or to read the user's choices after completion).

```tsx theme={null}
const session = await FlowPilot.createSession('paywall_main');

// Read
const isPremium = session.variableStore.get('user.is_premium'); // VariableValue | undefined
const all = session.variableStore.getAll();                     // Record<string, VariableValue>

// Write (returns false if the key is unknown or the variable is read-only)
const ok = session.variableStore.set('selected_plan', 'annual');

// Then render <FlowPilotPresenter session={session} /> (the presenter starts the flow).
```

Key methods on `variableStore`:

| Method                        | Returns                         | Notes                                                          |
| ----------------------------- | ------------------------------- | -------------------------------------------------------------- |
| `get(key)`                    | `VariableValue \| undefined`    | Looks up by variable key.                                      |
| `getByLabelOrKey(labelOrKey)` | `VariableValue \| undefined`    | Tries the key, then the human label.                           |
| `getAll()`                    | `Record<string, VariableValue>` | Snapshot of every variable.                                    |
| `set(key, value)`             | `boolean`                       | `false` if the key is unknown or the variable is not writable. |
| `contains(key)`               | `boolean`                       | Whether the variable exists.                                   |
| `interpolate(template)`       | `string`                        | Substitutes `{{var}}` placeholders in a string.                |

<Warning>
  `set(...)` respects the variable's `writable` flag set in the editor. A read-only variable (for example one sourced directly from SDK context) returns `false` and is not changed, with a warning logged. Make the variable writable in the editor if your app needs to mutate it.
</Warning>

## Using variables inside a flow

Most variable use happens inside the flow itself, authored in the editor: a text component shows `Hi {{user.name}}`, a price switches on `user.is_premium`, a condition node branches the navigation. Your app's job is just to supply the context; the editor decides how variables drive the UI.

`{{ }}` placeholders do plain string substitution. To switch a value (not just substitute one) based on a condition, the editor uses a conditional property value, not inline logic.

<Warning>
  `{{ }}` interpolation does string substitution only. There is no ternary or conditional syntax inside `{{ }}`. To switch a value based on a condition, use a conditional property value (case/else against a condition) instead.
</Warning>

See [Variables](/editor/variables) and [Dynamic values](/editor/dynamic-values) for how flow builders author these.

## Identity and the per-install user ID

By default the SDK generates a stable per-install user ID and persists it with `expo-secure-store`, so it survives app restarts. This ID buckets the user into A/B experiments deterministically (the same user always gets the same variant).

To tie activity to your own account ID instead, call `FlowPilot.identify(userId)` after `configure(...)`, ideally before presenting a flow. On logout, call `FlowPilot.reset()` to clear the identity; a fresh anonymous ID and session are created for subsequent activity.

```ts theme={null}
FlowPilot.identify(currentUser.id); // associate events with your account id
// ...later, on sign-out:
await FlowPilot.reset();            // clear identity, start fresh
```

<Note>
  A flow session already in progress keeps the ID it started with; `identify` affects subsequent sessions. If a user appears to switch experiment variants between launches **without** an `identify` call, their stored anonymous ID was reset (a reinstall, cleared secure store, or a different device), not a bug in bucketing.
</Note>

## Common mistakes

* **Context key does not match the variable's SDK path.** The variable reads `context[path]`. A mismatch means the variable silently falls back to its default. Match the keys exactly.
* **Trying to mutate a read-only variable.** `set(...)` returns `false` for a non-writable variable. Mark it writable in the editor.
* **Expecting `updateContext`.** It is not exposed. Re-`configure` to change context for future sessions.
* **Putting logic inside `{{ }}`.** Interpolation is substitution only. Use a conditional property value in the editor to switch values.

## Troubleshooting

* **A `{{user.name}}` placeholder renders empty.** No context entry matched the variable's SDK path, and it had no default. Confirm the context key equals the variable's path, set at configure time.
* **`set(...)` returns `false`.** Either the variable key does not exist in this flow, or it is read-only. Check the editor's variable definition. Enable `logLevel: 'debug'` to see the warning.
* **A user keeps flipping experiment variants.** Their per-install ID is being reset between launches. Test on a persistent device/simulator. See [Reading experiment results](/dashboard/reading-results).

## Related pages

* [Conversions and revenue](/expo-sdk/conversions)
* [Custom components](/expo-sdk/custom-components)
* [Variables (editor)](/editor/variables)
* [Dynamic values (editor)](/editor/dynamic-values)
* [Configuration](/expo-sdk/configuration)
