Skip to Content
Liquid context reference

Liquid context reference

This is the complete set of objects your theme can read. The platform builds this context and hands it to your Liquid - you never fetch data yourself. A machine-readable version is available at /context-schema.json (see the API reference).

Global objects

Available in every template and section.

VariableNotes
shopStorefront-wide info (see below).
settingsMerchant’s global theme settings, keyed by your settings_schema.json ids.
cartAlways present, may be empty.
customerThe signed-in customer, or null.
linklistsMenus keyed by handle.
collectionsIterable list AND a handle-keyed map of all collections.
request{ path, page_type, locale, host }.
template{ name } - alias for request.page_type.
routesCanonical URLs for cart / search / account routes.
canonical_urlFull URL of the current page.

Per-page extras

  • Product page - product
  • Collection page - collection (with products[] + facets), paginate, active_filters
  • Search page - search, active_filters
  • Content page - page

shop

Storefront-wide information.

FieldTypeNotes
namestringStore / business name.
currencystringISO currency code (e.g. INR).
slugstringStore brand slug.
primary_domainstringPrimary storefront domain.
descriptionstring | null
taglinestring | null
logostring | nullLogo image URL.
seo_titlestring | null<title> override.
seo_descriptionstring | null<meta description> override.
og_imagestring | null
faviconstring | nullNull until a logo is uploaded.
apple_touch_iconstring | null
web_manifeststring | null
cod_enabledbooleanCash-on-delivery available. Drives trust-strip copy.
free_shipping_thresholdnumberFree-shipping order value; 0 = none.
delivery_check_enabledbooleanServiceability/pincode check available. Gate the PDP pincode checker on this.
enabled_payment_typesstring[]Accepted payment methods. The single source of truth for the payment-icon row.
payment_icons_htmlstringPre-rendered payment-icon row - output verbatim behind your own show_payment_icons toggle.

settings

The merchant’s global theme settings, keyed by the ids you declare in config/settings_schema.json. Access as {{ settings.color_primary }}, {{ settings.logo }}, and so on. See Sections & settings.

Some well-known ids (color_bg, color_primary, color_surface, color_fg, color_border, color_accent, font_body_family, font_heading_family) also brand the merchant’s cart / account pages when your theme is live - use these exact ids to opt in for free.


product

Available on the product page, and nested inside collection.products[] and search.results[].

FieldTypeNotes
id, title, handlestring
description, excerptstring | null
urlstring
typestring
vendorstring | nullBrand/manufacturer. Guard with {% if product.vendor %}.
tagsstring[]
images{ url, alt_text, position }[]
featured_imagestring | nullFirst image URL.
availableboolean
pricenumberLowest variant price, in paise.
compare_at_pricenumber | nullIn paise.
variantsvariant[]See below.
optionsproduct_option[]Use this for swatches / size pickers.
collections{ id, title, handle }[]
ratingnumberAverage 0-5.
rating_countnumber
rating_breakdownnumber[]5-cell histogram; index 0 = 1-star.
reviewsarray{ id, rating, title, body, images[], verified, reviewer_name, created_at }
is_featuredboolean
custom_fieldscustom_field[]Iterate for PDP accordion panels.
custom_fields_by_keymapKeyed accessor: product.custom_fields_by_key.fabric_care.
related_productsproduct[]“You may also like” rail.
seo_title, seo_descriptionstring | null

product.options[] and variants

Every product surfaces a structured options[] array. Use it for swatches and size pickers - never split variant.title on /.

Each option group:

FieldTypeNotes
id, namestring"Color", "Size", …
kindstringSIZE | COLOR | CAPACITY | MATERIAL | FRAME | WEIGHT | PACK_SIZE | FRAGRANCE | STYLE | CUSTOM. Branch on this, not name.
systemstring | nullnull = freeform; a system id when canonical.
positionnumber1, 2, or 3.
valuesarraySee below.

Each option value:

FieldTypeNotes
id, labelstring"M", "Onyx", "27".
sort_ordernumber
swatch_hexstring | nullResolved hex: override → canonical → null.
canonicalobject | null{ id, system, label, regional_labels, body_measurements, swatch_hex } when linked to the taxonomy.

Each variant:

FieldTypeNotes
id, title, skustring
pricenumberIn paise.
compare_at_pricenumber | nullIn paise.
availablebooleanActive AND in stock.
inventory_quantitynumber
imagesstring[]
option_valuesarray{ option_id, option_name, option_kind, option_position, value_id, label, swatch_hex, canonical } per option group.

Rendering option pickers

Branch on option.kind:

