Skip to content

variant

The variant object is one purchasable combination of a product’s option values. It carries the effective price, inventory state, media, quantity rules, pickup availability, and the Sellerlane product-kind capabilities inherited from its parent product.

Availability and context

Variants are most commonly returned by product.variants, product.selected_variant, product.first_available_variant, and product.selected_or_first_available_variant. They also appear on cart and order resources. variant.product can be nil when the parent cannot be resolved in the current storefront, so guard it when the surrounding context does not already provide a product.

Examples

Render the selected option values

Prefer selected_options or option_values over the legacy option1, option2, and option3 aliases.

{% assign variant = product.selected_or_first_available_variant %}
{% if variant %}
<h2>{{ variant.title | escape }}</h2>
<dl>
{% for selected_option in variant.selected_options %}
<dt>{{ selected_option.name | escape }}</dt>
<dd>{{ selected_option.value | escape }}</dd>
{% endfor %}
</dl>
{% endif %}

Example output:

<h2>Red / Medium</h2>
<dl>
<dt>Color</dt><dd>Red</dd>
<dt>Size</dt><dd>Medium</dd>
</dl>

Show price and inventory-safe availability

Use available to decide whether the buyer can purchase. It accounts for the product kind, the catalog-level purchasable flag, inventory tracking, stock, and the backorder policy.

{% if variant.available %}
<span>{{ variant.price | money }}</span>
{% if variant.on_sale %}
<s>{{ variant.compare_at_price | money }}</s>
{% endif %}
{% else %}
<span>Sold out</span>
{% endif %}

Example output:

<span>₹1,499.00</span>
<s>₹1,799.00</s>

Do not use inventory_quantity > 0 as the purchase test. Untracked inventory, backorders, and non-inventory product kinds can be available with a zero quantity.

Highlight variants matched by active filters

{% for variant in product.variants %}
<a href="{{ variant.url }}"
{% if variant.selected %}aria-current="true"{% endif %}
{% unless variant.matched %}hidden{% endunless %}>
{{ variant.option_values_concatenated | escape }}
</a>
{% endfor %}

Example output for a blue-color filter:

<a href="/products/linen-shirt?variant=var_blue_small">Blue / Small</a>
<a href="/products/linen-shirt?variant=var_blue_medium" aria-current="true">Blue / Medium</a>

Without an active variant filter, every variant has matched == true.

Respect quantity rules and pickup availability

<input
type="number"
name="quantity"
min="{{ variant.quantity_rule.min }}"
{% if variant.quantity_rule.max %}max="{{ variant.quantity_rule.max }}"{% endif %}
step="{{ variant.quantity_rule.increment }}"
value="{{ variant.quantity_rule.min }}">
{% if variant.store_availabilities != empty %}
<p>Pickup is available at {{ variant.store_availabilities.size }} location(s).</p>
{% endif %}

Example output:

<input type="number" name="quantity" min="2" max="20" step="1" value="2">
<p>Pickup is available at 3 location(s).</p>

store_availabilities is defined for the URL-selected variant and for the product’s first available variant. These can be different variants, in which case both can expose pickup rows. The array contains at most 250 active, pickup-enabled, non-fulfillment locations in the store’s country, ordered with the default location first and then by creation order.

Nil values and behavioral details

  • selected is true only for the variant chosen by the URL or relevant-result context. It is not inferred from a theme loop.
  • incoming applies to inventory-capable product kinds when the storefront variant payload reports an incoming shipment; it does not additionally test inventory_tracked. next_incoming_date is nil unless incoming is true.
  • weight is authoritative grams and can be nil; grams is the compatibility alias and is 0 when no shippable weight exists. weight_in_unit and weight_unit can also be nil.
  • quantity_price_breaks is ordered by minimum quantity. The default quantity increment is 1.
  • purchasable is the catalog flag. purchase_ready additionally requires a direct digital sale to declare download, license_key, or both delivery; available then applies the product-kind inventory rules.
  • Prices and store-credit-like amounts are currency minor units. Apply money when displaying them.

Variant drops expose buyer-safe storefront fields only. They do not reveal seller inventory internals, unpublished pickup locations, or raw database records through either property access or | json.

Properties

