# Liquid tags reference

Source: https://support.storeconnect.com/articles/liquid-tags-reference · Last modified 21 August 2026

Liquid tags use the `{% %}` syntax and perform actions rather than output values. StoreConnect extends standard Liquid with its own tags for template structure, data querying, HTTP responses, caching, and more.

Tags come in two forms:

- **Simple tags** — self-contained: `{% tag_name options %}`
- **Block tags** — open/close pair wrapping content: `{% tag_name %}...{% endtag_name %}`

For the index of StoreConnect-specific tags grouped by category, see [Liquid tags](liquid-tags).

---

## Control flow

### `if` / `elsif` / `else`

Executes a block when a condition is true.


```liquid

{% if product.available %}
  <p>In stock</p>
{% elsif product.pricing.on_sale? %}
  <p>On sale</p>
{% else %}
  <p>Out of stock</p>
{% endif %}
```


**Comparison operators:** `==`, `!=`, `>`, `<`, `>=`, `<=`, `contains`

**Logical operators:** `and`, `or`


```liquid

{% if product.available and product.pricing.price < 100 %}
  <p>Affordable and in stock</p>
{% endif %}

{% if product.tags contains "sale" %}
  <span class="badge">Sale</span>
{% endif %}
```


### `unless`

Executes a block when a condition is **false**. Does not support `elsif`.


```liquid

{% unless current_customer %}
  <a href="{{ current_store.login_path }}">Log in</a>
{% endunless %}
```


### `case` / `when`

Switch statement for matching values.


```liquid

{% case current_checkout_step %}
{% when "customer_information" %}
  {% render "checkout/customer_information" %}
{% when "shipping_information" %}
  {% render "checkout/shipping_information" %}
{% else %}
  {% render "checkout/default" %}
{% endcase %}
```


Multiple values: `{% when "monday", "tuesday", "wednesday" %}`

---

## Iteration

### `for`

Iterates over a collection.


```liquid

{% for product in all_products %}
  <p>{{ product.name }}</p>
{% endfor %}
```


**Parameters:**

| Parameter | Description |
|-----------|-------------|
| `limit` | Maximum iterations: `{% for item in items limit: 5 %}` |
| `offset` | Skip items: `{% for item in items offset: 3 %}` |
| `reversed` | Reverse order: `{% for item in items reversed %}` |

**Range:** `{% for i in (1..10) %}{{ i }}{% endfor %}`

**`forloop` object:**

| Property | Description |
|----------|-------------|
| `forloop.index` | Current iteration (1-based) |
| `forloop.index0` | Current iteration (0-based) |
| `forloop.rindex` | Remaining iterations (1-based) |
| `forloop.rindex0` | Remaining iterations (0-based) |
| `forloop.first` | True on first iteration |
| `forloop.last` | True on last iteration |
| `forloop.length` | Total number of iterations |

**Empty fallback:**


```liquid

{% for product in collection %}
  {{ product.name }}
{% else %}
  <p>No products found</p>
{% endfor %}
```


### `break` / `continue`


```liquid

{% for item in items %}
  {% if item.hidden? %}{% continue %}{% endif %}
  {% if forloop.index > 10 %}{% break %}{% endif %}
  {{ item.name }}
{% endfor %}
```


### `tablerow`

Generates HTML table rows.


```liquid

<table>
  {% tablerow product in all_products cols: 3 %}
    {{ product.name }}
  {% endtablerow %}
</table>
```


Parameters: `cols`, `limit`, `offset`, `range`

---

## Variable

### `assign`

Assigns a value to a variable.


```liquid

{% assign my_variable = "Hello" %}
{% assign product_count = all_products.size %}
{% assign is_sale = product.pricing.on_sale? %}
```


### `capture`

Captures rendered content into a variable.


```liquid

{% capture full_name %}{{ current_customer.firstname }} {{ current_customer.lastname }}{% endcapture %}
<p>Welcome, {{ full_name }}</p>
```


### `increment` / `decrement`

Creates and increments/decrements a named counter. The counter is independent of variables with the same name.


```liquid

{% increment counter %}
{% increment counter %}
{% increment counter %}
```


### `default`

Sets default values for variables that are not already defined. Only runs if the variable doesn't exist — does not override passed values. Commonly used at the top of snippets to define parameter defaults.


```liquid

{% default title: "Untitled", show_price: true, max_items: 10 %}
```


### `new`

Creates new objects.

**UUID:**


```liquid

{% new UUID my_id %}
{{ my_id }}
```


**List:**


```liquid

{% new List my_list %}
{% new List my_list = "[1,2,3]" %}
```


**Map:**


```liquid

{% new Map my_map %}
{% new Map config = '{"theme":"dark"}' %}
{{ config.theme }}
```


**Random number:**


```liquid

{% new Rand dice, min: 1, max: 6 %}
{{ dice }}
```


### `struct`

Creates a validated structured object.


```liquid

{% struct my_obj = "struct_name", key: "value", count: 42 %}
```


---

## Template

### `comment`

Prevents content from rendering.


