On a product page, ctx.product contains the route-resolved product and its variants. Prices, availability, purchase state, and quantity limits already reflect the active storefront, market, inventory policy, and the merchant’s variant → product → store settings.
Quantity controls#
Use quantity_max as the max attribute on a fresh add-to-cart input. It is the largest quantity accepted right now after combining stock, remaining backorder capacity, and max_order_quantity. A null quantity_max means there is no finite runtime bound. A value of 0 means the product or variant cannot currently be added.
max_order_quantity is the resolved merchant policy: variant first, then product, then the store default. It may be null even when quantity_max is finite because stock can still provide the active limit.
{% assign purchasable = product %}
{% if product.selected_variant %}{% assign purchasable = product.selected_variant %}{% endif %}
{% form "cart_add" %}
<input type="hidden" name="product_id" value="{{ product.id }}">
{% if product.selected_variant %}
<input type="hidden" name="variant_id" value="{{ product.selected_variant.id }}">
{% endif %}
<input type="number" name="quantity" min="1" value="1"{% if purchasable.quantity_max %} max="{{ purchasable.quantity_max }}"{% endif %}>
<button type="submit"{% unless purchasable.available_for_sale %} disabled{% endunless %}>Add to cart</button>
{% endform %}
Product and variant fields#
- product.max_order_quantity and product.quantity_max apply directly to simple products.
- product.variants[*].max_order_quantity and quantity_max carry each variant’s resolved limits.
- product.selected_variant exposes the completed shopper selection; product.display_variant drives the current display while selection is incomplete.
- available_for_sale and purchase_state remain the authoritative controls for whether the item can be submitted.