Formatting and Transforming Data
Last updated March 23, 2026
Filters are data transformers that you apply to a value using the pipe (|) syntax. They take the value on the left, process it, and output the result. You can chain multiple filters together for more complex transformations.
You can find the complete list of built-in filters in the official Liquid documentation.
Built-in filters
append
Read the complete append documentation.
Adds the specified string to the end of another string.
{{"/my/fancy/url" | append: ".html"}}
→ /my/fancy/url.html
date
Read the complete date documentation.
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.
{{article.published_at | date: "%a, %b %d, %y"}}
→ Fri, Jul 17, 22
{{article.published_at | date: "%Y"}}
→ 2022
date works on strings if they contain well-formatted dates:
{{"March 14, 2022" | date: "%b %d, %y"}}
→ Mar 14, 22
To get the current time, pass the special word "now" (or "today") to date:
Last update: {{"now" | date: "%Y-%m-%d %H:%M"}}
→ Last update: 2022-03-14 12:34
Need a timezone?
in_time_zone filter provided by PDFMonkey.default
Read the complete default documentation.
Sets a default value for any variable with no assigned value. default will show its value if the input is nil, false, or empty.
When product_price is not defined, the default value is used:
{{product_price | default: 2.99}}
→ 2.99
When product_price is defined, the default value is not used:
{% assign product_price = 4.99 %}
{{product_price | default: 2.99}}
→ 4.99
When product_price is empty, the default value is used:
{% assign product_price = "" %}
{{product_price | default: 2.99}}
→ 2.99
Math filters
plus, minus, times, divided_by, round, ceil, and floor are covered in the dedicated How to do Maths page.newline_to_br
Read the complete newline_to_br documentation.
Inserts an HTML line break (<br />) in front of each newline () in a string.
{{"Hello\nWorld" | newline_to_br}}
→ Hello<br />
World
where
Read the complete where documentation.
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".
All products:
{% for product in products %}
- {{ product.title }}
{% endfor %}
{% assign kitchen_products = products | where: "type", "kitchen" %}
Kitchen products:
{% for product in kitchen_products %}
- {{ product.title }}
{% endfor %}
All products:
- Vacuum
- Spatula
- Television
- Garlic press
Kitchen products:
- Spatula
- Garlic press
PDFMonkey filters
Array filters
push
Adds an item to an array.
{% assign arr = "earth wind" | split: " " %}
{% assign arr = arr | push: "fire" %}
{{arr | to_sentence}}
→ earth, wind and fire
slice_by
Slices an array in groups of N elements.
{% assign reindeers = "Dasher Dancer Prancer Vixen Comet Cupid Donner Blitzen Rudolph" | split: " " %}
{% assign reindeerPairs = reindeers | slice_by: 2 %}
{% for reindeerPair in reindeerPairs %}
Pair:
{% for reindeer in reindeerPair %}
- {{reindeer}}
{% endfor %}
{% endfor %}
Pair:
- Dasher
- Dancer
Pair:
- Prancer
- Vixen
Pair:
- Comet
- Cupid
Pair:
- Donner
- Blitzen
Pair:
- Rudolph
sum
Returns the sum of a numbers array.
Let’s say you have this in your data:
{
"array": [1, 2, 3, 4, 5]
}
{{array | sum}}
→ 15
to_sentence
Converts the array to a comma-separated sentence where the last element is joined by the connector word.
{% assign arr = "earth wind" | split: " " %}
{% assign arr = arr | push: "fire" %}
{{arr | to_sentence}}
→ earth, wind and fire
{{arr | to_sentence: ' - '}}
→ earth - wind and fire
{{arr | to_sentence: ' - ', 'and finally '}}
→ earth - wind and finally fire
where_exp
Similar to Liquid’s where but accepts an expression.
Let’s start with the data:
{
"products": [
{ "name": "Product 1", "price": 1.00 },
{ "name": "Product 2", "price": 2.00 },
{ "name": "Product 3", "price": 3.00 },
{ "name": "Product 4", "price": 2.00 },
{ "name": "Product 5", "price": 1.00 }
]
}
{% assign cheapProducts = products | where_exp: "prod", "prod.price < 1" %}
{% for product in cheapProducts %}
- {{product.name}}
{% endfor %}
- Product 1
- Product 5
Date and time filters
in_time_zone
Shifts a date to the given timezone before formatting.
{{"2050-01-02 12:34:56" | in_time_zone: "Pacific/Galapagos" | date: "%Y-%m-%d %H:%M"}}
→ 2050-01-02 06:34
URL filters
ensure_protocol
You might get asset URLs that don’t include any protocol. Sadly our rendering engine doesn’t support this type of URL. For this reason we provide ensure_protocol that will add a protocol as needed:
{{"//example.com/some-picture.jpg" | ensure_protocol}}
→ https://example.com/some-picture.jpg
{{"//example.com/some-picture.jpg" | ensure_protocol: "http"}}
→ http://example.com/some-picture.jpg
{{"http://example.com/some-picture.jpg" | ensure_protocol}}
→ http://example.com/some-picture.jpg
Number filters
See also How to do Maths for arithmetic filters and practical calculation patterns.
format
The format filter is useful for advanced number formatting. For simpler formatting, prefer with_delimiter.
{{5 | format: "%05d"}}
→ 00005
{{5 | format: "%08.3f"}}
→ 0005.000
{{5 | format: "%.2f"}}
→ 5.00
{{5.1234 | format: "%.2f"}}
→ 5.12
with_delimiter
For basic number formatting like money for instance, the with_delimiter filter will help you set a thousand delimiter, a decimal separator and the precision.
Basic usage — adds a comma every three digits by default:
{{12345678 | with_delimiter}}
→ 12,345,678
{{1234.567 | with_delimiter}}
→ 1,234.567
Non-numeric text is left untouched:
{{'12345a' | with_delimiter}}
→ 12345a
Custom delimiter — change the thousands separator:
{{12345678 | with_delimiter, delimiter: " "}}
→ 12 345 678
Precision — control decimal places:
{{12345678 | with_delimiter, precision: 2}}
→ 12,345,678.00
{{1234.567 | with_delimiter, precision: 2}}
→ 1,234.57
Stripping trailing zeros:
{{12345678 | with_delimiter, precision: 2, strip_insignificant_zeros: true}}
→ 12,345,678
{{1234.567 | with_delimiter, precision: 2, strip_insignificant_zeros: true}}
→ 1,234.57
Combining options — for example, European-style formatting:
{{1234.567 | with_delimiter,
delimiter: " ",
separator: ",",
precision: 2,
strip_insignificant_zeros: true
}}
→ 1 234,57
{{1234.003 | with_delimiter,
delimiter: " ",
separator: ",",
precision: 2,
strip_insignificant_zeros: true
}}
→ 1 234
HTML filters
entities
This filter can be very useful if you have to deal with accented or special characters inside the header or footer. It will convert any non-latin character to its HTML entity.
{{"Marie Skłodowska Curie" | entities}}
→ Marie Skłodowska Curie
JSON filters
json
If you need to insert dynamic data in its original JSON format (like we do for charts for instance) the json filter is what you need. Notice it’s returning a string, not the object itself.
{{'banana, apple' | split: ', ' | json}}
→ ["banana", "apple"]
parse_json
Parses a JSON string into a usable object or array. This is especially handy when an integration (such as Glide or a webhook) can only send flat string values — you can pass structured data as a JSON string and parse it in the template.
{% assign obj = '{ "key": "value" }' | parse_json %}
{{obj.key}}
→ value
You can also parse arrays and loop over them:
{% assign items = '[{"name":"Waffle","qty":12},{"name":"Donut","qty":5}]' | parse_json %}
{% for item in items %}
{{item.name}} x{{item.qty}}
{% endfor %}
→ Waffle x12
Donut x5
If the input is empty or not valid JSON, parse_json returns nil by default. You can pass a fallback value as an argument:
{% assign data = invalidVariable | parse_json: "fallback" %}
{{data}}
→ fallback
Typical use case
parse_json to get a proper array you can loop over. See the Glide line items workaround for a complete example.Frequently asked questions
- How do I format numbers with thousand separators in PDFMonkey?
- Use the with_delimiter filter. For example, {{ 12345678 | with_delimiter }} outputs 12,345,678. You can customize the delimiter, decimal separator, and precision with named arguments.
- How do I format dates in a PDFMonkey Liquid template?
- Use the date filter with strftime format codes. For example, {{ article.published_at | date: "%b %d, %Y" }}. To convert to a specific timezone first, chain the in_time_zone filter before date.
- How do I parse a JSON string inside a PDFMonkey template?
- Use the parse_json filter to convert a JSON string into an object or array you can loop over. For example: {% assign items = jsonString | parse_json %}. This is especially useful when integrations like Glide can only send flat string values.
- How do I handle accented characters in PDFMonkey headers and footers?
- Use the entities filter to convert non-Latin characters to HTML entities. For example, {{ company.name | entities }} converts “é” to é, which renders correctly in settings-based headers and footers.