--- name: liquid-templating description: Master Shopify Liquid templating language. Use this skill for writing Liquid code, using objects, filters, and tags, accessing product/collection/cart data, creating dynamic content, handling conditionals and loops, and working with Liquid best practices. Essential for theme customization. license: MIT compatibility: Works within Shopify themes and compatible Liquid environments metadata: author: shopify-agent-skills version: "1.0" shopify-api-version: "2025-01" --- # Shopify Liquid Templating ## When to use this skill Use this skill when: - Writing Liquid template code - Accessing Shopify data (products, collections, cart, etc.) - Using Liquid filters to transform output - Creating conditional logic and loops - Building dynamic theme content - Debugging Liquid code issues - Optimizing Liquid performance ## Liquid Basics ### Output Tags Output data using double curly braces: ```liquid {{ product.title }} {{ shop.name }} {{ 'hello' | upcase }} ``` ### Logic Tags Use logic with `{% %}` tags: ```liquid {% if product.available %}

In Stock

{% else %}

Sold Out

{% endif %} ``` ### Whitespace Control Use `-` to strip whitespace: ```liquid {%- if condition -%} content {%- endif -%} ``` ## Core Objects ### Product Object ```liquid {{ product.title }} {{ product.description }} {{ product.price | money }} {{ product.compare_at_price | money }} {{ product.vendor }} {{ product.type }} {{ product.tags | join: ', ' }} {{ product.available }} {{ product.url }} {{ product.featured_image | image_url: width: 500 | image_tag }} {% for image in product.images %} {{ image | image_url: width: 300 | image_tag }} {% endfor %} {% for variant in product.variants %} {{ variant.title }} - {{ variant.price | money }} {% endfor %} {{ product.metafields.custom.care_instructions }} ``` ### Collection Object ```liquid {{ collection.title }} {{ collection.description }} {{ collection.products_count }} {{ collection.url }} {% for product in collection.products %} {{ product.title }} {% endfor %} {% paginate collection.products by 12 %} {% for product in collection.products %} {% render 'product-card', product: product %} {% endfor %} {{ paginate | default_pagination }} {% endpaginate %} ``` ### Cart Object ```liquid {{ cart.item_count }} {{ cart.total_price | money }} {{ cart.total_weight | weight_with_unit }} {% for item in cart.items %} {{ item.product.title }} {{ item.variant.title }} {{ item.quantity }} {{ item.line_price | money }} {% endfor %} {{ cart.attributes.gift_message }} {{ cart.note }} ``` ### Customer Object ```liquid {% if customer %} Hello, {{ customer.first_name }}! {{ customer.email }} {{ customer.orders_count }} orders {{ customer.total_spent | money }} {% for address in customer.addresses %} {{ address.street }} {{ address.city }}, {{ address.province }} {% endfor %} {% else %} Log in {% endif %} ``` ### Shop Object ```liquid {{ shop.name }} {{ shop.email }} {{ shop.domain }} {{ shop.money_format }} {{ shop.currency }} {{ shop.enabled_currencies }} ``` ### Request Object ```liquid {{ request.locale.iso_code }} {{ request.page_type }} {{ request.path }} {{ request.host }} ``` ## Essential Filters ### String Filters ```liquid {{ 'hello world' | capitalize }} {{ 'hello world' | upcase }} {{ 'HELLO' | downcase }} {{ ' hello ' | strip }} {{ 'hello' | append: ' world' }} {{ 'hello world' | prepend: 'say ' }} {{ 'hello' | replace: 'e', 'a' }} {{ 'hello world' | split: ' ' }} {{ 'hello world' | truncate: 8 }} {{ 'hello world' | truncatewords: 1 }} {{ 'hello' | size }} ``` ### Number Filters ```liquid {{ 4.5 | ceil }} {{ 4.5 | floor }} {{ 4.567 | round: 2 }} {{ 5 | plus: 3 }} {{ 5 | minus: 3 }} {{ 5 | times: 3 }} {{ 10 | divided_by: 3 }} {{ 10 | modulo: 3 }} {{ 1234.56 | money }} {{ 1234.56 | money_without_currency }} ``` ### Array Filters ```liquid {{ array | first }} {{ array | last }} {{ array | size }} {{ array | join: ', ' }} {{ array | sort }} {{ array | sort: 'price' }} {{ array | reverse }} {{ array | uniq }} {{ array | compact }} {{ array | concat: other_array }} {{ array | map: 'title' }} {{ array | where: 'available', true }} ``` ### URL Filters ```liquid {{ 'products' | url }} {{ product.url | within: collection }} {{ 'style.css' | asset_url }} {{ 'image.png' | asset_url }} {{ 'logo.png' | file_url }} {{ product.featured_image | image_url: width: 500 }} {{ product | product_image_url: 'master' }} ``` ### Image Filters ```liquid {{ image | image_url: width: 800 }} {{ image | image_url: width: 800, height: 600, crop: 'center' }} {{ image | image_url: width: 800 | image_tag }} {{ image | image_url: width: 1200 | image_tag: loading: 'lazy', widths: '300, 600, 900, 1200', sizes: '(max-width: 600px) 100vw, 50vw' }} {{ image | image_url: width: 500 | image_tag: alt: product.title }} ``` ### Money Filters ```liquid {{ product.price | money }} {{ product.price | money_with_currency }} {{ product.price | money_without_trailing_zeros }} {{ product.price | money_without_currency }} ``` ### Date Filters ```liquid {{ article.created_at | date: '%B %d, %Y' }} {{ article.created_at | date: '%Y-%m-%d' }} {{ 'now' | date: '%H:%M' }} ``` ## Control Flow ### Conditionals ```liquid {% if product.available %} In Stock {% elsif product.compare_at_price %} Sale {% else %} Sold Out {% endif %} {% unless product.available %} Sold Out {% endunless %} {% case product.type %} {% when 'Shirt' %}

