# Using Liquid templates

Liquid Templates significantly broaden Pushwoosh’s personalization capabilities by implementing sophisticated logic in addition to regular[ Dynamic Content](/developer/guides/personalization/dynamic-content/) usage.

Message personalization in Pushwoosh is based on [Tags (user data)](/developer/guides/audience-and-segmentation/tags/). Pushwoosh offers a variety of [default Tags](/developer/guides/audience-and-segmentation/tags/#default-tags) and [custom Tags](/developer/guides/audience-and-segmentation/tags/#custom-tags). Using them, you can specify user’s first name, city, purchase history, etc. to send a more personalized message, for example: Hi `{First_name}`, thanks for ordering `{item}`.

Liquid templates add more logic to dynamic content. For instance, if a user's subscription tag contains "free," you can send them a message: “Grab your 10% discount.”

Modifying the message content according to users' IDs, behaviors, and preferences is the most efficient way to increase relevance and get more impressive results from your marketing campaigns.

## Syntax

Content templates based on [Liquid by Shopify](https://shopify.github.io/liquid/) use a combination of [**tags**](/developer/guides/personalization/liquid-templates/#tags), [**objects**](/developer/guides/personalization/liquid-templates/#objects), and [**filters**](/developer/guides/personalization/liquid-templates/#filters) to load dynamic content. Content templates allow you to access certain variables from within a template and output their data without having to know anything about the data itself.

<Aside type="note">
To learn more about the syntax, please refer to [Liquid documentation](https://shopify.github.io/liquid/basics/introduction/).
</Aside>

### Objects

`objects` define the content that will be displayed to a user. `objects` should be enclosed in double curly braces: `{{ }}`

For example, when personalizing a message, send `{{Name}}` in its body to add the users' names to the message's content. The user's name (Name tag value) will replace the Liquid object in a message the user will see.

<Tabs>
  <TabItem label="Input">

```

Hi {{Name}}! We're glad you're back!

```

  </TabItem>

  <TabItem label="Output">
    Hi Anna! We're glad you're back!
  </TabItem>
</Tabs>


### Tags

`tags` create the logic and control flow for templates. The curly brace percentage delimiters `{%` and `%}` and the text that they surround do not produce any visible output when the template is rendered. This lets you assign variables and create conditions or loops without showing any of the Liquid logic to a user.

For example, using the `if` tag, you can vary the message's language based on what language is set on user's device:

<Tabs>
  <TabItem label="Input">

```liquid
{% if Language == 'fr' %}
Salut!
{% else %}
Hello!
{% endif %}
````

  </TabItem>

  <TabItem label="Output (fr)">
    Salut!
  </TabItem>

  <TabItem label="Output (es)">
    Hello!
  </TabItem>
</Tabs>

### Tags operators

<table data-header-hidden><thead><tr><th width="189.5" align="center">Operator</th><th>Description</th></tr></thead><tbody><tr><td align="center"><code>==</code></td><td>equals</td></tr><tr><td align="center"><code>!=</code></td><td>does not equal</td></tr><tr><td align="center"><code>></code></td><td>greater than</td></tr><tr><td align="center"><code>&#x3C;</code></td><td>less than</td></tr><tr><td align="center"><code>>=</code></td><td>greater than or equal to</td></tr><tr><td align="center"><code>&#x3C;=</code></td><td>less than or equal to</td></tr><tr><td align="center"><code>or</code></td><td>logical or</td></tr><tr><td align="center"><code>and</code></td><td>logical and</td></tr><tr><td align="center"><code>contains</code></td><td>checks for the presence of a substring inside a string or array of strings</td></tr></tbody></table>

<Aside type="note">
In tags with more than one `and` or `or` operator, operators are checked in order _from right to left_. You cannot change the order of operations using parentheses — parentheses are invalid characters in Liquid and will prevent your tags from working.
</Aside>

### Filters

`filters` modify the output of a Liquid object or variable. They are used within double curly braces `{{ }}` and variable assignment, and are separated by a pipe character `|`. Multiple filters can be used on one output, and are applied from left to right.


<Tabs>
<TabItem label="Input">

```

{{ Name | capitalize | prepend:"Hello " }}

```

</TabItem>

<TabItem label="Output">

Hello Anna

</TabItem>
</Tabs>

## Using Liquid Templates in messages sent via API

Use the Liquid syntax in your [`createMessage`](/developer/api-reference/messages-api/#createmessage) requests to implement Liquid Templates. Templates are available for the "content" parameter of `createMessage` request, as well as for any other parameter supporting Dynamic Content, in particular, platform-specific "title", "subtitle", and "image" params.

By using content templates, you can either specify the data in your API requests (passing the "template\_bindings" parameter) or get the data from Tag values stored on users' devices (by not using the "template\_bindings" parameter). This way, you're able to build user-based push campaigns containing extremely relevant content.

<Aside type="note">
Please note, that unlike Dynamic Content, the variables in templates should be enclosed into double curly braces as follows: `{{myVariable}}`.
</Aside>

To define the template logic using the Tags with spaces in their names, use the following technique:

**Example**

```
{% capture my_tag %}{{My Tag}}{% endcapture %}
{% if my_tag == 'value' %}
Content to send in this case
{% else %}
Content to send otherwise
{% endif %}
```
## Liquid Templates use cases

Here you'll find several use cases when Liquid Templates come in handy.

### Multi-language push

Liquid Templates make it possible to definitely specify in what language users should receive your push messages. Look at the simple example of the API request and the message received depending on template bindings used in the request.


<Tabs>
<TabItem label="Liquid input">

```

{% if Language == 'es' %}
¡Hola!
{% else %}
Hello!
{% endif %}

````

</TabItem>

<TabItem label="API request">

```javascript
{
  "request": {
    "application": "XXXXX-XXXXX", // Pushwoosh app code
    "auth": "yxoPUlw.....IyEX4H", // API access token from Pushwoosh Control Panel
    "notifications" : [ // push message parameters
      {
       "content": "{% raw %}
{% if language == 'es' %}¡Hola!{% else %}hello!{% endif %}
{% endraw %}",
        "template_bindings": { // optional. When no template_bindings are passed in a request, Tag values from the device are used.
         "language" : "es"
        }
      }
    ]
  }
}
````

</TabItem>

<TabItem label="Output">

**Language is 'es'**:
¡Hola!

**Language is 'en'**:
Hello!

</TabItem>
</Tabs>


### Subscription upgrade prompt

Encourage your customers to upgrade their subscription based on their current plan.

<Tabs>
  <TabItem label="Liquid input">

```

{% if Subscription == 'Basic' %}
    Upgrade to Silver for getting more product features and 24/7 support.
{% elsif Subscription == 'Silver' %}
    Upgrade to Gold for priority support and advanced features.
{% else %}
    Please contact your manager to renew your subscription.
{% endif %}

````

</TabItem>

<TabItem label="API request">

```json
{
  "request": {
    "application": "XXXXX-XXXXX", // Pushwoosh app code
    "auth": "yxoPUlw.....IyEX4H", // API access token from Pushwoosh Control Panel
    "notifications" : [ // push message parameters
      {
       "content": "{% raw %}
{% if Subscription == 'Basic' %}Upgrade to Silver for getting more product features and 24/7 support.{% elsif Subscription == 'Silver' %}Upgrade to Gold for priority support and advanced features.{% else %}Please contact your manager to renew your subscription. {% endif %}
{% endraw %}",
        "template_bindings": { // optional. When no template_bindings are passed in a request, Tag values from the device are used.
         "language" : "es"
        }
      }
    ]
  }
}
````

  </TabItem>

  <TabItem label="Output">

**For users with Basic subscription plan:**
Upgrade to Silver for getting more product features and 24/7 support.

**For users with Silver subscription plan:**
Upgrade to Gold for priority support and advanced features.

**For users with other plans:**
Please contact your manager to renew your subscription.

  </TabItem>
</Tabs>


### List tags

Content templates are quite helpful to handle Tags of a List type.

#### Variable size

One of the possible use cases is to deliver different content depending on the number of values the Tag contains. For example, you can provide different discounts to customers with different behaviors. Let's say the customer has some items in their WishList—encourage them to purchase with the most fitting discount based on how many products they're going to buy!


<Tabs>
<TabItem label="Liquid input">

```

{% if WishList.size >= 3 %}
Get 20% off your next purchase!
{% elsif WishList.size == 2 %}
Get a 10% discount on your next purchase!
{% else %}
Hey, take a look at new outwears!
{% endif %}

````

</TabItem>

<TabItem label="API request">

```javascript
{
  "request": {
    "application": "XXXXX-XXXXX", // Pushwoosh app code
    "auth": "yxoPUlw.....IyEX4H", // API access token from Pushwoosh Control Panel
    "notifications" : [ // push message parameters
      {
       "content": "{% raw %}
{% if WishList.size >= 3 %}Get 20% off your next purchase!{% elsif WishList.size == 2 %}Get a 10% discount on your next purchase!{% else %}Hey, take a look at new outwears!{% endif %}
{% endraw %}",
        "template_bindings": {
         "WishList" : ["Skinny Low Ankle Jeans", "Linen Trenchcoat", "High Waisted Denim Skirt", "Strappy Tiered Maxi Dress"]
        }
      }
    ]
  }
}
````

</TabItem>

<TabItem label="WishList size ≥ 3">

<img src="/personalization-liquid-templates-1.webp" alt="Email preview with wishlist size greater than or equal to 3" width="200"/>

</TabItem>

<TabItem label="WishList size = 2">

<img src="/personalization-liquid-templates-2.webp" alt="Email preview with wishlist size equal to 2" width="200"/>

</TabItem>
</Tabs>

#### Variable contains

One more case you might need to cover is to deal with List Tags values and deliver the most relevant content based on what values the Tag contains.

<Tabs>
<TabItem label="Liquid input">

```

{% if WishList contains 'Skinny Low Ankle Jeans' %}
Get 20% off products in your wishlist!
{% else %}
Hey, take a look at the brand new Skinny Low Ankle Jeans!
{% endif %}

````

</TabItem>

<TabItem label="API request">

```javascript
{
  "request": {
    "application": "C90C0-0E786",
    "auth": "yxoPUlw.....IyEX4H", // API access token from Pushwoosh Control Panel
    "notifications" : [ // push message parameters
      {
       "content": "{% raw %}
{% if WishList contains 'Skinny Low Ankle Jeans' %}Get 20% off your next purchase!{% else %}Hey, take a look at the brand new Skinny Low Ankle Jeans!{% endif %}
{% endraw %}",
        "template_bindings": {
         "WishList" : ["Skinny Low Ankle Jeans", "Linen Trenchcoat", "High Waisted Denim Skirt", "Strappy Tiered Maxi Dress"]
        }
      }
    ]
  }
}
````

</TabItem>

<TabItem label="Variable contains data">

<img src="/personalization-liquid-templates-3.webp" alt="Personalized template with data" width="200"/>

</TabItem>

<TabItem label="Variable does not contain data">

<img src="/personalization-liquid-templates-4.webp" alt="Fallback view when data is missing" width="200"/>

</TabItem>
</Tabs>


### Plurals

By using the content templates, you're able to adjust message content according to users' behavior. For example, you can modify the message text to contain plural words in case the List Tag contains more than one value.


<Tabs>
<TabItem label="Liquid input">

```
    Get 20% off item
{% if WishList.size > 1 %}
    s in your WishList!
{% else %}
    in your Wishlist!
{% endif %}

````

</TabItem>

<TabItem label="API request">

```javascript
{
  "request": {
    "application": "C90C0-0E786",
    "auth": "yxoPUlw.....IyEX4H", // API access token from Pushwoosh Control Panel
    "notifications" : [ // push message parameters
      {
       "content": "Get 20% off item{% raw %}
{% if WishList.size > 1 %}s in your WishList!{% else %} in your Wishlist!{% endif %}
{% endraw %}",
        "template_bindings": { // optional. When no template_bindings are passed in a request, Tag values from the device are used.
         "WishList" : ["Skinny Low Ankle Jeans", "Linen Trenchcoat", "High Waisted Denim Skirt", "Strappy Tiered Maxi Dress"]
        }
      }
    ]
  }
}
````

</TabItem>

<TabItem label="Plural">

<img src="/personalization-liquid-templates-5.webp" alt="Plural form template example" width="200"/>

</TabItem>

<TabItem label="Singular">

<img src="/personalization-liquid-templates-6.webp" alt="Singular form template example" width="200"/>

</TabItem>
</Tabs>

### Timezone

Template for timezones converts the date and time according to the timezone specified.

<Tabs>
<TabItem label="Liquid input">
```
{{ MyDate | timezone: MyTimezone | date: \"%Y-%m-%d %H:%M\" }}
```
</TabItem>

<TabItem label="API request">
```javascript title="Example"
{
  "request" : {
    "auth" : "3H9bk8w3.....Acge2RbupTB", // API access token from Pushwoosh Control Panel
    "application" : "XXXXX-XXXXX", // Pushwoosh app code
    "notifications" : [ // push message parameters
      {
        "content": "Current Date: {{ MyDate | timezone: MyTimezone | date: \"%Y-%m-%d %H:%M\" }}",
        "template_bindings": { // optional. When no template_bindings are passed in a request, Tag values from the device are used.
         "MyDate" : "2019-07-23 15:00",
         "MyTimezone" : "Asia/Dubai"
        }
      }
    ]
  }
}
```
</TabItem>
<TabItem label="Output"> <img src="/personalization-liquid-templates-7.webp" alt="Personalized date output in push notification" width="200"/>
</TabItem>
</Tabs>


## Connected content

Connected content is a feature in Liquid templates that allows you to dynamically retrieve and use data from an external source, such as a web service, directly within your email or push notification messages. This feature enables real-time personalization by fetching JSON data from a specified URL and saving it to a variable that can be utilized in your content.

#### Key use cases

- **Product recommendations**: Display personalized product lists tailored to each user.

- **Promo codes**: Insert unique promo codes generated by a backend service.

#### Prerequisites

* To use Connected Content, you must have your own backend service that generates and provides the required data (e.g., promo codes, product recommendations) based on **User ID, HWID, or custom tags**. Pushwoosh then fetches this data before sending a message.

### Step-by-step implementation guide


#### Step 1. Set up backend service

The backend service should:

* Accept a request containing user-specific parameters (e.g., `userId`). Connected Content supports `UserID`, `HWID`, or any custom tags you’ve set up in your project.
* Return a JSON response with the required data. This content can then be inserted dynamically into messages

<Aside type="note" title="How it works">

The backend service acts as a data provider, responding to HTTP requests with user-specific information.

1. Pushwoosh sends a request to your backend, passing user-specific identifiers as query parameters.
2. Your backend processes the request and retrieves the requested data.
3. Your backend returns a JSON response.
4. Before sending a message, Pushwoosh fetches the JSON response from the backend service and uses the returned values (e.g., the `code`) in the message content dynamically.

**Example response**

```
{ "code": "SPECIALOFFERFORUSER12345" }
```
</Aside>



#### Step 2. Create a preset with Сonnected content in Pushwoosh

1. In the [Push](/product/content/push-presets/) or [Email content editor](/product/content/email-content/drag-and-drop-email-editor/), insert the Connected Content syntax into the message field.

**Example**

```
{% connected_content http://your-backend-url.com?userId={{ ${userid} }} :save result %}
```
**Syntax breakdown**
|  |  |
| ----- | ----- |
| `connected_content` | Fetches JSON data from the specified backend URL. |
|    `http://your-backend-url.com` | The backend endpoint that returns required data in JSON format. |
| `userId={{ ${userid} }}` | A dynamic query parameter that passes the user ID to the backend. |
| `:save result` | Stores the fetched JSON response in the result variable for use in Liquid templates |

![Insert the Connected Content syntax](/connectedcontent.webp)

**Authentication (optional)**

If your backend service requires authentication, you can include an API key or token in the Connected Content request to ensure secure access.

```
{% connected_content http://your-backend-url.com?userId={{ ${userid} }}&auth=YOUR_API_KEY :save result %}
```

You can also send authentication (or any other) data as HTTP headers using the optional `:headers` parameter — a JSON object of header names and values.

```
{% connected_content http://your-backend-url.com?userId={{ ${userid} }} :headers {"Authorization": "Bearer YOUR_TOKEN", "X-Api-Key": "YOUR_API_KEY"} :save result %}
```
|  |  |
| ----- | ----- |
| `:headers {...}` | A JSON object of HTTP headers sent with the request, e.g. `Authorization: Bearer <token>`. |

<Aside type="caution" title="Static values only">
`${}` personalization variables work only inside the URL. Values inside `:headers` are static and are not interpolated.
</Aside>

**Using tags in Connected content**

To include custom tags, insert them as query parameters in the **Connected Content** request (`{{ tag_name }}`).

```
{% connected_content http://your-backend-url.com?userId={{ ${userid} }}{{ Language }} :save result %}
```

2. Next, add the message text incorporating the **retrieved data**, like this:

```

Hey, {{userid}}, grab your personal promo code - {{result.code}}
```

![Add the message text with the **retrieved data**](/connectedcontent-1.webp)

3. After finalizing the message content and configuring the preset settings, save it for reuse in campaigns.

<video src="/connectedcontent-2.webm" title="Send a message with connected content" autoplay loop muted playsinline />

#### Step 3. Send a message using the configured preset

Send a message with this preset using the [one-time push](/product/messaging-channels/push-notifications/send-push-notifications/one-time-push/#how-to-send-a-push-notification-using-the-one-time-push-form) or [email form](/product/messaging-channels/emails/send-email/#how-to-send-a-one-time-email) or [customer journey](/product/customer-journey/pushwoosh-journey-overview/).

<Aside type="caution" title="Important">
If the service returns a status other than HTTP 200 OK, the email or push notification will not be sent. This ensures that your communication only goes out if the necessary data is successfully retrieved.
</Aside>