Conditions code editor
Available for "Custom Sections" widget, contact support to get access to it.
Liquid Template Editor Guide
This guide explains how to write Liquid templates in our editor, including available objects, tags, and best practices.
Template Structure
Liquid templates support three main types of markup:
Output
Display dynamic content using double curly braces:
{{ cart.cost.total }}
Control Tags
Control flow using special tags:
{% if customer.loggedIn %}
Hello, customer!
{% endif %}
Comments
Document your code:
{# Quick inline comment #}
{% comment %}
Detailed explanation here
{% endcomment %}
Available Objects
Lines
The lines
array contains information about each item in the cart. Each line item represents a product variant with its quantity and associated data.
Properties
id
Type:
string
Description: Unique identifier for the line item
Example:
"gid://shopify/LineItem/12345"
quantity
Type:
number
Description: Number of items of this variant in the cart
Example:
2
cost
Type:
object
Description: Cost information for this line item
Properties:
totalAmount.amount
(number
): Total cost for this line item including quantity
merchandise
Type:
object
Description: Product variant information
Properties:
id
(string
): Variant identifiertitle
(string
): Product variant titleselectedOptions
(array
): Selected variant optionsname
(string
): Option name (e.g., "Size")value
(string
): Option value (e.g., "Small")
product
(object
): Parent product informationid
(string
): Product identifiervendor
(string
): Product vendor nameproductType
(string
): Product category/type
requiresShipping
(boolean
): Whether the item needs shippingsku
(string
): Stock keeping unit
attributes
Type:
array
Description: Custom attributes attached to the line item
Properties:
key
(string
): Attribute keyvalue
(string
): Attribute value
Usage Example
{% for line in lines %}
ID: {{ line.id }}
Quantity: {{ line.quantity }}
Total: {{ line.cost.totalAmount.amount }}
{# Access variant details #}
{{ line.merchandise.title }}
SKU: {{ line.merchandise.sku }}
{# Show selected options #}
{% for option in line.merchandise.selectedOptions %}
{{ option.name }}: {{ option.value }}
{% endfor %}
{% endfor %}
Cart
The cart
object contains overall information about the shopping cart, including totals and metadata.
Properties
currency
Type:
string
Description: The currency code for the cart
Example:
"USD"
note
Type:
string
Description: Customer notes attached to the cart
Example:
"Please gift wrap"
attributes
Type:
array
Description: Custom attributes for the entire cart
Properties:
key
(string
): Attribute keyvalue
(string
): Attribute value
quantity
Type:
number
Description: Total number of items in the cart
Example:
5
cost
Type:
object
Description: Detailed cost breakdown
Properties:
total
(number
): Final cart total including all costssubtotal
(number
): Sum of line items before tax/shippingtax
(number
): Total tax amountshipping
(number
): Shipping cost
Usage Example
Cart Summary:
Total Items: {{ cart.quantity }}
Subtotal: {{ cart.cost.subtotal }}
Tax: {{ cart.cost.tax }}
Shipping: {{ cart.cost.shipping }}
Total: {{ cart.cost.total }}
{% if cart.note != blank %}
Note: {{ cart.note }}
{% endif %}
Customer
The customer
object provides information about the current user's status and preferences.
Properties
loggedIn
Type:
boolean
Description: Whether the customer is currently authenticated
Example:
true
acceptsEmailMarketing
Type:
boolean
Description: Customer's email marketing preference
Example:
true
acceptsSmsMarketing
Type:
boolean
Description: Customer's SMS marketing preference
Example:
false
Usage Example
{% if customer.loggedIn %}
Welcome back!
Marketing Preferences:
{% if customer.acceptsEmailMarketing %}
✓ Email updates enabled
{% endif %}
{% if customer.acceptsSmsMarketing %}
✓ SMS updates enabled
{% endif %}
{% endif %}
Shipping
The shipping
object contains information about shipping methods and address details.
Properties
state
Type:
string | null
Description: Shipping destination state/province code
Example:
"AL"
country
Type:
string | null
Description: Shipping destination country code
Example:
"US"
selected
Type:
object
Description: Currently selected shipping method
Properties:
label
(string | null
): Display name of the shipping methodtype
('shipping' | 'local' | 'pickup' | 'pickupPoint' | null
): Display type of the shipping method
target
Type:
object | null
Description: Target shipping method information. Only works when the widget is added under Delivery methods.
Properties:
isCurrentSelected
(boolean
): Whether this method is selectedcode
(string
): Shipping method identifiertitle
(string
): Display namecost.amount
(number
): Shipping cost amount
Usage Example
Shipping to: {{ shipping.state }}, {{ shipping.country }}
{% if shipping.selected %}
Selected Method: {{ shipping.selected.label }}
Cost: {{ shipping.target.cost.amount }}
{% else %}
Please select a shipping method
{% endif %}
Order
The order
object contains information about the current order being processed.
Properties
payment.selected
Type:
object
Description: Selected payment method information
Properties:
type
('creditCard' | 'deferred' | 'local' | 'manualPayment' | 'offsite' | 'other' | 'paymentOnDelivery' | 'redeemable' | 'wallet' | 'customOnsite' | null
): Payment method type
metafields
Type:
array
Description: Additional custom data attached to the order
Properties:
key
(string
): Metafield identifiervalue
(string
): Metafield valuenamespace
(string
): Grouping namespace. use "checkoutbuilder" to access fields created with "Custom fields" widget.
Usage Example
Payment Method: {{ order.payment.selected.type }}
Order Details:
{% for field in order.metafields %}
{% if field.namespace == "checkoutbuilder" %}
{{ field.key }}: {{ field.value }}
{% endif %}
{% endfor %}
Filters
The editor supports various filters to transform values. Filters are applied using the pipe character (|
).
String Filters
replace
Replaces all occurrences of a substring
search
(string, required)
replace
(string, required)
upcase
Converts string to uppercase
None
downcase
Converts string to lowercase
None
capitalize
Capitalizes the first character
None
append
Appends a string to the end
suffix
(string, required)
prepend
Prepends a string to the beginning
prefix
(string, required)
strip
Removes whitespace from both ends
None
split
Splits a string into an array
separator
(string, required)
Example
{% assign title = "hello world" %}
{{ title | capitalize | replace: "world", "everyone" }}
Output: "Hello everyone"
{{ " spaces " | strip }}
Output: "spaces"
Number Filters
ceil
Rounds up to nearest integer
None
floor
Rounds down to nearest integer
None
round
Rounds to nearest integer
None
divided_by
Divides by a number
divisor
(number, required)
minus
Subtracts a number
subtrahend
(number, required)
plus
Adds a number
addend
(number, required)
times
Multiplies by a number
multiplier
(number, required)
Example
{{ 4.6 | ceil }}
Output: 5
{{ 10 | divided_by: 3 | round }}
Output: 3
{{ product.price | times: 0.8 | round }}
Output: Price with 20% discount
Array Filters
first
Returns the first element
None
last
Returns the last element
None
join
Joins elements with a separator
separator
(string, optional, default: " ")
size
Returns array length
None
Example
{% assign fruits = "apple,banana,orange" | split: "," %}
{{ fruits | join: " and " }}
Output: "apple and banana and orange"
{{ fruits | first }}
Output: "apple"
{{ fruits | size }}
Output: 3
Filter Chaining
You can chain multiple filters together. They are applied from left to right.
{{ "hello world" | capitalize | replace: "world", "everyone" | append: "!" }}
Output: "Hello everyone!"
⚠️ Important Notes
Maximum 3 filters per variable (see complexity rules)
Filters must match the input type they accept
Some filters change the value type (e.g.,
split
converts string to array)Use intermediate variables for complex transformations
Control Flow
Conditional Tags
Available tags:
if
/elsif
/else
/endif
unless
/endunless
Example:
{% if cart.cost.total > 100 %}
High-value cart
{% elsif cart.cost.total > 50 %}
Medium-value cart
{% else %}
Standard cart
{% endif %}
Loops
Available controls:
for
/endfor
break
continue
⚠️ Important Limitations
Maximum 20 iterations per loop
No nested loops allowed
Range loops limited to 20 steps:
(1..20)
Example:
{% for line in lines %}
{{ line.merchandise.title }}
{% if line.quantity > 10 %}{% break %}{% endif %}
{% endfor %}
Show/Hide System
Basic Usage
Templates are hidden by default and must be explicitly shown:
{% if cart.cost.total > 100 %}
{% show %}
{% endif %}
{% if cart.quantity == 0 %}
{% hide %}
{% endif %}
📝 Key Rules
First show/hide tag wins
Processing stops at show/hide
Default state is hidden
Template Complexity
Limits
{
TOTAL_MAX: 50, // Max complexity score
LOOPS_MAX: 5, // Max loops
NESTING_MAX: 3, // Max nesting
CONDITIONS_MAX: 10, // Max conditions
ASSIGNMENTS_MAX: 15, // Max assignments
FILTERS_PER_VAR: 3 // Max filters per variable
}
Scoring
Each element adds to complexity:
Loop: +5 points
Condition: +2 points
Assignment: +1 point
Filter: +1 point
Large range loop: +3 extra points
Best Practices
1. Optimize Loops
Pre-calculate values outside loops:
{% assign total_cost = cart.cost.total %}
{% for line in lines %}
{% if line.cost.totalAmount.amount > total_cost | divided_by: 2 %}
High-value item: {{ line.merchandise.title }}
{% endif %}
{% endfor %}
2. Use Early Exits
Exit early when possible:
{% if cart.quantity == 0 %}
{% hide %}
{% endif %}
3. Keep Filters Simple
Avoid long filter chains:
{# Good #}
{% assign title = line.merchandise.title | upcase %}
{{ title | replace: "OLD", "NEW" }}
{# Avoid #}
{{ line.merchandise.title | upcase | replace: "OLD", "NEW" | strip }}
4. Handle Null Values
Always check for null:
{% if shipping.selected %}
{{ shipping.selected.label }}
{% else %}
Select shipping method
{% endif %}
5. Document Complex Logic
Use comments for clarity:
{% comment %}
Express shipping requirements:
- Cart total > 100
- All items need shipping
- Customer logged in
{% endcomment %}
6. Optimize Property Usage
Each property access in your template triggers a recalculation when that property changes. To ensure optimal performance:
Only use properties that are necessary for your logic
Remove debug statements before saving
Avoid accessing deeply nested properties repeatedly
{# Bad - Accessing unnecessary properties #}
{% if customer.loggedIn and customer.acceptsEmailMarketing and customer.acceptsSmsMarketing %}
{{ cart.cost.total }}
{{ cart.cost.subtotal }}
{{ cart.cost.tax }}
{% endif %}
{# Good - Only using required properties #}
{% if customer.loggedIn %}
{{ cart.cost.total }}
{% endif %}
{# Bad - Repeated deep property access #}
{% for line in lines %}
{{ line.merchandise.product.title }}
{% if line.merchandise.product.vendor == "Specific" %}
{{ line.merchandise.product.productType }}
{% endif %}
{% endfor %}
{# Good - Assign deep properties to variables #}
{% for line in lines %}
{% assign product = line.merchandise.product %}
{{ product.title }}
{% if product.vendor == "Specific" %}
{{ product.productType }}
{% endif %}
{% endfor %}
⚠️ Performance Impact
Each property access creates a dependency
Changes to any accessed property trigger template recalculation
Unused property access impacts performance unnecessarily
Debug statements should be removed in production
Last updated
Was this helpful?