Variables and the variable picker
Read the event, earlier step results, loop items, secrets and your own workflow variables in any field, and pick them instead of typing paths.
Every text field of every step can read data of the run. You write a variable in double curly braces, and the app fills in the value when the step runs:
Order {{ event.payload.name }} was placed by {{ event.payload.customer.first_name }}
What you can read
| Variable | Holds |
|---|---|
event.topic |
The trigger, for example orders/create |
event.payload |
The trigger's data: the order, product, request body and so on |
event.changes.items |
For change triggers: each changed field with oldValue and newValue |
steps.<id>.output |
What an earlier step returned |
steps.<id>.status |
SUCCESS or FAILED |
loop.item, loop.index, loop.number |
Inside a Repeat for each: the current item and its position |
vars.NAME |
A workflow variable you defined |
secrets.NAME |
A secret from the Secrets page |
shop |
Your store's domain |
run.id, run.test |
The id of this run, and true in a test run |
The variable picker
You rarely type a path. Every field that takes variables has a button on its right. It opens the picker with everything this step can read, in groups:
- Trigger - the fields of the trigger's sample event, each with a sample value.
- Loop - when the step is inside a Repeat for each.
- Step: ... - one group per earlier step, with the fields that step is known to return.
- Variables and Store and run.
Two things make the picker better:
- Run a test. After a test, a step's group is marked (from your last test) and offers the real fields of what the step really returned. For an HTTP request, a Shopify query or code, that is the only way to see the fields of the answer.
- Watch for May be empty. A step that does not run on every path that leads here, for example a step on one branch of a condition, is marked. If it did not run, its variables render as nothing.

Lists
One entry of a list is read by its position, starting at 0:
{{ event.payload.line_items[0].sku }}
In a Condition's Field, the same value is written as a path with a dot: event.payload.line_items.0.sku. The picker writes the right form for you.
To work through all entries, use Repeat for each, or a Liquid for loop inside the field. See Liquid in every field.
Workflow variables
A workflow variable is a value you define once and use in any field of any step. Good for a threshold, a tag name, an email address, or a longer expression you do not want to repeat.
- Select Variables in the toolbar above the canvas.
- Select Add variable.
- Enter a Name: letters, digits and
_only, starting with a letter, 40 characters at most. - Enter the Value. It is a Liquid template: it may read the event, a secret and the variables above it.
Use it in fields as {{ vars.NAME }} and in conditions as vars.NAME.
{{ event.payload.total_price | times: 1 | round }}
- A workflow holds up to 30 variables, each up to 10 KB.
- A value that is exactly one
{{ output }}keeps its type: a number stays a number, a list stays a list. - Variables are worked out again for every step that uses them and are never stored with the run. So a variable may hold
{{ secrets.NAME }}. - A variable should not read a step's result: it is empty for the steps that run before that step, and the editor warns about it.
- The Variables panel is also where you choose the workflow's Shopify Admin API version. See Every Shopify mutation and query.

Missing values
A variable that does not exist renders as nothing. It does not fail the step. That is on purpose: a step after two branches may read a branch that did not run. Give a fallback with the default filter where it matters:
Hi {{ event.payload.customer.first_name | default: "there" }}
The editor catches the mistakes it can see: a variable of a step that does not run before this one, a workflow variable that is not defined, and loop values outside a loop are listed as problems.
Step ids
The <id> in steps.<id> is the step's id, which the editor assigns. The picker inserts it for you, and the name you give a step does not change it. An older id that contains a hyphen is written with brackets: steps["my-step"].output.
