Using Liquid syntax
Learn how to personalize message content in OneSignal using Liquid syntax across email, push notifications, SMS, in-app messages, and Live Activities.
Liquid is a templating language supported by OneSignal to personalize messages across channels including email, push, SMS, in-app, and Live Activities. It uses tags, filters, and conditionals to dynamically customize message content.
To learn more about Liquid syntax, see the official Liquid documentation.
Supported fields for Liquid syntax
- Subject, Reply-to, and Pre-header
- Message Body
- Image substitution in HTML blocks. Example:
<img src="{{image_url}}"/>
- Subject, Reply-to, and Pre-header
- Message Body
- Image substitution in HTML blocks. Example:
<img src="{{image_url}}"/>
- Title (
headings
), Subtitle, Body (contents
) - Image URL
- Launch URL. Example:
https://example.com/{{last_category_viewed}}
- Additional
data
doesn’t support Liquid syntax.
- Message Body (
contents
)
- Only Tag substitution is supported at this time.
- Text, Button, Image Blocks.
- Within the
event_updates
,contents
andheadings
properties.
Basic syntax
Liquid uses two main syntax structures:
- Output Tags:
{{ ... }}
- Display data from a variable or object. - Logic Tags:
{% ... %}
- Execute conditional statements or loops.
Data sources
Source | Example | Set via |
---|---|---|
Tag | {{ first_name }} | OneSignal SDK or API (tags ) |
Property | {{ subscription.email }} | System-managed (email, external_id, language) |
Custom Data | {{ message.custom_data.key }} | Passed in API call to create message |
See Message personalization for more information on data sources.
Conditionals
Operators
==
,!=
,>
,<
,>=
,<=
and
,or
contains
(string or array)
Operations run right to left. Parentheses are not supported.
if
, elsif
, else
unless
Filters
Apply filters using {{ variable | filter }}
to adjust how the data is displayed.
default
Assign a default value if the property is empty or does not exist.
date
The date filter converts a timestamp into another date format. The format for this syntax is the same as strftime. The input uses the same format as Ruby’s Time.parse.
Set dates as a unix timestamp in seconds with tags. This allows for use of both liquid syntax personalization and segmentation with Time Operators. For example, a tag might look like: bill_due : 1687968776
Date formatting works on strings if they contain well-formatted dates.
To get the current time, pass the special word now
(or today
) along with the date filter.
The current time will be rendered in the message based on when the message is sent to the recipient. If you are testing the message, you will see the current time as when the test message was sent.
capitalize
This filter makes the first character of a string capitalized and converts the remaining characters to lowercase.
round
This filter rounds a number to the nearest integer, or, if a number is passed as an argument, to that number of decimal places.
pluralize
This filter returns the singular or plural form of a string based on a given number. The number must be a whole number and can be provided as a string. Both the singular and plural forms of a string must be provided.
Iteration
for
loops
Repeatedly executes a block of code. For a full list of attributes available within a for
loop, refer to the for
loop object.
While powerful and flexible, the usage of for
loops in liquid syntax can lead to poor notification delivery performance in certain rare cases. Be mindful of your usage of for
loops. Also note that we prevent the usage of for
loops in a few Push Channel fields: contents
, headings
, subtitle
, apns_alert
, and url
limit
& offset
Limits the loop to the specified number of iterations. For example, if you only want to show 4 products in a message, you could use Limits and Offsets to specify the number of products shown.
To begin the loop at the specified index, add an offset value:
where
Creates an array including only the objects with a given property value, or any truthy value by default.
In this example, assume you have a list of products and you want to show your kitchen products separately. Using where
, you can create an array containing only the products that have a type
of kitchen
.
String Manipulation
Occasionally you may have data tags that contain strings that is in a format that is not suitable to be shown directly to your users, and you may need to manipulate the string to adjust the format. Below is a table of liquid syntax commands that can be used to adjust strings. You can use string manipulation both on Tags and directly on strings written into the message.
Command | Description | Example | Example Output |
---|---|---|---|
replace | Replaces a substring with another string. | {{ 'hello world' | replace: 'world', 'there' }} | hello there |
capitalize | Capitalizes the first letter of a string. | {{ 'hello' | capitalize }} | Hello |
upcase | Converts a string to uppercase. | {{ 'hello' | upcase }} | HELLO |
downcase | Converts a string to lowercase. | {{ 'HELLO' | downcase }} | hello |
strip | Removes leading and trailing whitespace from a string. | {{ ' hello ' | strip }} | hello |
strip_html | Removes all HTML tags from a string. | {{ '<p>hello</p>' | strip_html }} | hello |
truncate | Shortens a string to a specified length, adding an ellipsis (…) if needed. | {{ 'This is a long sentence' | truncate: 10 }} | This is a… |
truncatewords | Truncates a string after a certain number of words. | {{ 'This is a long sentence' | truncatewords: 2 }} | This is… |
replace_first | Replaces the first occurrence of a substring. | {{ 'hello world' | replace_first: 'world', 'there' }} | hello there |
prepend | Adds a string to the beginning of another string. | {{ 'world' | prepend: 'hello ' }} | hello world |
append | Adds a string to the end of another string. | {{ 'hello' | append: ' world' }} | hello world |
lstrip | Removes leading whitespace from a string. | {{ ' hello' | lstrip }} | hello |
rstrip | Removes trailing whitespace from a string. | {{ 'hello ' | rstrip }} | hello |
FAQ
Why is substitution not working?
- In-App Messages do not support property substitution.
- Tag substitution does not work when using “Send Test Message”.
- Tag keys must be alphanumeric, or use _ and - (no periods or spaces).
- Substitution does not appear in preview mode — send a real message to test.
How to control whitespace and newlines?
Use hyphens: {{- ... -}}
, {%- ... -%}
to trim surrounding whitespace.
See Whitespace control for more details.
How to handle user-generated content?
Wrap user-generated text in {% raw %}
and {% endraw %}
to prevent Liquid parsing. See “raw” syntax.