Skip to content

Mix & match

Build-your-own-box bundles with sections, minimums, and tiered discounts.

Shoppers assemble a bundle from sections you define (“pick 3 coffees, pick 2 mugs”) and get a discount that can grow with the size of the box. Needs: the Storesynk AI app on the Pro plan.

  1. Open Discounts & Bundles, click Create, and pick Mix & match bundle.
  2. Add sections: a name, an image, the product pool, and the minimum and maximum items. A minimum of 0 makes the section optional.
  3. Choose the discount: a single rule or tiers by item count. Types are percentage, fixed amount, set price, free shipping, and (in tiers) cheapest item free. You can apply it to the whole selection or to specific sections.
  4. Pick the cart presentation: grouped as one bundle line, or separate lines discounted automatically.
  5. Set the title, tick Show the mix & match widget on all pool products’ pages, set the dates, and mark it Active.

Limits: 25 mix & match bundles per shop, 10 sections, 30 products per section, 60 distinct products across the bundle, 6 tiers. Fixed-amount and set-price discounts are recorded in the shop currency and only apply to carts in that currency.

Two placements: inside a product page’s <storesynk-product>, or on a standalone builder page with handle="…" naming the bundle (client-rendered only). Four clone containers nest, and each one’s first child is its template:

storesynk-mix-match → first child: the per-bundle template (mix-match-offer)
mix-match-offer
mix-match-section-list → first child: mix-match-section
mix-match-section
toggle-section → the disclosure header
mix-match-item-list → first child: the pool card (storesynk-product)
mix-match-selection-list → first child: the pick thumbnail
<storesynk-mix-match>
<mix-match-offer>
<show-mix-match-title></show-mix-match-title>
<show-mix-match-tier-hint></show-mix-match-tier-hint>
<mix-match-section-list>
<mix-match-section>
<toggle-section>
<button type="button">
<show-section-title></show-section-title>
<show-section-requirement></show-section-requirement>
<show-section-count></show-section-count>
</button>
</toggle-section>
<mix-match-item-list>
<storesynk-product>
<show-image><img alt="" /></show-image>
<show-title></show-title>
<show-price></show-price>
<change-option group="1"><select><option>Choose</option></select></change-option>
<add-mix-match-item><button type="button">Add</button></add-mix-match-item>
<decrease-mix-match-item><button type="button" aria-label="Remove one">−</button></decrease-mix-match-item>
<show-item-quantity></show-item-quantity>
<increase-mix-match-item><button type="button" aria-label="Add one more">+</button></increase-mix-match-item>
</storesynk-product>
</mix-match-item-list>
</mix-match-section>
</mix-match-section-list>
<mix-match-selection-list max="4">
<span><show-pick-image></show-pick-image><show-pick-quantity></show-pick-quantity></span>
<show-selection-overflow></show-selection-overflow>
</mix-match-selection-list>
<show-mix-match-original-total></show-mix-match-original-total>
<show-mix-match-total></show-mix-match-total>
<p>You save <show-mix-match-savings></show-mix-match-savings></p>
<add-mix-match-to-cart><button type="button">Add box to cart</button></add-mix-match-to-cart>
</mix-match-offer>
</storesynk-mix-match>
  • The accordion drives itself: the first unmet section opens, and a met section collapses to the next. <toggle-section> and the item list form a proper disclosure; do not add your own roles.
  • Pool cards are real products fed by the engine, so option pickers and prices work. Give them no handle.
  • The increase, decrease, and remove controls are the one family the engine does not name. Give each an aria-label.
  • Prices are advisory. The app’s discount function applies the real discount at checkout. The add button stays disabled until every section is within its limits and sends the whole box in one cart update.
storesynk-mix-match[ss-empty], storesynk-mix-match[ss-loading] { display: none; }
mix-match-offer, mix-match-section-list, mix-match-section, mix-match-selection-list { display: block; }
mix-match-item-list:not([hidden]) { display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 10px; }
storesynk-product[ss-selected] { outline: 2px solid #111; }
add-mix-match-to-cart[ss-incomplete] button { opacity: .5; cursor: not-allowed; }
AttributeSet onMeaning
ss-empty, ss-loadingstoresynk-mix-matchnothing live, or fetching
ss-open, ss-metmix-match-sectionsection expanded; section minimum reached
ss-selectedpool storesynk-productthe card is in the box
ss-maxadd-mix-match-item, increase-mix-match-itemthe section is full
ss-incompleteadd-mix-match-to-carta section is outside its limits

The engine also sets --ss-progress (0 to 1) on <show-section-progress> for a progress bar.