> ## Documentation Index
> Fetch the complete documentation index at: https://docs.launchmystore.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Tags

> Control flow, loops, and template logic with Aqua tags

# Aqua Tags

Tags create logic, loops, and control the template flow. They're wrapped in `{% %}`.

## Control Flow

### if / elsif / else

Conditional rendering based on truthiness.

```aqua theme={null}
{% if product.available %}
  <button>Add to Cart</button>
{% elsif product.coming_soon %}
  <button disabled>Coming Soon</button>
{% else %}
  <button disabled>Sold Out</button>
{% endif %}
```

**Operators:**

| Operator   | Description           |
| ---------- | --------------------- |
| `==`       | Equal                 |
| `!=`       | Not equal             |
| `>`        | Greater than          |
| `<`        | Less than             |
| `>=`       | Greater or equal      |
| `<=`       | Less or equal         |
| `contains` | String/array contains |
| `and`      | Logical AND           |
| `or`       | Logical OR            |

```aqua theme={null}
{% if product.price > 100 and product.available %}
  Premium & Available
{% endif %}

{% if product.tags contains 'sale' %}
  On Sale!
{% endif %}
```

### unless

Inverse of `if` - renders when condition is false.

```aqua theme={null}
{% unless product.available %}
  <span class="sold-out">Sold Out</span>
{% endunless %}
```

### case / when

Switch statement for multiple conditions.

```aqua theme={null}
{% case product.type %}
  {% when 'Shirt' %}
    <p>Check our size guide</p>
  {% when 'Shoes' %}
    <p>Available in US sizes</p>
  {% when 'Accessory' %}
    <p>One size fits all</p>
  {% else %}
    <p>Standard sizing</p>
{% endcase %}
```

***

## Iteration

### for

Loop through arrays and ranges.

```aqua theme={null}
{% for product in collection.products %}
  <div class="product">
    {{ product.title }}
  </div>
{% endfor %}
```

**Loop variables:**

| Variable          | Description             |
| ----------------- | ----------------------- |
| `forloop.index`   | Current index (1-based) |
| `forloop.index0`  | Current index (0-based) |
| `forloop.first`   | Is first iteration      |
| `forloop.last`    | Is last iteration       |
| `forloop.length`  | Total iterations        |
| `forloop.rindex`  | Reverse index (1-based) |
| `forloop.rindex0` | Reverse index (0-based) |

```aqua theme={null}
{% for product in collection.products %}
  <div class="product {% if forloop.first %}first{% endif %}">
    {{ forloop.index }}. {{ product.title }}
  </div>
{% endfor %}
```

**Parameters:**

```aqua theme={null}
{# Limit results #}
{% for product in collection.products limit: 4 %}

{# Skip items #}
{% for product in collection.products offset: 2 %}

{# Reverse order #}
{% for product in collection.products reversed %}

{# Combine parameters #}
{% for product in collection.products limit: 4 offset: 2 reversed %}
```

**Parallel iteration:**

For loops that fetch async data per iteration (e.g. rendering a list of
product cards where each card reads metafields), append `parallel: true`
to evaluate every iteration concurrently instead of sequentially:

```aqua theme={null}
{% for product in collection.products, parallel: true %}
  {% render 'product-card', product: product %}
{% endfor %}
```

This is an Aqua-specific extension on top of standard Liquid. Use it when
the iteration body issues independent I/O — re-ordering or shared mutable
state inside the loop will not behave as expected.

**Ranges:**

```aqua theme={null}
{% for i in (1..5) %}
  {{ i }}
{% endfor %}
```

**else (empty array):**

```aqua theme={null}
{% for product in collection.products %}
  {{ product.title }}
{% else %}
  No products found.
{% endfor %}
```

### break / continue

Control loop execution.

```aqua theme={null}
{% for product in collection.products %}
  {% if product.price > 1000 %}
    {% continue %}
  {% endif %}
  
  {{ product.title }}
  
  {% if forloop.index >= 10 %}
    {% break %}
  {% endif %}
{% endfor %}
```

### cycle

Alternates between values.

```aqua theme={null}
{% for product in collection.products %}
  <div class="{% cycle 'odd', 'even' %}">
    {{ product.title }}
  </div>
{% endfor %}
```

