Minimum Quantity Enforcement

The PromoSync Pricing Engine embed block is shared with Volume Pricing. If you already enabled it for tier pricing, minimum quantity enforcement is included. Just verify the checkbox is on.

PromoSync stores a per-product minimum order quantity in the psrestful.minimum_quantity metafield (populated during supplier import) and enforces it in three places, with zero theme code changes:

WhereHowWorks on
Product pagePricing Engine embed keeps the quantity input at or above the minimumDawn-compatible themes
Cart page and cart drawerPricing Engine embed raises a lowered quantity back to what the product needsDawn-compatible themes
CheckoutMinimum Order Quantity checkout rule blocks checkout below the minimumAny theme, including express checkouts (Shop Pay, PayPal, Apple Pay, Google Pay)

The product page and cart run in the shopper’s browser and give immediate feedback. The checkout rule runs on Shopify’s servers, so it can’t be bypassed by a theme that our scripts don’t recognize, a custom cart, or direct Storefront API calls.


How It Works

1. Product page (Embed Block)

The PromoSync Pricing Engine embed block (target: "body") injects a <script type="application/json" data-promo-min-quantity> tag on product pages with the minimum quantity and product ID. MinQuantityHandler in promo-pricing.js then:

  • Sets the HTML5 min attribute and data-min on quantity inputs
  • Sets the initial value to the minimum if it’s currently below
  • Adds change and blur listeners that snap typed values back to the minimum (0 is allowed for themes that use 0 as a reset)
  • Calls validateQtyRules() on Dawn’s <quantity-input> custom element if available (updates +/- button states)
  • Uses a MutationObserver to re-apply after Section Rendering API re-renders (e.g., variant changes)

2. Cart page and cart drawer (Embed Block)

On every page, the embed also outputs <script type="application/json" data-promo-cart-min-quantities>: the minimum and product ID for each item already in the cart, keyed by variant ID. CartMinQuantityHandler listens for quantity changes in the capture phase, so it adjusts the value before the theme’s own handler sends the cart update:

  • The minimum applies to the product’s total across its variants, so a line is only raised as far as the product still needs (60 red + 40 blue meets a minimum of 100)
  • Setting a line to 0 removes it, as usual
  • Items added to the cart without a page reload (for example through an AJAX add-to-cart) are picked up after the next page load; the checkout rule covers them in the meantime

3. Checkout rule (Shopify Function)

The Minimum Order Quantity checkout rule is a Cart and Checkout Validation function shipped with PromoSync. When the buyer is in checkout, it totals each product’s quantity across its variants and, for any product below its psrestful.minimum_quantity, blocks checkout with a message such as:

Kelly Bottle has a minimum order of 100 units. Your cart has 40.

It only blocks during checkout, not while the cart is being edited, so a buyer can build a mixed-color order one variant at a time.

4. Minimum Quantity Notice (App Block)

The Min Quantity Notice app block (target: "section") renders a styled notice: “Minimum order: N units”. Merchants drag it into any product page section via Theme Customizer.

⚠️

Samples and single units. The checkout rule only knows psrestful.minimum_quantity. If your store sells samples or single units of products that have a minimum (for example through a custom theme flow), the rule will block those orders too. Leave the checkout rule off in that case and contact us.


Setup Instructions

Step 1: Enable the Embed Block

  1. Go to Online Store > Themes > Customize
  2. Click App embeds (left sidebar, puzzle piece icon)
  3. Toggle PromoSync Pricing Engine to ON (if not already enabled for tier pricing)
  4. The “Enforce minimum order quantity” checkbox is ON by default

Quantity inputs on product pages, the cart page, and the cart drawer now respect the minimum.

Step 2: Turn On the Checkout Rule

  1. In your Shopify admin, go to Settings > Checkout
  2. Find the Checkout rules section and add Minimum Order Quantity (PromoSync)
  3. Turn the rule on and save

The checkout rule is what guarantees the minimum on every theme. Steps 1 and 3 improve the shopping experience, but only this step stops an under-minimum order from being placed.

Step 3 (Optional): Add the Notice Block

To show a visible “Minimum order: N units” message on product pages:

  1. In Theme Customizer, navigate to a product page template
  2. Click Add block in the product section
  3. Select Min Quantity Notice (under the PromoSync app)
  4. Drag it to your preferred position (e.g., below the quantity selector)
  5. Save

The notice only renders on products that have a psrestful.minimum_quantity metafield with a value greater than 0.


Settings Reference

PromoSync Pricing Engine (Embed Block)

SettingDefaultDescription
Enforce minimum order quantityONKeep quantities at or above psrestful.minimum_quantity on product pages, the cart page and the cart drawer

Minimum Order Quantity (Checkout Rule)

No settings. Turn it on or off under Settings > Checkout > Checkout rules. It reads psrestful.minimum_quantity from each product in the cart.

