The product Drop on Product Pages
On templates/product.json and product.liquid, Shopify provides a product object with every field from the product admin: title, description, variants, images, SEO, and metafields. On collection pages, each item in collection.products is also a product drop — but with fewer preloaded associations.
Essential Properties
- product.id — unique numeric ID (use in data attributes and JSON)
- product.title, product.handle — display name and URL slug
- product.description — HTML rich text from the admin editor
- product.price — lowest variant price in cents
- product.compare_at_price — MSRP when set on any variant
- product.available — true if at least one variant is purchasable
- product.url — canonical product URL path
- product.featured_image — primary image drop
- product.images — array of all product media
- product.variants — array of variant drops
- product.options — option names (Size, Color) without values
- product.tags, product.type, product.vendor — merchandising metadata
- product.metafields — custom namespace.key data
Product page with variant selector
<h1>{{ product.title }}</h1>
<p class="vendor">{{ product.vendor }}</p>
<div class="rte">{{ product.description }}</div>
<select name="id" form="product-form">
{% for variant in product.variants %}
<option
value="{{ variant.id }}"
{% if variant == product.selected_or_first_available_variant %}selected{% endif %}
{% unless variant.available %}disabled{% endunless %}
>
{{ variant.title }} — {{ variant.price | money }}
{% unless variant.available %} (Sold out){% endunless %}
</option>
{% endfor %}
</select>- product.selected_or_first_available_variant — URL ?variant= param or first in-stock variant
- variant.available — false when inventory is 0 and policy is 'deny'
- variant.id is required for add-to-cart — never use product.id in cart forms
- The rte class styles rich text HTML from product.description
Note: product.price returns the minimum variant price. On sale pages with wide price ranges, loop variants or use price_varies.