Skip to main content

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.

Preview limitations

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' }}
Common mistake

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:

  1. The parameter of an arrow function, such as p in map(p => p.title)
  2. The names of the enclosing loops, the key name included
  3. loop, inside a loop
  4. Variables
  5. Providers, such as post or site

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​