TemplatesTemplate variables and Liquid

Template variables and Liquid

Copy page

The data a template can print for an order, a product or a customer, the brand object, the money, percent and br filters, and what Liquid in a document template does not support.

A template is HTML with Liquid tags. When a document is generated, the Liquid is filled with the data of one order, one product or one customer, plus your shop and your branding. This page lists what a template can print and which filters it can use.

The editor shows the same list for the template you have open: the Variables card under the code has a short introduction and the full list of variables to expand.

What every template sees

Object What it holds
order, product or customer The one the template renders, set with Renders on the Settings tab
shop Your store: shop.name, shop.email, shop.currency, shop.domain, shop.url, shop.address
brand Your branding from Settings, see below
language The language the document is made for, see Templates in several languages

Print a value with double braces and loop over a list with for:

xml
<h1>Invoice {{ order.name }}</h1>

{% for line in order.line_items %}
  <p>{{ line.quantity }} x {{ line.title }} - {{ line.discounted_total | money }}</p>
{% endfor %}

<p>Total: {{ order.total_price | money }}</p>

Order

For templates that render An order.

Variable What it holds
order.name The order number, for example #1001
order.id The Shopify id of the order
order.created_at, order.processed_at Dates, print them with the date filter
order.email, order.phone Contact details on the order
order.note, order.po_number, order.tags Note, purchase order number and tags
order.customer_locale The language the customer ordered in
order.currency The currency code
order.financial_status, order.fulfillment_status For example PAID and UNFULFILLED
order.customer first_name, last_name, name, email
order.billing_address, order.shipping_address name, company, address1, address2, zip, city, province, country, country_code, phone
order.shipping_method The title of the shipping line
order.payment_gateways, order.discount_codes Lists of text
order.subtotal_price, order.shipping_price, order.total_tax, order.total_discounts, order.total_price, order.total_refunded Amounts as numbers
order.tax_lines A list, each with title, rate, price
order.line_items A list, see the next table

Each entry of order.line_items:

Variable What it holds
title, variant_title, sku, vendor Text
quantity Number
unit_price, discounted_unit_price Price of one unit, before and after discounts
total, discounted_total Line total, before and after discounts
tax_lines A list, each with title, rate, price
image_url The line item's image, when it has one

A document carries up to 250 line items of an order.

Product

For templates that render A product.

Variable What it holds
product.title, product.handle, product.vendor, product.product_type Text
product.description_html The description as you wrote it, as HTML. Print it with the raw filter
product.tags, product.status Tags and status, for example ACTIVE
product.created_at, product.updated_at Dates
product.url The product page in your online store, when it is published there
product.image_url The featured image
product.options A list, each with name and values
product.currency, product.min_price, product.max_price The price range
product.variants A list, each with id, title, sku, barcode, price, compare_at_price, inventory_quantity, options (each name and value) and image_url

A document carries up to 100 variants of a product.

Customer

For templates that render A customer.

Variable What it holds
customer.name, customer.first_name, customer.last_name Name
customer.email, customer.phone Contact details
customer.note, customer.tags Note and tags
customer.locale The customer's language
customer.created_at Date
customer.address The default address, with the same fields as an order address
customer.orders_count, customer.amount_spent, customer.currency Totals
customer.orders The 20 most recent orders, newest first, each with id, name, created_at, financial_status, fulfillment_status, total_price

The brand object

Your branding from Settings is available in every template, as the brand object and as CSS variables. See Branding your documents for where the values come from.

Variable What it holds
brand.logo_url, brand.logo_width Your logo and the width it is printed at. logo_url is empty when no logo is uploaded
brand.company_name, brand.address, brand.tax_id, brand.footer_text Your company details. Empty text when a field is not filled
brand.primary_color, brand.accent_color, brand.text_color, brand.muted_color, brand.border_color Hex colors
brand.font_family, brand.heading_font_family, brand.font_size Body font, heading font and base font size

In CSS, use the variables instead: var(--brand-primary), var(--brand-accent), var(--brand-text), var(--brand-muted), var(--brand-border), var(--brand-font), var(--brand-heading-font) and var(--brand-font-size). The page already uses your body font, base size and text color, and your heading font on headings, so a template only needs them for its own accents.

xml
{% if brand.logo_url %}
  <img src="{{ brand.logo_url }}" width="{{ brand.logo_width }}" alt="">
{% else %}
  <strong>{{ brand.company_name | default: shop.name }}</strong>
{% endif %}

<p>{{ brand.address | br }}</p>

Filters

Amounts are plain numbers and text is escaped, so three filters of our own do the formatting:

Filter What it does Example
money Formats an amount as money, in the currency of the order, product or customer and for the language of the document order.total_price with money prints an amount such as 64.70 with the currency symbol
money: "USD" The same with a currency code you choose. It only changes the format, it does not convert the amount
percent Turns a rate into a percentage A tax rate of 0.19 prints as 19%
br Keeps the line breaks of a text with several lines brand.address with br prints one line per row
raw Prints HTML as it is, without escaping product.description_html with raw

The standard Liquid filters work too, for example date, default, upcase, plus, times, size, join and first.

perl
{{ order.processed_at | date: "%Y-%m-%d" }}

{% for tax in order.tax_lines %}
  {{ tax.title }} {{ tax.rate | percent }}: {{ tax.price | money }}
{% endfor %}

{{ product.description_html | raw }}

The language variable

language holds the language the document is made for: the Language of the Flow action when it is filled, else the language of the order's customer or of the customer, else the template's main language. Amounts are formatted for it.

xml
{% if language == "de" %}
  <h1>Rechnung {{ order.name }}</h1>
{% else %}
  <h1>Invoice {{ order.name }}</h1>
{% endif %}

For more than a few words, give each language its own HTML instead. See Templates in several languages.

What Liquid in a template does not support

A document template is one self-contained HTML file. Some things you may know from Shopify themes are not available:

  • No includes, partials or layouts. The tags render, include, layout and block are refused when you save.
  • No theme objects or theme filters. Only the data on this page exists. An unknown filter is reported as an error with its line, it is not ignored.
  • No scripts. JavaScript in a template does not run, neither in the preview nor in the PDF.
  • Images need absolute URLs, for example a file from your Shopify Files or brand.logo_url.
  • Limits. The HTML can be up to 200 KB and the CSS up to 100 KB, and a template has 3 seconds to render.

A variable that does not exist prints nothing. Check values that can be empty with if before you print a label for them.

Next steps