Liquid Fundamentals for Theme Developers Beginner 12 min read

Liquid Objects Explained: Your Gateway to Shopify Data

Master Liquid objects and learn how to access product, collection, cart, and customer data in your Shopify themes.

Objects are the foundation of Liquid. They’re containers that hold all the data about your Shopify store: products, collections, customers, cart contents, and more. Understanding how to access and use objects is essential for building dynamic Shopify themes.

What Are Liquid Objects?

In Liquid, an object is a container for related data. Each object has properties (also called attributes) that you can access to display information.

{{ product.title }}

In this example:

  • product is the object
  • title is a property of that object
  • {{ }} outputs the value

Dot Notation

You access object properties using dot notation: the object name, followed by a dot, followed by the property name:

{{ shop.name }}
{{ product.price }}
{{ collection.description }}

You can chain multiple properties to access nested data:

{{ product.featured_image.src }}
{{ product.variants.first.price }}
{{ customer.default_address.city }}

The Most Important Objects

Let’s explore the objects you’ll use most frequently.

The shop Object

The shop object contains information about the store itself:

{{ shop.name }} {# Store name #}
{{ shop.email }} {# Store email #}
{{ shop.domain }} {# mystore.myshopify.com #}
{{ shop.url }} {# Full store URL #}
{{ shop.currency }} {# Store currency code (USD, EUR, etc.) #}
{{ shop.money_format }} {# How money is formatted #}

Common use case: Displaying the store name in the header:

<header>
<a href="/" class="logo">{{ shop.name }}</a>
</header>

The product Object

The product object is available on product pages and contains everything about a product:

{# Basic Info #}
{{ product.title }}
{{ product.description }}
{{ product.vendor }}
{{ product.type }}
{{ product.handle }} {# URL-friendly identifier #}
{# Pricing #}
{{ product.price }} {# Price in cents #}
{{ product.price | money }} {# Formatted price #}
{{ product.compare_at_price }}
{{ product.price_min }}
{{ product.price_max }}
{# Availability #}
{{ product.available }} {# true or false #}
{{ product.variants.size }} {# Number of variants #}
{# Images #}
{{ product.featured_image }}
{{ product.images }} {# Array of all images #}
{# Metadata #}
{{ product.tags }} {# Array of tags #}
{{ product.collections }} {# Collections containing this product #}

Example: A complete product card:

<article class="product-card">
{% if product.featured_image %}
<img
src="{{ product.featured_image | image_url: width: 400 }}"
alt="{{ product.featured_image.alt | escape }}"
loading="lazy"
>
{% endif %}
<h2>{{ product.title }}</h2>
<p class="vendor">{{ product.vendor }}</p>
<p class="price">
{{ product.price | money }}
{% if product.compare_at_price > product.price %}
<span class="compare-price">
{{ product.compare_at_price | money }}
</span>
{% endif %}
</p>
{% unless product.available %}
<span class="badge sold-out">Sold Out</span>
{% endunless %}
</article>

The collection Object

The collection object represents a group of products:

{{ collection.title }}
{{ collection.description }}
{{ collection.handle }}
{{ collection.image }}
{{ collection.products }} {# Array of products #}
{{ collection.products_count }}
{{ collection.all_products_count }}

Example: Looping through collection products:

<h1>{{ collection.title }}</h1>
{% if collection.description != blank %}
<div class="description">
{{ collection.description }}
</div>
{% endif %}
<div class="products-grid">
{% for product in collection.products %}
<div class="product-card">
<a href="{{ product.url }}">
<img src="{{ product.featured_image | image_url: width: 300 }}">
<h3>{{ product.title }}</h3>
<p>{{ product.price | money }}</p>
</a>
</div>
{% endfor %}
</div>

The cart Object

The cart object contains the current shopping cart:

{{ cart.item_count }} {# Number of items #}
{{ cart.total_price | money }}
{{ cart.items }} {# Array of line items #}
{{ cart.currency }}
{{ cart.note }} {# Cart note #}

Example: Cart summary:

<div class="cart-summary">
<p>{{ cart.item_count }} items in your cart</p>
<ul>
{% for item in cart.items %}
<li>
{{ item.product.title }} - {{ item.variant.title }}
<span>{{ item.quantity }} × {{ item.price | money }}</span>
</li>
{% endfor %}
</ul>
<p class="total">
Total: {{ cart.total_price | money }}
</p>
</div>

The customer Object

The customer object is available when a customer is logged in:

{% if customer %}
<p>Welcome back, {{ customer.first_name }}!</p>
<p>Email: {{ customer.email }}</p>
<p>Total orders: {{ customer.orders_count }}</p>
{% else %}
<a href="/account/login">Log in</a>
{% endif %}

Important: Always check if customer exists before accessing its properties, as it’s nil when no one is logged in.

Global vs. Template-Specific Objects

Some objects are available everywhere in your theme:

Global ObjectsDescription
shopStore information
cartShopping cart
customerLogged-in customer (or nil)
requestCurrent page request info
settingsTheme settings
localizationLanguage/currency info

Other objects are only available in specific templates:

ObjectAvailable In
productproduct.liquid, product.json
collectioncollection.liquid, collection.json
articlearticle.liquid
blogblog.liquid
pagepage.liquid

Accessing Array Elements

Many objects contain arrays (lists of items). You can access specific elements:

{# First and last items #}
{{ product.images.first }}
{{ product.images.last }}
{# By index (0-based) #}
{{ product.images[0] }}
{{ product.images[1] }}
{# Size/count #}
{{ product.images.size }}

Example: Display first 3 product images:

{% for image in product.images limit: 3 %}
<img src="{{ image | image_url: width: 200 }}" alt="{{ image.alt }}">
{% endfor %}

Using Square Bracket Notation

Sometimes you need to access properties dynamically. Use square brackets:

{% assign property_name = "title" %}
{{ product[property_name] }}
{# Same as: {{ product.title }} #}

This is useful when the property name comes from a variable or setting.

Checking if Objects Exist

Always check before accessing nested properties that might not exist:

{# Bad - might error if no image #}
{{ product.featured_image.alt }}
{# Good - check first #}
{% if product.featured_image %}
{{ product.featured_image.alt }}
{% endif %}
{# Also good - use default filter #}
{{ product.featured_image.alt | default: product.title }}

Common Patterns

Displaying Money

Prices in Shopify are stored in cents. Always use the money filter:

{# Wrong: displays "1999" #}
{{ product.price }}
{# Right: displays "$19.99" #}
{{ product.price | money }}
{# With currency code: "$19.99 USD" #}
{{ product.price | money_with_currency }}

Conditional Display

{% if product.available %}
{% if product.compare_at_price > product.price %}
<span class="sale-badge">Sale!</span>
{% endif %}
{% else %}
<span class="sold-out-badge">Sold Out</span>
{% endif %}

Handling Empty Values

{# Using blank check #}
{% if product.description != blank %}
{{ product.description }}
{% else %}
<p>No description available.</p>
{% endif %}
{# Using default filter #}
{{ product.description | default: "No description available." }}

Practice Exercise

Try creating a product information panel that displays:

  1. Product title and vendor
  2. Price (with sale price if applicable)
  3. Availability status
  4. First 3 tags
  5. Number of variants available
<div class="product-info">
<h1>{{ product.title }}</h1>
<p class="vendor">by {{ product.vendor }}</p>
<div class="pricing">
{% if product.compare_at_price > product.price %}
<span class="sale-price">{{ product.price | money }}</span>
<span class="original-price">{{ product.compare_at_price | money }}</span>
<span class="discount">
Save {{ product.compare_at_price | minus: product.price | money }}
</span>
{% else %}
<span class="price">{{ product.price | money }}</span>
{% endif %}
</div>
<p class="availability">
{% if product.available %}
✓ In Stock
{% else %}
✗ Out of Stock
{% endif %}
</p>
{% if product.tags.size > 0 %}
<div class="tags">
{% for tag in product.tags limit: 3 %}
<span class="tag">{{ tag }}</span>
{% endfor %}
</div>
{% endif %}
<p class="variants">
{{ product.variants.size }} variant{% if product.variants.size != 1 %}s{% endif %} available
</p>
</div>

Try it live: Explore product, collection, cart, and customer objects in our Liquid Playground with realistic mock data you can edit.

Key Takeaways

  1. Objects contain data about your store, products, customers, etc.
  2. Use dot notation to access properties: object.property
  3. Global objects (shop, cart, customer) are available everywhere
  4. Template-specific objects (product, collection) are only available in certain templates
  5. Always check for nil before accessing nested properties
  6. Use filters to format output (especially money for prices)

What’s Next?

Now that you understand objects, you’re ready to learn more about Filters, which are powerful tools for transforming and formatting your data.

You might also want to explore the complete object reference in Shopify’s official documentation.

Finished this lesson?

Mark it complete to track your progress.

Discussion

Loading comments...