Skip to main content
A fixed pricing bundle sells a defined set of products for one fixed total price, regardless of the sum of the individual item prices. For example, “Any 3 candles for $40” — if the candles total $54, the customer saves $14 automatically. This guide shows how to run a fixed pricing bundle entirely from your own storefront UI. You use the same metafield, cart-line attributes, and Shopify Function that Appstle’s built-in widget uses — only the UI is yours. If you have not yet read the headless overview, start there — it explains the automatic-discount model these steps rely on.
bundleTypeSINGLE_PRODUCT_BUILD_A_BOX
bundleSubTypeFIXED_BUNDLE
Read fromappstle_bundles.bundle_rules shop metafield
Discount applied byAppstle automatic discount (Shopify Function)

How pricing works

The merchant sets a single price on the rule — the total the customer pays for the bundle. Appstle’s discount Function reduces the bundled lines so their combined total equals price:
customer pays   = price
customer saves  = (sum of selected line prices) − price
The discount is applied automatically at checkout once the lines carry the bundle attributes. You do not compute or submit the discount.

Step 1 — Read the rule from the metafield

Read the active rules from the appstle_bundles.bundle_rules shop metafield — the Shopify-native source, with no call to Appstle’s servers (see Reading bundle configuration). Filter to fixed pricing bundles by bundleType + bundleSubType.
{% assign bundle_rules = shop.metafields.appstle_bundles.bundle_rules.value %}
<script>window.MY_BUNDLE_RULES = {{ bundle_rules | json }};</script>
const rules = window.MY_BUNDLE_RULES || [];

const fixedBundles = rules.filter(
  r => r.bundleType === 'SINGLE_PRODUCT_BUILD_A_BOX' &&
       r.bundleSubType === 'FIXED_BUNDLE' &&
       r.status === 'ACTIVE'
);
The fields you need from each rule:
FieldUse
uniqueRefAttach to every cart line as _appstle-bb-id.
nameDisplay label; attach as __appstle-bb-name.
priceThe fixed total the customer pays.
minProductCount / maxProductCountHow many items the customer must pick.
products / variantsEligible products and variants (JSON).
Take the eligible product and variant IDs from the rule’s products / variants fields and hydrate titles, images, and prices with Shopify’s own Storefront API or Liquid product objects. If you would rather receive a pre-parsed product list from Appstle, the App Proxy endpoint GET /bundles/bb/api/build-a-box/get-bundle/{handle} returns one — use it as a last resort and cache the response.

Step 2 — Render your selector

Build whatever UI matches your theme. Drive its rules from the configuration:
  • Show the eligible products.
  • Enforce the item count between minProductCount and maxProductCount.
  • Display the headline price (price) prominently, and optionally the savings (see below).

Step 3 — Add the bundle to the cart

When the selection is valid, add the chosen variants to the cart with the required attributes. For a fixed pricing bundle, each component line carries _appstle-bb-id, _appstle_bundles_type, and __appstle-bb-name.
const lineFor = (variantId, quantity) => ({
  id: variantId,
  quantity,
  properties: {
    '_appstle-bb-id': bundle.uniqueRef,
    '_appstle_bundles_type': 'SINGLE_PRODUCT_BUILD_A_BOX',
    '__appstle-bb-name': bundle.name,
  },
});

await fetch(`${Shopify.routes.root}cart/add.js`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    items: selectedItems.map(i => lineFor(i.variantId, i.quantity)),
  }),
});
mutation AddFixedBundle($cartId: ID!) {
  cartLinesAdd(
    cartId: $cartId
    lines: [
      {
        merchandiseId: "gid://shopify/ProductVariant/111"
        quantity: 1
        attributes: [
          { key: "_appstle-bb-id", value: "fixed-candle-set-ref" }
          { key: "_appstle_bundles_type", value: "SINGLE_PRODUCT_BUILD_A_BOX" }
          { key: "__appstle-bb-name", value: "Any 3 Candles" }
        ]
      }
      {
        merchandiseId: "gid://shopify/ProductVariant/222"
        quantity: 1
        attributes: [
          { key: "_appstle-bb-id", value: "fixed-candle-set-ref" }
          { key: "_appstle_bundles_type", value: "SINGLE_PRODUCT_BUILD_A_BOX" }
          { key: "__appstle-bb-name", value: "Any 3 Candles" }
        ]
      }
    ]
  ) {
    cart { id }
    userErrors { field message }
  }
}
Every line that belongs to the bundle must carry the same _appstle-bb-id. A line without the attributes is treated as a normal product and is not priced into the fixed total.

Step 4 — Discount applies automatically

Once the lines are in the cart, Appstle’s automatic discount reduces the bundled lines so the set totals price. It shows in the cart, persists through checkout, and is reflected on the order. There is nothing else to call.

Previewing savings

To show the customer what they save before checkout, compute it from the rule (remember cart prices are in cents):
// linePrices: array of unit prices (in cents) × quantities for the selected items
const subtotal = linePrices.reduce((sum, cents) => sum + cents, 0);
const fixedTotalCents = Math.round(bundle.price * 100);
const savingsCents = Math.max(0, subtotal - fixedTotalCents);

// e.g. "You save $14.00"
const savingsLabel = `You save ${(savingsCents / 100).toFixed(2)}`;
This is a display-only preview. The Shopify Function applies the authoritative discount at checkout from the same price, so the two always agree.

Checklist

1

Bundle is Active in the Appstle admin

Only active rules have a live automatic discount.
2

Selection respects min/max product count

Validate before adding to cart.
3

Every line carries the bundle attributes

_appstle-bb-id (= uniqueRef) and _appstle_bundles_type (= SINGLE_PRODUCT_BUILD_A_BOX) on each line.
4

Verify the discount in the cart

Confirm the bundled lines total the configured price.

Next steps

Dynamic pricing bundle

Build-your-own with a percentage or amount discount.

Volume discount bundle

Tiered “buy more, save more” discounts.