Named cycles for nested loops:

```aqua theme={null}
{% cycle 'row': 'row-1', 'row-2' %}
{% cycle 'col': 'col-1', 'col-2', 'col-3' %}
```

### tablerow

Generates HTML table rows.

```aqua theme={null}
<table>
  {% tablerow product in collection.products cols: 3 %}
    {{ product.title }}
  {% endtablerow %}
</table>
```

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

***

## Variable

### assign

Creates or updates a variable.

```aqua theme={null}
{% assign featured_product = all_products['product-handle'] %}
{% assign sale_price = product.price | times: 0.9 %}
```

### capture

Captures output into a variable.

```aqua theme={null}
{% capture product_info %}
  <span class="title">{{ product.title }}</span>
  <span class="price">{{ product.price | money }}</span>
{% endcapture %}

{{ product_info }}
```

### increment / decrement

Creates and modifies counter variables.

```aqua theme={null}
{% increment counter %}  {# 0 #}
{% increment counter %}  {# 1 #}
{% increment counter %}  {# 2 #}

{% decrement counter %}  {# -1 #}
{% decrement counter %}  {# -2 #}
```

***

## Theme Tags

### render

Renders a snippet with isolated scope.

```aqua theme={null}
{% render 'product-card', product: product %}
{% render 'icon', name: 'cart', size: 24 %}
```

**With for loop:**

```aqua theme={null}
{% render 'product-card' for collection.products as product %}
```

Variables inside render are isolated - they don't leak to the parent template.

### include

Renders a snippet with shared scope (legacy).

```aqua theme={null}
{% include 'snippet-name', variable: value %}
```

<Warning>
  Prefer `render` over `include`. Include shares scope which can cause variable collisions.
</Warning>

### section

Renders a section (in layouts).

```aqua theme={null}
{% section 'header' %}
{% section 'footer' %}
```

### sections

Renders a section group (JSON file).

```aqua theme={null}
{% sections 'header-group' %}
{% sections 'footer-group' %}
```

### layout

Specifies which layout to use.

```aqua theme={null}
{% layout 'theme' %}
{% layout 'alternate' %}
{% layout none %}
```

### content\_for

Dynamic block/section rendering.

```aqua theme={null}
{% content_for 'block', type: 'product-card', id: 'featured' %}
{% content_for 'header' %}
```

***

## Template Tags

### comment

Content inside is not rendered.

```aqua theme={null}
{% comment %}
  This won't appear in the output.
  Good for notes and temporarily hiding code.
{% endcomment %}
```

Single-line shorthand:

```aqua theme={null}
{# This is a comment #}
```

### raw

Outputs Aqua syntax literally.

```aqua theme={null}
{% raw %}
  {{ this.will.not.be.parsed }}
  {% this.either %}
{% endraw %}
```

### aqua

Multiple tags in condensed format inside a single `{% liquid %}` /
`{% aqua %}` block. Both keywords are accepted as aliases of each other,
but new code should use `{% aqua %}`.

```aqua theme={null}
{% aqua
  assign featured = collection.products | first
  if featured.available
    assign status = 'available'
  else
    assign status = 'sold-out'
  endif
%}
```

Inside the block, each line is a tag — no `{% %}` wrappers needed. Mix
control flow (`if`, `for`, `case`), assignments (`assign`, `capture`),
and includes (`render`, `include`, `section`, `sections`) freely.

### echo

Output inside aqua blocks.

```aqua theme={null}
{% aqua
  assign name = 'World'
  echo 'Hello ' | append: name
%}
```

***

## Form Tags

### form

Creates HTML forms with CSRF protection.

```aqua theme={null}
{% form 'contact' %}
  {{ form.errors | default_errors }}
  
  <input type="email" name="contact[email]" required>
  <textarea name="contact[body]"></textarea>
  <button type="submit">Send</button>
{% endform %}
```

**Form types:**