{% for option in product.options %} {% if option.kind == 'COLOR' %} {% for v in option.values %} <button class="swatch" style="--swatch: {{ v.swatch_hex | default: '#ccc' }};" data-option-value-id="{{ v.id }}" aria-label="{{ v.label }}"></button> {% endfor %} {% elsif option.kind == 'SIZE' %} {% for v in option.values %} <button class="chip" data-option-value-id="{{ v.id }}">{{ v.label }}</button> {% endfor %} {% endif %} {% endfor %}

product.custom_fields[]

Merchant-defined typed metafields. Two access patterns:

{# iterate every attached field #} {% for f in product.custom_fields %} <h3>{{ f.label }}</h3> {% if f.type == 'RICH_TEXT' %}{{ f.value_text }} {% elsif f.type == 'IMAGE' %}<img src="{{ f.value_image }}" alt="{{ f.label }}"> {% elsif f.type == 'IMAGE_LIST' %}{% for img in f.value_images %}<img src="{{ img }}">{% endfor %} {% elsif f.type == 'NUMBER' %}{{ f.value_number }} {% else %}{{ f.value_text }}{% endif %} {% endfor %} {# look up a specific field by key #} {% assign care = product.custom_fields_by_key.fabric_care %} {% if care %}<div class="rte">{{ care.value_text }}</div>{% endif %}

Each field: { id, key, label, type, description, position, value, value_text, value_image, value_images, value_number, value_json }. type is one of TEXT | RICH_TEXT | IMAGE | IMAGE_LIST | VIDEO | URL | NUMBER | JSON_LIST.


collection

Available on collection pages, and every entry in the global collections list.

FieldTypeNotes
id, title, handlestring
descriptionstring | null
imagestring | null
urlstring
products_countnumberUse for “N products” labels.
show_in_navboolean
positionnumber
parent_idstring | nullFilter top nav by parent_id == blank.
childrencollection[]Sub-collections (populated on the global map).
productsproduct[]Paginated products.
facetsobject | nullFilter-sidebar source.
seo_title, seo_descriptionstring | null

On the global collections list, each entry carries metadata only - .products is [] unless a section/block on the current page references that collection, or it is the page’s own collection. Use products_count for counts on collection-list tiles.

collection.facets

The canonical source for the filter sidebar. Read from this - do not compute facets client-side from products[].

facets: { sizes: [{ label, hex, count }], // hex always null for sizes colors: [{ label, hex, count }], // hex = override || canonical || null priceRange: { min, max }, // in RUPEES (not paise) categories: [{ label, count }] }

paginate

{ current_page, pages, items, page_size, next, previous }

active_filters

Parsed active filter state - read from this rather than parsing the query string:

{ sortBy, sizes[], colors[], minPrice, maxPrice, inStockOnly, onSaleOnly, categoryHandles[], minRating, q }

minPrice / maxPrice are in RUPEES (render raw as ₹{{ active_filters.maxPrice }}).

Filter forms must submit as GET so the URL is shareable. Recognised query params: size, color, min_price, max_price, on_sale, in_stock, category, min_rating, sort_by, page.


cart

Always present. All prices in paise - render with the money filter.

FieldType
idstring
item_countnumber
itemscart_item[]
total_price, items_subtotal, items_subtotal_pricenumber
tax_totalnumber
tax_lines{ name, rate, amount }[]
discount_total, grand_totalnumber
applied_discount_codesstring[]
notestring | null

Each line item: { id, product_id, variant_id, quantity, title, variant_title, sku, url, image, price, final_price, original_price, unit_price, line_price, final_line_price, original_line_price }.

{{ item.line_price | money }}

linklists

Navigation menus keyed by handle. Your theme must iterate linklists['main-menu'].links for the header and linklists['footer-menu'].links for the footer. Both handles are platform-guaranteed to resolve. See Navigation.

{% for link in linklists['main-menu'].links %} <a href="{{ link.url }}">{{ link.title }}</a> {% if link.links.size > 0 %} <ul class="dropdown"> {% for child in link.links %} <li><a href="{{ child.url }}">{{ child.title }}</a></li> {% endfor %} </ul> {% endif %} {% endfor %}

Each link: { title, url, type, resource, links[] }. Child links live on link.links (not link.children). type is one of COLLECTION | PRODUCT | PAGE | URL | CATALOG.


customer

null when signed out. When signed in:

{ id, name, first_name, email, phone, logged_in }

On the /search page:

{ terms, performed, results: product[], results_count }

performed is true when a non-empty query ran. Render a styled empty state when results_count == 0.


page

On a content page (templates/page.json):

{ title, handle, content }

content is rich-text body HTML. Render {{ page.content }}. The platform-seeded legal pages (About us, Privacy Policy, Terms of Service, Cookie Policy) rely on this.


request, template, routes

request = { path, page_type, locale, host } template = { name } // alias for request.page_type routes = { root, cart_url, search_url, collections_url, account_url, account_login_url }

Use routes.* for account-app links rather than hardcoding paths.