It's a shirt!

{% when 'Pants' %}

It's pants!

{% else %}

Unknown type

{% endcase %} ``` ### Comparison Operators ```liquid {% if product.price > 1000 %}{% endif %} {% if product.price >= 1000 %}{% endif %} {% if product.price < 1000 %}{% endif %} {% if product.price <= 1000 %}{% endif %} {% if product.title == 'Hat' %}{% endif %} {% if product.title != 'Hat' %}{% endif %} {% if product.tags contains 'sale' %}{% endif %} {% if product.title %}{% endif %} {% if product.title == blank %}{% endif %} ``` ### Logical Operators ```liquid {% if product.available and product.price < 5000 %} Affordable and in stock! {% endif %} {% if product.type == 'Shirt' or product.type == 'Pants' %} It's clothing! {% endif %} ``` ## Loops ### For Loop ```liquid {% for product in collection.products %} {{ forloop.index }}: {{ product.title }} {% endfor %} {% for product in collection.products limit: 4 offset: 2 %} {{ product.title }} {% endfor %} {% for product in collection.products reversed %} {{ product.title }} {% endfor %} {% for item in array %} {{ forloop.index }} {{ forloop.index0 }} {{ forloop.first }} {{ forloop.last }} {{ forloop.length }} {% endfor %} {% for product in collection.products %} {{ product.title }} {% else %} No products found. {% endfor %} ``` ### Cycle ```liquid {% for product in collection.products %}
{{ product.title }}
{% endfor %} ``` ### Tablerow ```liquid {% tablerow product in collection.products cols: 3 %} {{ product.title }} {% endtablerow %}
``` ## Variables ### Assign ```liquid {% assign my_variable = 'Hello' %} {% assign price_in_dollars = product.price | divided_by: 100.0 %} ``` ### Capture ```liquid {% capture full_name %} {{ customer.first_name }} {{ customer.last_name }} {% endcapture %}

Hello, {{ full_name }}!

``` ### Increment/Decrement ```liquid {% increment counter %} {% increment counter %} {% decrement counter %} ``` ## Snippets and Sections ### Render Snippets ```liquid {% render 'product-card' %} {% render 'product-card', product: product %} {% render 'product-card', product: product, show_price: true %} {% render 'product-card' for collection.products as product %} ``` ### Section Tags ```liquid {% section 'header' %} {% sections 'footer-group' %} {{ content_for_layout }} {{ content_for_header }} ``` ## Forms ### Product Form ```liquid {% form 'product', product %} {% endform %} ``` ### Contact Form ```liquid {% form 'contact' %} {% endform %} ``` ### Customer Forms ```liquid {% form 'customer_login' %} {% endform %} {% form 'create_customer' %} {% endform %} ``` ## Best Practices 1. **Use `render` not `include`** - `render` is faster and scopes variables 2. **Avoid complex logic in Liquid** - Move to JavaScript when possible 3. **Use descriptive variable names** - `{% assign product_price = ... %}` 4. **Leverage caching** - Use Liquid responsibly within sections 5. **Handle blank states** - Always check for `blank` or empty arrays 6. **Use schema defaults** - Provide sensible defaults in section schemas ## Common Patterns ### Sale Badge ```liquid {% if product.compare_at_price > product.price %} {% assign savings = product.compare_at_price | minus: product.price %} {% assign percent_off = savings | times: 100.0 | divided_by: product.compare_at_price | round %} {{ percent_off }}% OFF {% endif %} ``` ### Variant Selector ```liquid {% unless product.has_only_default_variant %} {% for option in product.options_with_values %} {% endfor %} {% endunless %} ``` ## Resources - [Liquid Reference](https://shopify.dev/docs/api/liquid) - [Liquid Cheat Sheet](https://www.shopify.com/partners/shopify-cheat-sheet) - [Objects Reference](https://shopify.dev/docs/api/liquid/objects) - [Filters Reference](https://shopify.dev/docs/api/liquid/filters) - [Tags Reference](https://shopify.dev/docs/api/liquid/tags)