```liquid

{% comment %}
  This won't be output
{% endcomment %}

{%- comment -%} Inline comment {%- endcomment -%}
```


Inline form: `{%# This is a comment %}`

### `raw`

Temporarily disables Liquid processing so `{{ }}` and `{% %}` syntax passes through as literal text.

```liquid


  {{ this will not be processed }}

```

### `render`

Renders a snippet or partial template.


```liquid

{% render "header" %}
{% render "products/card", product: product, show_price: true %}
```


Variables are passed as named parameters. The snippet runs in its own scope — only passed variables are available.

### `layout`

Specifies which layout wraps the current page template. If omitted, the default `theme.liquid` layout is used.


```liquid

{% layout "account" %}
```


### `require`

Loads a CSS or JavaScript asset. Automatically deduplicates — the same asset is only loaded once per page regardless of how many templates request it.


```liquid

{% require "styles/theme.css" %}
{% require "scripts/theme.js" %}
```


Alias: `{% resource_path "styles/theme.css" %}`

### `header`

Sets HTTP response headers.


```liquid

{% header name: "Content-Type", value: "application/json" %}
{% header name: "Cache-Control", value: "public, max-age=3600" %}
```


### `component`

Renders a reusable component with support for lazy loading and event-driven reload.


```liquid

{% component "cart", reload: "sc.cart-updated" %}
{% component "checkout/vouchers", reload: "sc.voucher-applied sc.voucher-removed", lazy: true %}
```


| Parameter | Description |
|-----------|-------------|
| First argument | Component template name (in `components/` directory) |
| `reload` | Space-separated event names that trigger a reload |
| `lazy` | If `true`, loads asynchronously after page load |
| Additional params | Passed to the component template |

### `form`

Wraps a block in an HTML form with CSRF protection and field definitions.


```liquid

{% form "add-to-cart", product: current_product %}
  <input type="number" name="{{ form.quantity.name }}" value="1">
  <button type="submit">Add to cart</button>
{% endform %}
```


Inside the block, the `form` variable provides field definitions and errors. See [Theme forms](theme-forms) and [Liquid forms reference](liquid-forms-reference).

### `paginate`

Paginates a collection with configurable page size and navigation window.


```liquid

{% paginate all_products by 20, window: 5 %}
  {% for product in all_products %}
    {{ product.name }}
  {% endfor %}

  {% if paginate.pages > 1 %}
    {% for part in paginate.parts %}
      {% if part.gap? %}...
      {% elsif part.current? %}<strong>{{ part.page }}</strong>
      {% else %}<a href="{{ part.url }}">{{ part.page }}</a>
      {% endif %}
    {% endfor %}
  {% endif %}
{% endpaginate %}
```


| Parameter | Description |
|-----------|-------------|
| `by` | Items per page (required) |
| `as` | Custom URL parameter name (default: `"page"`) |
| `window` | Number of page links on each side (default: `5`) |

**`paginate` drop properties:** `page_size`, `current_page`, `pages`, `records`, `current_offset`, `next`, `previous`, `first`, `last`, `parts`

**Part properties:** `url`, `page`, `current?`, `gap?`

### `cache`

Caches a block of rendered HTML for a configurable duration.


```liquid

{% cache "product-card", items: [current_product, current_store], expires_in: 60 %}
  {% render "products/card", product: current_product %}
{% endcache %}
```


| Parameter | Description |
|-----------|-------------|
| First argument | Cache key name (required) |
| `items` | Array of objects used to generate the cache key |
| `expires_in` | Expiration in seconds |
| `race_condition_ttl` | Race condition TTL in seconds |

### `process_event`

Processes an event object and injects its methods into the template context.


```liquid

{% process_event order_event %}
  <p>{{ event_type }}: order #{{ order_number }}</p>
{% endprocess_event %}
```


---

## Data & integration

### `query`

Fetches records from the StoreConnect data store and assigns them to a variable.


```liquid

{% query 'Product2' as featured, Featured__c: true order by 'Name asc' %}
{% for record in featured %}
  {{ record.Name }}
{% endfor %}
```


**Syntax:** `{% query 'ObjectName' as variable [, field: value] [order by 'field asc|desc'] %}`

Records from `{% query %}` are raw record objects. Use `| cast: "TypeName"` to convert them to drops with full property access.


```liquid

{% query 'Product2' as records, IsActive: true order by 'CreatedDate desc' %}
{% for record in records %}
  {% assign product = record | cast: "Product" %}
  {{ product.name }} — {{ product.pricing.price | money }}
{% endfor %}
```


See [Liquid query](liquid-query) for full usage guidance.

### `api`

Makes an outbound HTTP request to an external service.


```liquid

{%- new Map post_data -%}
{%- assign post_data = post_data | set_key: "event", "signup" | set_key: "email", current_customer.email -%}
{% api url: "https://api.example.com/track", method: "post", data: post_data %}
  {% if response.status == 200 %}
    <p>{{ response.body.message }}</p>
  {% endif %}
{% endapi %}
```


