Variables
{% set %}Stores a value or query result for reuse across your template.This page shows you how to use the Variable block to store values and reuse them across your template.
When to use a Variable block
Most of the time, you don't need one. A Loop block can run queries on its own and even expose query results by name after the loop.
The Variable block exists for one main case: you need query data before the loop — like showing a total count or pagination above the list. Since blocks render in order, the loop hasn't run yet, so you need the Variable block to define the query first.
Set the Variable block's Source to Query, then build the query as in a Loop block. The inspector shows it as get_posts():
{% set products = get_posts() %}
<p>{{ products.found_posts }} products</p>
{{ products.pagination }}
{% for post in products %}
<h2>{{ post.title }}</h2>
{% endfor %}
found_posts and pagination need the Query source. An expression such as get_posts({post_type: 'product'}) gives the posts, but no total and no pagination.
If you only need pagination after the loop, skip the Variable block — the Loop block handles it.
Some expressions — like loop counters or computed values that change per iteration — may not render correctly in the editor. The editor preview is an approximation. Always verify on the frontend to confirm your variables and expressions work as expected.
Other uses
Beyond query pre-fetching, variables can store any value. Leave Source on Expression and write it in the Expression field:
Avoid repeating long expressions
Name: my_price
Expression: post.meta('sale_price') ?: post.meta('regular_price')
{{ my_price|number_format(2) }}
Store computed values
Name: display_title
Expression: post.meta('custom_title') ?: post.title
{{ display_title }}
Avoid repeating chains
Name: img
Expression: post.thumbnail
{{ img.src('large') }}
{{ img.alt ?: post.title }}
{{ img.width }}
Using Variables
Once created, variables work like any other data source:
{{ my_variable }}
{{ my_variable.title }}
{{ my_variable|upper }}
{{ my_variable ? 'exists' : 'empty' }}
A variable must be declared before any block that references it. If you place a Variable block after a block that uses {{ my_var }}, the value won't be available yet. Order matters — put your Variable blocks early in the template.
How names resolve
A name in an expression is looked up in this order, the first match wins:
- The parameter of an arrow function, such as
pinmap(p => p.title) - The names of the enclosing loops, the key name included
loop, inside a loop- Variables
- Providers, such as
postorsite
So a variable named post hides the post provider, and a loop named like a variable hides it inside the loop.
Variables belong to the whole page:
- A Variable block with the name of an earlier one replaces it for the blocks that follow.
- A Loop block with a query name stores its results under that name too.
- A Variable block inside a loop is set again on each item and keeps the last one after the loop.
Names keep lowercase letters, digits and underscores only: My Price becomes myprice. With the Query source, entering the name of another variable reuses its query.
Next steps
- Loop — use query variables as a loop data source
- Expressions & Syntax — full reference for operators and filters
- Common Patterns — ready-to-use expression examples