Shopify Liquid Objects: Product, Collection, Cart & Shop
Master the four Liquid objects every Shopify theme developer touches daily: product, collection, cart, and shop. This guide covers properties, dot notation, nil-safe patterns, and real-world usage from ADSPOC's theme builds.
What Liquid objects are and how dot notation works
In Shopify Liquid, objects are structured data containers that the platform injects into your templates at render time. When you write {{ product.title }}, Liquid resolves the product object in the current template context and outputs its title property. Dot notation chains through nested objects: {{ product.featured_image.alt }} walks from the product, into its featured image, and reads the alt text. Arrays use bracket notation: {{ product.images[0].src }} or, more safely, loop with {% for image in product.images %}.
Objects are read-only in theme Liquid—you cannot mutate product.price or cart.item_count from the storefront. What you can do is read properties, branch on them with {% if %}, and pass slices of objects into snippets via the render tag. Understanding which object is in scope on each template type is the foundation of every theme: product pages expose product, collection pages expose collection, cart.liquid exposes cart, and shop is global on every page via layout and section rendering.
The product object: variants, media, and metafields
The product object represents a single catalog item. Core properties include product.title, product.handle, product.description, product.vendor, product.type, and product.tags (an array you can split, join, or check with contains). Pricing lives on variants, not the product root: product.selected_or_first_available_variant.price outputs the active variant price in cents, and you format it with the money filter—{{ product.selected_or_first_available_variant.price | money }}. For variant pickers, iterate {% for variant in product.variants %} and read variant.id, variant.title, variant.available, variant.options, and variant.featured_media.
Media handling shifted from product.images to product.media, which unifies images, videos, and 3D models. Use {% for media in product.media %} and branch on media.media_type. Metafields extend products without code changes: product.metafields.custom.care_instructions.value or product.metafields.reviews.rating.value when defined in Admin. Always nil-check metafields—{% if product.metafields.custom.badge != blank %}—because undefined namespaces return empty drops, not errors, and blank output is better than broken markup.
The collection object: listings, filters, and pagination
On collection templates, collection gives you the current collection's metadata and its products. collection.title, collection.description, collection.handle, and collection.image power hero sections and SEO. The product list is collection.products, paginated by Shopify when you use {% paginate collection.products by 24 %}. Inside the paginate block, paginate.pages, paginate.current_page, and paginate.next.url drive pagination UI. collection.products_count and collection.all_products_count differ when filters narrow results—use products_count for filtered views.
Collection objects also expose sort options and, on Online Store 2.0 themes with filtering enabled, collection.filters for storefront faceted search. Each filter has filter.label, filter.type, and filter.values with value.count and value.active. When building collection grids, pass each product into a snippet: {% render 'product-card', product: product, lazy: true %}. ADSPOC collection templates always lazy-load below-the-fold cards and reserve the first row for LCP-critical images with fetchpriority="high" on the lead product card only.
The cart object: line items, totals, and drawer patterns
cart is available globally and updates after Ajax Cart API calls or full page reloads. cart.item_count is the total quantity across line items; cart.items is the array of line items, each with item.product, item.variant, item.quantity, item.line_price, item.original_line_price, and item.key (required for /cart/change.js updates). cart.total_price, cart.original_total_price, and cart.cart_level_discount_applications power summary rows. Properties added at add-to-cart time appear on item.properties—{% for property in item.properties %}—useful for engraving, gift messages, or bundle identifiers.
Cart drawer themes typically fetch /cart.js as JSON and hydrate Liquid partials via sections rendering, but the cart object still drives server-rendered fallbacks. Check {% if cart.item_count > 0 %} before rendering line items; empty carts should show a CTA back to collections. For free-shipping bars, compare cart.total_price against a threshold stored in theme settings: {% assign remaining = settings.free_shipping_threshold | minus: cart.total_price %}. ADSPOC cart drawers always show line-level compare-at savings and surface item.variant.title when it is not 'Default Title'—small details that reduce support tickets and checkout confusion.
The shop object, nil checks, and defensive Liquid patterns
shop is global: shop.name, shop.url, shop.domain, shop.currency, shop.money_format, shop.enabled_payment_types, and shop.policies (privacy, refund, terms) are available on every page. Use shop.url with routes for locale-aware links: {{ routes.cart_url }}, {{ routes.root_url }}, {{ routes.account_login_url }}. shop.metafields mirrors product metafields at the store level—ideal for announcement banners, global badges, or footer trust copy managed in Admin without redeploying code.
Nil-safe Liquid prevents empty tags and layout collapse. Prefer {% if product != blank %} over assuming context. Use the default filter for fallbacks: {{ product.metafields.custom.subtitle | default: product.vendor }}. For arrays, check size: {% if product.tags.size > 0 %}. The blank keyword treats nil, false, and empty strings as falsy. Avoid chaining deeply without guards—{% if product.featured_media %} {{ product.featured_media.preview_image | image_url: width: 800 }} {% endif %}—because a missing featured media should not break the PDP. These patterns are non-negotiable in ADSPOC production themes where merchants add products with incomplete data daily.
Frequently asked questions
Get a free conversion audit from India's best Shopify builders
ADSPOC since 2000 · India's #1 CRO-focused Shopify agency · any store type · 18-day delivery or money back · 23+ conversion features built in · WhatsApp direct line · trained thousands of developers · Mumbai & Solan, serving India, Bangladesh, Pakistan, and worldwide.
Prefer a quick chat? Message ADSPOC on WhatsApp
Related reading
Liquid Filters and Tags: The Developer's Reference
Filters transform output; tags control logic. This reference covers the Liquid filters and tags Shopify theme developers use every day—with syntax, gotchas, and ADSPOC production patterns.
Shopify Snippets: Reusable Liquid Code Patterns
Snippets are the composable building blocks of every ADSPOC theme. Learn render tag syntax, parameter passing, snippet architecture, and battle-tested patterns for icons, product cards, and beyond.
JSON Templates vs Liquid Templates in Shopify
Online Store 2.0 replaced monolithic Liquid templates with JSON templates that compose sections. Learn when to use each format, how JSON templates are structured, and how alternate templates unlock flexible merchandising.