| Parameter | Description |
|-----------|-------------|
| `url` / `endpoint` | Target URL (required) |
| `method` | HTTP method: `get`, `post`, `put`, `patch`, `delete` (default: `get`) |
| `data` | Request body — must be a Map variable, not inline JSON |
| `headers` | Custom HTTP headers |
| `username` / `password` | Basic authentication |
| `bearer` | Bearer token |
| `async` | Run in background (forced `true` inside `{% final %}`) |

**Response object:** `response.status`, `response.body`, `response.headers`. JSON responses are automatically parsed. Async requests don't expose response data.

---

## State management

### `session`

Stores values in the user's session, persisting them across requests.


```liquid

{% session last_viewed: product.id, preference: "compact" %}
```


Access stored values with `session_variables`:


```liquid

{{ session_variables.last_viewed }}
{{ session_variables.preference }}
```


### `context`

Sets variables scoped to a component. Only effective inside component templates. Context variables persist across reloads and don't leak to parent or sibling components.


```liquid

{% context product_id: current_product.id, show_details: true %}
```


---

## Controller lifecycle

These block tags run only during a specific phase of a Liquid controller's execution. See [Liquid controllers guide](liquid-controllers-guide) for full usage.

### `before`

Runs before the page template renders.


```liquid

{% before %}
  {% params product_id: current_request.params.id %}
  {% action "cart.add", product_identifier: product_id, quantity: 1 %}
{% endbefore %}
```


### `after`

Runs after the main controller action.


```liquid

{% after %}
  {% redirect to: "/cart", notice: "Item added" %}
{% endafter %}
```


### `final`

Runs after the response is sent. API calls here are automatically async.


```liquid

{% final %}
  {%- new Map payload -%}
  {%- assign payload = payload | set_key: "event", "purchase" -%}
  {% api url: "https://analytics.example.com/track", method: "post", data: payload %}{% endapi %}
{% endfinal %}
```


### Action tags (inside phases)

These tags are valid only inside `{% before %}`, `{% after %}`, or `{% final %}` blocks.

**`{% params %}`** — reads request parameters into controller params.

**`{% variables %}`** — sets template variables available in the page template.

**`{% redirect %}`** — redirects and stops execution. Options: `to`, `notice`, `alert`, `status`.

**`{% respond %}`** — sends a custom HTTP response. Options: `status`, `body`, `json`.

**`{% update %}`** — updates a custom data field on an object.

**`{% action %}`** — executes a named action. Cart: `cart.add`, `cart.update`, `cart.remove`, `cart.empty`, `cart.select`, `cart.clone`. Shipping: `shipping.set`. Pricebook: `pricebook.set`, `pricebook.clear`. Promotion: `promotion.apply`, `promotion.remove`, `promotion.clear`.

---

## Debugging

### `debug`

Logs variable values to the session debug output.


```liquid

{% debug product_id: product.id, cart_items: current_cart.item_count %}
```


### `timer`

Measures and logs the execution time of a template block.


```liquid

{% timer "product_list_render" %}
  {% for product in all_products %}
    {% render "products/card", product: product %}
  {% endfor %}
{% endtimer %}
```


---

## Whitespace control

Add `-` to tag delimiters to strip surrounding whitespace:


```liquid

{%- assign x = "hello" -%}
{%- if true -%}Content{%- endif -%}
```

---

## Follow StoreConnect

- [Email Newsletter](https://getstoreconnect.com/c/lp-newsletter)
- [LinkedIn Newsletter](https://www.linkedin.com/build-relation/newsletter-follow?entityUrn=7444956928444862464)
- [YouTube](https://www.youtube.com/channel/UCngKdP2x8l1wcbAKW3tvU8g)
- [LinkedIn](https://www.linkedin.com/company/storeconnect)
- [X / Twitter](https://x.com/storeconnecthq)

## Popular Links

- [Partners](https://getstoreconnect.com/partners)
- [News](https://getstoreconnect.com/articles/news)
- [Events](https://getstoreconnect.com/articles/events)
- [Feature Comparison](https://getstoreconnect.com/how-we-compare)
- [Download a free trial](https://appexchange.salesforce.com/appxListingDetail?listingId=a0N3A00000FMkeKUAT)
- [Book a Demo](https://getstoreconnect.com/contact)

## Documentation

- [Help documentation](https://support.storeconnect.com/help-documentation)
- [AI agents](https://support.storeconnect.com/ai)
- [Videos & tutorials](https://support.storeconnect.com/videos-tutorials)
- [Developer reference](https://support.storeconnect.com/developer-reference)
- [Release notes](https://support.storeconnect.com/release-notes)
- [Troubleshooting](https://support.storeconnect.com/troubleshooting)
- [Trust Center](https://trust.getstoreconnect.com/)
- [Status Page](https://status.storeconnect.com/)

## Contact

- info@getstoreconnect.com
- US +1 415 745 3230
- AUS +61 2 8365 2308

100 S Ashley Dr, Suite 600-2461
Tampa FL 33602-600 USA

Level 22, Sydney Place
180 George Street
Sydney, NSW, 2000, AUS

---

StoreConnect Support — https://support.storeconnect.com/articles/liquid-tags-reference