Min Quantity Notice (App Block)

No additional settings. The block reads psrestful.minimum_quantity directly and uses the promo.min_quantity.notice translation key.


Behavior Details

Product page

ScenarioBehavior
Page load (min=5)Quantity input starts at 5, min attribute set to 5
User types “2”, tabs awayValue snaps back to 5
User clicks minus buttonStops at 5 (Dawn’s built-in stepDown() respects min)
User types “0”Allowed (some themes use 0 as remove/reset)
User types “10”Allowed (above minimum)
Variant changes re-render formMutationObserver re-applies enforcement
Product has no minimum metafieldNo enforcement, quantity input behaves normally
Minimum is 0 or 1No enforcement (minimum of 1 is the default)

Cart page and cart drawer

Scenario (min=100)Behavior
One line, changed from 100 to 40Raised back to 100 before the cart updates
Red 60 + Blue 40, red changed to 50Red raised to 60 (blue already covers 40)
Red 60 + Blue 40, red changed to 70Allowed
Line set to 0Line is removed
Product has no minimum metafieldNo change

Checkout

Scenario (min=100)Behavior
40 units of one variantCheckout blocked: ”… has a minimum order of 100 units. Your cart has 40.”
60 + 40 units of two variants of the same productAllowed
Two products below their minimumsOne message per product
Product has no minimum, or a minimum of 0 or 1Allowed
Buyer is editing the cart (not in checkout yet)Not blocked

Supported quantity input selectors

The browser-side handlers find inputs via these selectors, covering Dawn and compatible themes. On themes with different markup, the checkout rule still enforces the minimum.

/* Product page */
product-info quantity-input input.quantity__input
.product-form quantity-input input.quantity__input
form[action*="/cart/add"] input[name="quantity"]
 
/* Cart page and cart drawer (variant read from data-quantity-variant-id or the line's data-promo-variant-id) */
input[name="updates[]"]
cart-items input.quantity__input
cart-drawer-items input.quantity__input

Metafield Reference

MetafieldNamespaceKeyTypeSet By
Minimum quantitypsrestfulminimum_quantitynumber_integerPromoSync product import

The metafield is populated automatically when products are imported from PromoStandards suppliers. No manual setup is required.


Files Involved

FileTypePurpose
blocks/promo-pricing-engine.liquidEmbed blockSerializes min quantity JSON on product pages and cart minimums on every page
assets/promo-pricing.jsJavaScriptMinQuantityHandler (product page) and CartMinQuantityHandler (cart page and drawer)
blocks/min-quantity-notice.liquidApp blockDrag-and-drop “Minimum order: N units” notice
assets/promo-pricing.cssStylesheet.promo-min-quantity styles
snippets/min-quantity.liquidSnippetLegacy snippet, kept for backward compatibility
locales/en.default.jsonTranslationspromo.min_quantity.notice key
extensions/minimum-quantity-validationShopify FunctionThe Minimum Order Quantity checkout rule (cart.validations.generate.run)

Customization

CSS

Override the notice styles using CSS custom properties:

:root {
  --promo-bg-alt: #f0f0f0;       /* Notice background */
  --promo-primary: #2c6ecb;       /* Left border color */
  --promo-text: #1a1a1a;          /* Text color */
  --promo-font-size-sm: 0.8125rem; /* Font size */
  --promo-spacing-sm: 0.5rem;      /* Padding */
  --promo-radius-sm: 0.25rem;      /* Border radius */
}

Translations

Edit locales/en.default.json to customize the notice text:

{
  "promo": {
    "min_quantity": {
      "notice": "Minimum order: {{ quantity }} units",
      "notice_short": "Min: {{ quantity }}"
    }
  }
}

Verification Checklist

  1. Open a product page with psrestful.minimum_quantity set (e.g., min=5)
  2. Quantity input starts at 5, not 1, and min / data-min are set to 5
  3. Type “2” in the input, tab away: it snaps back to 5
  4. Click minus button: it stops at 5
  5. Change variant: enforcement is still active after re-render
  6. Add “Min Quantity Notice” block via Theme Customizer: it renders correctly
  7. Open a product with no minimum quantity metafield: no enforcement, no notice
  8. Add a product with a minimum to the cart, open the cart page, change the quantity below the minimum: it goes back up to the minimum
  9. With the checkout rule on, open /cart/<variant_id>:<below minimum> and continue to checkout: checkout is blocked with the minimum order message
  10. Add two variants of the same product that together meet the minimum: checkout is allowed

Migrating from Theme-Level Enforcement

If you previously added minimum quantity enforcement directly in your theme code, you can safely remove:

  • enforceMinimum() from global.js or QuantityInput class overrides
  • setQuantityBoundries() / data-min logic from product-info.js
  • Metafield reads and min/data-min/value attributes from main-product.liquid
  • data-min plumbing from cart drawer/page templates

The app extension handles all of this automatically.