What Is a Page Variable?
A page variable is a named, typed slot of in-memory state that belongs to a single page. Blocks on the page bind to it, actions change it, and it exists only while the visitor is on that page.
Page variables are the page-scoped tier of the variable system. See Variables Overview for how page scope compares to app scope.
Creating and Configuring a Variable
Create variables from the builder's Data panel (or Explorer panel) alongside data sources and functions. Each variable requires:
Give it a name: A human label shown in the builder and used in auto-named references. Must be unique within the page's variable namespace. Renaming does NOT change the ID — ID-based bindings survive a rename.
Choose a type: One of five lowercase types:
string,number,boolean,object,array. The type is not cosmetic — it determines which operations are available when writing.Set an initial value (optional): The value the variable starts with when the page opens. Always stored as a string — the runtime converts it to the declared type at load time. Use Save & Run to evaluate and preview the result.
Stored Configuration Shape
A page variable is stored as an entry in page.properties.pageVariables — an ID-keyed map. Here is the shape of a real entry:
JSON — a boolean page variable
{ "id": "var_DSBrc", "name": "show_pan", "type": "boolean", "createdTime": 1750196246281, "initialValue": "false" }
Field Reference
| Field | Required | Description |
| id | Required (required) | Stable handle, var_ + random suffix. Bindings reference this ID, never the name. The platform assigns it — never invent one. |
| name | Required (required) | Human label shown in the builder. Must be unique within the page. Renaming does NOT change the id. |
| type | Required (required) | One of the five type strings (lowercase). Decides which setPageVariable operations are legal. |
| createdTime | Required (required) | Epoch-ms number. Stamped at creation. Not read by bindings. |
| initialValue | Optional (optional) | A STRING seed evaluated at page load. Omitted means the variable starts as undefined. |
| parentId | Optional (optional) | Optional folder ID for organizing variables in the builder's left-panel tree. Organizational only — no effect on runtime or bindings. |
Initial Value Contract
initialValue is always stored as a string — even for number, boolean, object, and array variables. At page load it is evaluated once:
| Type | Initial Value String | Result |
| string | "false" | The text "false" (used as-is) |
| number | "42" | The number 42. Non-numeric → undefined. |
| boolean | "true" or "false" | The boolean true or false (case-insensitive). Any other non-empty string is truthy. |
| object | "{'status':'new'}" | Parsed as JSON (or JS-style). Must yield a plain object or → undefined. |
| array | "[1, 2, 3]" | Parsed as JSON (or JS-style). Must yield an array or → undefined. |
| any | "{{ ds_config['data'] }}" | Expression evaluated at page load, result coerced to the declared type. |
Reading a Page Variable
Variables are exposed in the binding scope under their ID, with the current value nested under ['value']:
Reading in binding expressions
// Read the variable's value {{ var_DSBrc['value'] }} // Use in a visibility condition // property: {{ var_DSBrc['value'] }} operator: EQUAL value: true // Call setValue directly from a script or function {{ var_DSBrc.setValue(true) }}
Writing a Page Variable
Writes go through the setPageVariable action. The available operations depend on the declared type:
Operations by Type
| Type | Operation | Effect |
| string | SET | Replace the value |
APPEND | Concatenate value to the end | |
PREPEND | Concatenate value to the beginning | |
| number | SET | Replace the value |
INCREMENT_BY | Add value to the current number | |
DECREMENT_BY | Subtract value from the current number | |
| boolean | SET | Replace with true or false |
TOGGLE | Flip to the opposite value | |
| object | SET | Replace the entire object |
MERGE | Shallow-merge provided keys into the current object | |
REMOVE_PROPERTY | Delete a key from the object | |
| array | SET | Replace the entire array |
APPEND | Add element to the end | |
PREPEND | Add element to the beginning | |
REMOVE_LAST | Remove the last element | |
REMOVE_FIRST | Remove the first element | |
REMOVE_AT | Remove element at a given index | |
REMOVE_BY_VALUE | Remove all elements equal to the given value |
When Variables Reset
Page variables live in memory only. They reset to their initial values when:
The visitor navigates away from the page (including to another page in the same app)
The browser tab is reloaded
They do NOT reset when:
A Modal, Drawer, or Bottom Sheet is opened or closed
Tabs are switched within a Tabs block
These operations keep the visitor on the same page and do not mount a new page, so page variables are untouched.
App Scope vs Page Scope
| Scenario | Use Page Variable | Use App Variable |
| State only needed on one page | Yes | No |
| State must survive navigating to another page | No | Yes |
| State must survive a browser tab reload | No | No — use local/session storage |
| State needed by an app-level data source | No | Yes |
Practical Examples
Selected row variable — open modal with record data
// Variable: var_selectedRow (type: object) // On row click event — two sequential actions: // 1. Set the variable with the selected row { "actionType": "setPageVariable", "payload": { "variableId": "var_selectedRow", "operation": "SET", "value": "{{ row }}" } } // 2. Open the edit modal { "actionType": "controlModal", "payload": { "modalId": "b_editModal", "operation": "show" } } // Inside the modal, bind fields to: {{ var_selectedRow['value']['name'] }} {{ var_selectedRow['value']['email'] }}
Step counter variable for a multi-step form
// Variable: var_currentStep (type: number, initialValue: "1") // Next button: { "actionType": "setPageVariable", "payload": { "variableId": "var_currentStep", "operation": "INCREMENT_BY", "value": 1 } } // Previous button: { "actionType": "setPageVariable", "payload": { "variableId": "var_currentStep", "operation": "DECREMENT_BY", "value": 1 } } // Bind each step's visibility: // Step 2 visibility: {{ var_currentStep['value'] }} EQUAL 2
Filter state variable — object type
// Variable: var_filters (type: object, initialValue: "{}") // When status filter changes: { "actionType": "setPageVariable", "payload": { "variableId": "var_filters", "operation": "MERGE", "value": { "status": "{{ select_status['value'] }}" } } } // Bind data source parameter: {{ var_filters['value']['status'] }}
Troubleshooting
Variable is empty or back to default when I return to the page
Expected behavior — page variables reset every time the page opens fresh, including navigating away and back. Use an app variable or local storage for state that must survive navigation.
Wrong operations available for my variable
Operations are gated by type. Changing a variable's type changes which operations exist — interactions built on the old type may need reconfiguring. Numeric operations reject non-numeric input silently (value keeps previous state).
Write is not working — variable shows stale value
Check that: (1) the variableId in the action still matches the variable's ID (it may have been deleted and recreated), (2) the operation is valid for the variable's type, (3) the action is actually firing (check with a debug notification action before the variable write).