Checkout Builder
  • 👋Welcome to Checkout Builder
  • Overview
    • Install Checkout Builder
    • 🛒Checkout Limitations: Shopify Plus vs Standard Plans
    • 📖Frequently Asked Questions
    • 🤝Support
  • Widgets
    • Conditions code editor
  • Discounts
    • Product discounts
    • Shipping discounts
    • Order discounts
  • Customizations
    • Delivery customizations
      • Rename a Delivery Method
      • Remove a Delivery Method
    • Payment customizations
      • Rename a Payment Method
      • Reorder a Payment Method
      • Remove a Payment Method
Powered by GitBook
On this page
  • Liquid Template Editor Guide
  • Template Structure
  • Available Objects
  • Lines
  • Cart
  • Customer
  • Shipping
  • Order
  • Filters
  • String Filters
  • Number Filters
  • Array Filters
  • Filter Chaining
  • Control Flow
  • Conditional Tags
  • Loops
  • Show/Hide System
  • Basic Usage
  • Template Complexity
  • Limits
  • Scoring
  • Best Practices
  • 1. Optimize Loops
  • 2. Use Early Exits
  • 3. Keep Filters Simple
  • 4. Handle Null Values
  • 5. Document Complex Logic
  • 6. Optimize Property Usage

Was this helpful?

  1. Widgets

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 identifier

    • title (string): Product variant title

    • selectedOptions (array): Selected variant options

      • name (string): Option name (e.g., "Size")

      • value (string): Option value (e.g., "Small")

    • product (object): Parent product information

      • id (string): Product identifier

      • vendor (string): Product vendor name

      • productType (string): Product category/type

    • requiresShipping (boolean): Whether the item needs shipping

    • sku (string): Stock keeping unit

attributes

  • Type: array

  • Description: Custom attributes attached to the line item

  • Properties:

    • key (string): Attribute key

    • value (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 key

    • value (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 costs

    • subtotal (number): Sum of line items before tax/shipping

    • tax (number): Total tax amount

    • shipping (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 method

    • type ('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 selected

    • code (string): Shipping method identifier

    • title (string): Display name

    • cost.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 identifier

    • value (string): Metafield value

    • namespace (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

Filter
Description
Parameters

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

Filter
Description
Parameters

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

Filter
Description
Parameters

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 2 months ago

Was this helpful?