| Type                         | Purpose                 |
| ---------------------------- | ----------------------- |
| `contact`                    | Contact form            |
| `customer_login`             | Login form              |
| `create_customer`            | Registration            |
| `recover_customer_password`  | Password reset request  |
| `reset_customer_password`    | Set new password        |
| `activate_customer_password` | Activate account        |
| `customer_address`           | Address form            |
| `new_comment`                | Blog comment            |
| `product`                    | Add to cart             |
| `cart`                       | Cart update             |
| `localization`               | Country/language picker |
| `currency`                   | Currency selector       |
| `storefront_password`        | Password page           |

<Note>
  The customer form types (`customer_login`, `create_customer`,
  `recover_customer_password`, `reset_customer_password`,
  `activate_customer_password`, `customer_address`) power theme-rendered
  account pages. Field names, error handling, and full examples are in
  [Theme Customer Accounts](/aqua/customer-accounts#forms).
</Note>

**Product form example:**

```aqua theme={null}
{% form 'product', product %}
  <select name="id">
    {% for variant in product.variants %}
      <option value="{{ variant.id }}">{{ variant.title }}</option>
    {% endfor %}
  </select>
  <input type="number" name="quantity" value="1" min="1">
  <button type="submit">Add to Cart</button>
{% endform %}
```

**Form object properties:**

| Property                    | Description        |
| --------------------------- | ------------------ |
| `form.errors`               | Validation errors  |
| `form.posted_successfully?` | Submission success |
| `form.password_needed`      | Password required  |

***

## Pagination

### paginate

Paginates arrays.

```aqua theme={null}
{% paginate collection.products by 12 %}
  {% for product in collection.products %}
    {{ product.title }}
  {% endfor %}
  
  {% if paginate.pages > 1 %}
    <nav class="pagination">
      {% if paginate.previous %}
        <a href="{{ paginate.previous.url }}">Previous</a>
      {% endif %}
      
      {% for part in paginate.parts %}
        {% if part.is_link %}
          <a href="{{ part.url }}">{{ part.title }}</a>
        {% else %}
          <span class="current">{{ part.title }}</span>
        {% endif %}
      {% endfor %}
      
      {% if paginate.next %}
        <a href="{{ paginate.next.url }}">Next</a>
      {% endif %}
    </nav>
  {% endif %}
{% endpaginate %}
```

**Paginate object:**

| Property                  | Description          |
| ------------------------- | -------------------- |
| `paginate.current_page`   | Current page number  |
| `paginate.pages`          | Total pages          |
| `paginate.items`          | Total items          |
| `paginate.page_size`      | Items per page       |
| `paginate.current_offset` | Current offset       |
| `paginate.previous`       | Previous page object |
| `paginate.next`           | Next page object     |
| `paginate.parts`          | Page number links    |

***

## Section Schema

### schema

Defines section/block configuration (JSON).

```aqua theme={null}
{% schema %}
{
  "name": "Featured Product",
  "settings": [
    {
      "type": "product",
      "id": "product",
      "label": "Product"
    },
    {
      "type": "checkbox",
      "id": "show_vendor",
      "label": "Show vendor",
      "default": true
    }
  ],
  "presets": [
    {
      "name": "Featured Product"
    }
  ]
}
{% endschema %}
```

See [Schema Reference](/aqua/schema) for full documentation.

### stylesheet

Scoped CSS for sections.

```aqua theme={null}
{% stylesheet %}
  .featured-product {
    padding: 2rem;
    background: {{ section.settings.background_color }};
  }
{% endstylesheet %}
```

### javascript

Scoped JavaScript for sections.

```aqua theme={null}
{% javascript %}
  document.addEventListener('DOMContentLoaded', () => {
    console.log('Section loaded');
  });
{% endjavascript %}
```

***

## Whitespace Control

Add hyphens to strip whitespace:

```aqua theme={null}
{%- assign name = 'value' -%}
{{- output -}}
```

| Syntax | Effect              |
| ------ | ------------------- |
| `{%-`  | Strip before        |
| `-%}`  | Strip after         |
| `{{-`  | Strip before output |
| `-}}`  | Strip after output  |

Example:

```aqua theme={null}
{# With whitespace #}
{% assign x = 1 %}
{{ x }}

{# Without whitespace #}
{%- assign x = 1 -%}
{{- x -}}
```
