Skip to content

Buy blocks

The blocks that take the order. One of them — Buy buttons — owns the <form>, and three others are rendered inside it. The rest sit alongside and reorder freely.

Option selection. Colour-like options render as swatches; everything else renders as labelled pills. Includes a plain dropdown fallback when scripting is unavailable, and the size-guide dialog.

SettingTypeDefaultWhat it does
Size guide labelTextSize guideThe link or button text, and the dialog’s heading
Size guide contentHTML(empty)Shown in a pop-up beside the option. Tables are supported
Size guide pageURL(empty)Used only when no size guide content is set — links out instead of opening a dialog

The block renders nothing on a product with only a default variant.

Which options become swatches is decided by Theme settings → Swatches → Swatch option names, a comma-separated list that defaults to color, colour, shade, tint. An option whose name matches (case-insensitively) renders as a colour chip; anything else renders as a text pill. See Colour swatches for how the colours themselves are resolved.

The currently selected value is echoed into the option label — “Size — M” — and updated live as the shopper changes it.

The section’s script walks every combination and marks the ones that don’t exist or are out of stock. A value that resolves to no variant at all is disabled; a value that resolves to a sold-out variant stays clickable — so a shopper can select their sold-out size and be offered the Back-in-stock form instead of being silently blocked.

On size-style pills the sold-out state is drawn as a diagonal hatch with dimmed text. Colour swatches are marked in the markup but carry no hatch of their own, so a sold-out colourway looks the same as an available one until it’s selected. If every colour in a run can sell out independently, consider leading with colour as the second option rather than the first.

The radios are named option-0, option-1 and so on, not id. The script resolves the chosen combination to a variant and writes that variant’s id into the form’s hidden id input. That indirection is what lets the picker be reordered anywhere in the column — above the title, below the perks — without breaking add-to-bag.

The dialog lives on this block rather than on the Product section for a structural reason: a block cannot read section.settings. It also belongs beside the option it explains.

  • Fill in size_guide_content and a Size guide button appears next to the first non-swatch option, opening a real <dialog> with a focus trap supplied by the browser.
  • Leave the content empty and set size_guide_page instead, and the same label renders as a plain link to that page.
  • Set neither and nothing appears.

The button is only placed on non-swatch options, so “Colour” never gets a size guide. See Size guide for the standalone measurement section.

The add-to-cart unit — and the block that owns the product form itself. Everything that has to be submitted with the order lives inside it.

SettingTypeDefaultWhat it does
Add to bag labelTextAdd to bagThe button label when the variant is available
Show quantity selectorCheckboxOnRenders the quantity stepper before the button
Show accelerated checkoutCheckboxOnRenders Shop Pay and the other accelerated checkout buttons below
Delivery labelTextDeliveryHeading above the subscription control
One-time labelTextOne timeLabel for the one-time purchase option
  1. The hidden id input carrying the selected variant.

  2. The subscription selector, when the product has selling plans. Nothing at all when it doesn’t.

  3. A quantity-rule note, when the product has B2B quantity rules — minimum, increment, maximum, composed into one line.

  4. A volume pricing table, when the selected variant has quantity_price_breaks. Shows the base price and each break.

  5. Gift-card recipient fields, on gift-card products only.

  6. The quantity stepper and the add-to-cart button, side by side.

  7. The accelerated checkout buttons.

Steps 3 to 5 appear automatically from product data — there’s no setting, because there’s nothing for a merchant to decide. Quantity rules and volume breaks come from Shopify’s B2B catalogue features; the gift-card fields appear because Shopify reads those exact properties[…] field names on a gift-card product and delivers the card to the recipient instead of the buyer.

On a gift-card product the block adds a “send this as a gift” checkbox which reveals recipient email, recipient name, a 200-character message and a send-on date. The email becomes required only when the box is ticked, so a shopper buying a card for themselves isn’t asked for an address they don’t have.

The form’s submit is intercepted: the item posts to /cart/add.js, the bag count updates, a toast confirms, the cart drawer re-renders and — when motion is on — a copy of the product image flies to the bag icon. The shopper never leaves the product page. If the request fails, Shopify’s own human-readable reason is shown in the toast rather than a generic error.

The quantity stepper — minus, a number input, plus. No settings.

Rendered statically inside Buy buttons, because the input has to be inside the product form to be submitted with it. Toggle it with Buy buttons’ show_qty.

It reads the variant’s quantity_rule, so the input’s min, step and max reflect any B2B rules on the product; the stepper buttons move in increments of step and clamp to the range.

The submit button, and the wishlist heart beside it. No settings of its own — the label comes from Buy buttons’ atc_label, which is passed in as a parameter.

  • Available: Add to bag — $240.00. The price in the label is kept in sync with the variant and the chosen subscription plan.
  • Unavailable: Sold out, and the button is disabled.

The heart next to it appears when Theme settings → Quick view & wishlist → Enable wishlist is on, and toggles the product in the device-local wishlist.

Also rendered statically inside Buy buttons.

Shop Pay, PayPal, Google Pay, Apple Pay — whichever accelerated methods the shop has enabled. No settings. Toggle it with Buy buttons’ show_dynamic_checkout.

This block exists only because of one Liquid constraint. The payment_button filter needs the form drop, and a block cannot reach the form object of a form it didn’t open. So Buy buttons passes it in:

{% content_for 'block', type: 'accelerated-checkout', id: 'accelerated-checkout', form_obj: form %}

Without that parameter the block renders nothing. That’s why it’s a static nested block rather than a freely placed one. See Accelerated checkout.

An email sign-up shown when the selected variant is sold out, hidden when it’s available. No settings — all copy comes from the locale file.

It’s an outlined panel with a heading, a line of help text, an email field and a submit button. The section’s script shows and hides it as the shopper changes variant, and rewrites the hidden note field so the sign-up records which variant was wanted.

Submission happens by fetch so the shopper stays on the product page and sees the confirmation. Sign-ups land as customers tagged back-in-stock. Full detail, including how to actually send the notifications, is on Back-in-stock notifications.

In-store pickup for the selected variant, rendered from store_availabilities — so it reflects your real locations, not a setting. No settings.

It shows the first pickup-enabled location and whether the variant is available there, plus a “+2 more locations” line when there are others. Available reads in the accent colour; unavailable reads dim.

The block renders nothing when no location has pickup enabled, so a store that doesn’t offer pickup never sees it.

On variant change the block re-fetches itself through the Section Rendering API rather than guessing, because availability is per variant per location and only Shopify knows it. See Pickup availability for setup.