PropertyDescription
variant.availabletrue when this variant is currently purchasable after product-kind and inventory rules.
variant.backorder_allowedtrue when inventory policy permits selling after stock reaches zero.
variant.barcodeBarcode value.
variant.bpnBuyer-facing part number, or an empty string.
variant.bulk_pricing_discount_typeDiscount calculation type used by bulk-pricing tiers.
variant.bulk_pricing_enabledtrue when one or more bulk-pricing tiers apply.
variant.bulk_pricing_tiersQuantity tiers ordered by minimum quantity.
variant.bundleVariant-level bundle configuration, or nil.
variant.bundle_itemsResolved items in the variant-level bundle.
variant.compare_at_priceOriginal price before discount, if any.
variant.compare_at_price_in_centsRaw compare-at price in currency minor units, or nil.
variant.created_atCreation timestamp.
variant.digital_deliveryVariant-level digital-delivery configuration, or nil.
variant.featured_imageThe featured image.
variant.featured_mediaThe featured media item.
variant.gramsWeight in whole grams; returns 0 when no shippable weight is defined.
variant.gtinGlobal Trade Item Number, or an empty string.
variant.has_pricetrue when the variant has a finite effective price.
variant.has_price?Boolean alias of has_price.
variant.idUnique identifier.
variant.imagePrimary image.
variant.image_urlDirect URL of the primary variant image, or an empty string.
variant.imagesAll images.
variant.incomingtrue for an inventory-capable product kind when the storefront variant payload reports an incoming shipment; it does not additionally test inventory_tracked.
variant.inventory_managementInventory tracking system, if any.
variant.inventory_policy’deny’ or ‘continue’ — selling when out of stock.
variant.inventory_quantityUnits in stock.
variant.inventory_trackedtrue when this product kind and variant use tracked inventory.
variant.matchedtrue for all variants without a variant filter; otherwise true only for variants matching the active filters.
variant.mediaAll media (images, video, 3D).
variant.metafieldsMetafields on this resource.
variant.mpnManufacturer Part Number, or an empty string.
variant.msrpManufacturer suggested retail price in currency minor units, or nil.
variant.nameName.
variant.next_incoming_dateEarliest active incoming shipment date, or nil when inventory is not incoming.
variant.on_saletrue when the effective price is below the compare-at price.
variant.option_1Compatibility alias of option1.
variant.option_2Compatibility alias of option2.
variant.option_3Compatibility alias of option3.
variant.option_namesSelected option names in position order.
variant.option_valuesSelected option values in position order.
variant.option_values_by_nameSelected option values keyed by their option name.
variant.option_values_concatenatedSelected option values joined with /.
variant.option1First selected option value, or an empty string.
variant.option2Second selected option value, or an empty string.
variant.option3Third selected option value, or an empty string.
variant.optionsSelected option-value objects in position order.
variant.priceEffective price in currency minor units, or nil when neither a base nor sale price is configured. Format with money.
variant.price_in_centsConfigured base price in currency minor units, or nil.
variant.price_unavailabletrue when this variant had its prices withheld after a failed catalog price resolution; renders as price-unavailable, never as sold out.
variant.price_unavailable?Boolean alias of price_unavailable.
variant.productParent product, loaded in the current store, or nil.
variant.product_idParent product identifier.
variant.product_typeSellerlane product kind inherited from the parent product.
variant.public_titleVariant title without the platform default-title placeholder.
variant.purchasableCatalog-level purchasable flag before inventory availability is applied.
variant.purchase_readytrue when the variant is catalog-purchasable and any direct digital sale declares a supported delivery mode; inventory is still checked separately by available.
variant.purchase_ready?Boolean alias of purchase_ready.
variant.quantity_price_breaksOrdered quantity price breaks for the variant.
variant.quantity_price_breaks_configuredtrue when quantity_price_breaks is non-empty.
variant.quantity_price_breaks_configured?Boolean alias of quantity_price_breaks_configured.
variant.quantity_ruleThe variant quantity rule.
variant.regular_priceNon-sale unit price in currency minor units, or nil.
variant.requires_selling_planAlways false because selling plans are unavailable.
variant.requires_shippingtrue when physical delivery is needed.
variant.sale_price_in_centsConfigured sale price in currency minor units, or nil.
variant.selectedtrue when this variant is selected by the current URL or relevant-result context.
variant.selected_optionsSelected name/value option objects in position order.
variant.selected_selling_plan_allocationAlways nil because selling plans are unavailable.
variant.selected?Boolean alias of selected.
variant.selling_plan_allocationsAlways empty because selling plans are unavailable.
variant.skuStock keeping unit.
variant.store_availabilitiesUp to 250 pickup-availability rows for the URL-selected variant and the product’s first available variant; empty in other variant contexts.
variant.taxabletrue when taxed.
variant.titleDisplay title.
variant.unit_priceUnit price in currency minor units, or nil when not configured.
variant.unit_price_measurementMeasurement basis used with unit_price, or nil.
variant.upcUniversal Product Code, or an empty string.
variant.updated_atLast update timestamp.
variant.urlRelative URL of the resource.
variant.videosVideo and external-video media attached to the variant.
variant.weightWeight in grams, or nil when the product kind is not shippable or no authoritative weight can be resolved.
variant.weight_in_unitMerchant-entered weight expressed in weight_unit, or nil when the variant has no weight.
variant.weight_unitUnit for weight display.

Property names are generated from the storefront engine (VariantDrop), so the list matches what themes can access. {{ variant | json }} is a curated synchronous snapshot: it omits some public properties, always serializes store_availabilities as an empty array, and removes inventory quantity and policy. Inspect those properties directly when needed.

Sellerlane differences from Shopify

  • Selling plans are not supported. requires_selling_plan is false, selected_selling_plan_allocation is nil, and selling_plan_allocations is empty.
  • Quantity price breaks come from Sellerlane bulk-pricing tiers; they are not Shopify B2B price lists or company-location pricing.
  • product_type can be physical, digital, gift_card, event, or bundle. These native types determine whether shipping and inventory concepts apply.
  • option1, option2, option3, and their underscore aliases remain for theme compatibility, but new themes should use selected_options, option_values, or option_values_by_name.