Liquid filters
The 16 filters the platform registers: signature, input and output, an example, and RTL notes.
On this page
Alongside the standard LiquidJS filters (upcase, date, default, plus, size, …) the platform registers the following. The mode is strict: an unknown filter fails the render. Every {{ }} output is escaped; only the filters marked safe below emit raw HTML.
Money#
money#
{{ product.price | money }}Input is a money object (or a number in minor units, treated as USD). Output is safe: <span class="money-value" data-amount-minor="250000" data-currency="SYP">…</span> with the formatted text inside. The two data attributes let the browser-side currency converter re-render in the visitor's currency. Western digits, symbol before the amount, bidi-wrapped; with the arabic_numerals setting the digits become Eastern Arabic.
money_with_currency#
{{ cart.subtotal | money_with_currency }}The same formatted text without any markup. It does not convert with the visitor's currency; use it in alt, title and the like.
money_amount#
{{ product.price | money_amount }}A bare decimal string in major units ("185000" or "12.50") with no symbol and no wrapping, for machine consumers: JSON-LD and meta tags. Always Western digits.
money_major: CURRENCY#
{{ theme_settings.free_shipping_threshold | money_major: cart.subtotal.currency }}Formats a major-unit number the merchant typed (a free-shipping threshold, say) with the same markup money emits, so it converts with the visitor's currency too. Safe.
Media and files#
img_url: WIDTH#
<img src="{{ product.image_url | img_url: 400 }}"
srcset="{{ product.image_url | img_url: 400 }} 400w, {{ product.image_url | img_url: 800 }} 800w"
sizes="(max-width: 600px) 100vw, 400px" alt="{{ product.name }}">The image-CDN contract: on the platform media origin it emits a resized URL with the width snapped up to a fixed ladder (96, 128, 200, 400, 600, 800, 1200, 1600), automatic format and quality 72; on any other origin it adds a ?w= hint. A missing width means 400. Never build transform URLs by hand; the URL is an internal shape and the filter is the contract.
asset_url#
<img src="{{ section.settings.image | asset_url }}" alt="{{ section.settings.image | file_alt }}">The only way a stored file reference (an image or video setting) becomes a URL. Absolute values, schemes and .. traversal return ""; without a configured base it returns "" so the theme falls into its placeholder state.
file_alt and file_focal_style#
<img src="{{ block.settings.image | asset_url }}" alt="{{ block.settings.image | file_alt }}"
style="{{ block.settings.image | file_focal_style }}">They read the alt text, focal point (object-position: X% Y%) and dominant color (background-color) set per file in the media library. The file_focal_style value is ready for a style attribute and sanitized on the server.
Text#
t#
{{ 'product.add_to_cart' | t }}A lookup in the current locale's table from locales/<locale>.json with dotted keys. A missing key returns the key itself and never throws.
richtext#
<div class="prose">{{ section.settings.body | richtext }}</div>The only way merchant-typed HTML is output. It re-sanitizes at render, whatever the source, down to p br strong em u s ul ol li h2 h3 blockquote a, with dir and text-align only on block tags, and https:/mailto:/tel:/absolute-path links. Safe. Limit 10,000 characters.
strip_html#
{{ product.description | strip_html | truncate: 160 }}Removes tags, decodes the basic entities and normalizes whitespace; the output is plain text escaped like any output. For descriptions in JSON-LD and meta tags.
json#
<script type="application/ld+json">{ "name": {{ product.name | json }} }</script>Serializes the value to JSON with <, >, & and the U+2028/U+2029 line separators escaped as \u sequences, so it is valid inside a JSON-LD block and in any context. Safe.
Links#
tel_href and wa_href#
<a href="{{ theme_settings.phone | tel_href }}">{{ theme_settings.phone }}</a>
<a href="{{ store.whatsapp_number | wa_href }}">{{ 'contact.whatsapp' | t }}</a>The only way a phone number becomes a link: the input is reduced to digits (with one leading + for tel:), so a merchant value can never smuggle a scheme. Empty in, empty out.
Dates#
date_localized: LOCALE#
{{ review.created_at | date_localized: request.locale }}A YYYY-MM-DD date as readable text: Levantine month names in Arabic, plain English otherwise. Anything not in the date shape passes through.
Neutralized#
raw#
The built-in LiquidJS raw filter is neutralized and returns its value as plain text that gets escaped; writing | raw in a template is rejected at push anyway. There is no path to raw HTML from theme or store data outside the safe filters above.