---
title: Templates
description: Create dynamic notification content with Liquid templating
---

Templates define the content of your notifications. Notiflows uses [Liquid](https://shopify.github.io/liquid/) templating to insert dynamic content into your notifications.

## Variable Contexts

Three variable contexts are available in every template:

| Context | Description | Example |
|---------|-------------|---------|
| `recipient.*` | Recipient user attributes | `{{ recipient.first_name }}` |
| `actor.*` | User who triggered the notification | `{{ actor.email }}` |
| `data.*` | Custom payload from the API call | `{{ data.order_id }}` |

These contexts are populated from the data you pass when [running a notiflow](/docs/learn/building-notiflows/trigger-step).

## Basic Syntax

Insert variables with double curly braces:

```liquid
Hi {{ recipient.first_name }},

{{ actor.first_name }} left a comment on your post.
```

## Filters

Transform values with filters:

```liquid
{{ recipient.first_name | capitalize }}
{{ data.price | money }}
{{ data.created_at | date: "%B %d, %Y" }}
```

## Conditionals

Use conditional logic:

```liquid
{% if data.discount %}
You saved {{ data.discount }}!
{% endif %}

{% if recipient.custom_fields.plan == "premium" %}
As a premium member, you get early access.
{% else %}
Upgrade to premium for early access.
{% endif %}
```

## Loops

Iterate over arrays:

```liquid
Your items:
{% for item in data.items %}
- {{ item.name }}: {{ item.price }}
{% endfor %}
```

## Template Formats by Channel

### Email

Email templates support three content types:

- **Visual** — Drag-and-drop editor for rich HTML emails
- **HTML** — Raw HTML with full control over layout
- **Plaintext** — Simple text emails

```liquid
Subject: Order #{{ data.order_id }} confirmed

Hi {{ recipient.first_name }},

Thanks for your order! Here's what you purchased:

{% for item in data.items %}
- {{ item.name }} ({{ item.quantity }}x)
{% endfor %}

Total: {{ data.total }}
```

### SMS

SMS templates use plaintext only:

```liquid
Hi {{ recipient.first_name }}, your order #{{ data.order_id }} has shipped! Track it: {{ data.tracking_url }}
```

### Mobile Push

Mobile push templates have a title and body field (both plaintext):

```liquid
Title: New message from {{ actor.first_name }}
Body: {{ data.message_preview }}
```

### Web Push

Web push templates have a title and body (both plaintext), plus optional icon, image, and action URL fields:

| Field | Required | Example |
|-------|----------|---------|
| Title | Yes | `{{ actor.first_name }} commented on your post` |
| Body | Yes | `{{ data.comment_preview }}` |
| Icon URL | No | `https://yourapp.com/icon.png` |
| Image URL | No | `{{ data.post_image_url }}` |
| Action URL | No | `https://yourapp.com/posts/{{ data.post_id }}` |

### In-App

In-app templates have a body (markdown) and an optional action URL:

```liquid
Body: **{{ actor.first_name }}** commented on your post: "{{ data.comment_preview }}"
Action URL: {{ data.post_url }}
```

### Chat (Slack)

Chat templates support markdown or JSON for rich formatting:

**Markdown:**
```liquid
*New order #{{ data.order_id }}*
Customer: {{ actor.first_name }} {{ actor.last_name }}
Total: {{ data.total }}
```

**JSON (Slack Block Kit):**
```json
{
  "blocks": [
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": "*Order #{{ data.order_id }}*\nCustomer: {{ actor.first_name }}"
      }
    }
  ]
}
```

## Digest Templates

When using a [digest step](/docs/learn/building-notiflows/digest-step), templates have access to the collected events via the `digest` context:

| Variable | Description |
|----------|-------------|
| `digest.total_items` | Number of events collected in the digest window |
| `digest.items` | Array of collected events |
| `digest.items[].data` | The original notification data payload |
| `digest.items[].actor` | The actor who triggered the event (`id`, `external_id`, `email`, `first_name`, `last_name`) |
| `digest.items[].recipient` | The recipient of the notification (same fields as actor) |

```liquid
You have {{ digest.total_items }} new comments:

{% for item in digest.items %}
- {{ item.actor.first_name }}: {{ item.data.message }}
{% endfor %}
```
