Flow: Bundle & Save Campaign
Before executing this skill, read Create Discount Rule with
ReadFullDocsArticle— it contains the discount-rule mechanics and the pre-create guardrails (conflict/stacking, margin floor, %-sanity).
Creates a discount that rewards customers for purchasing multiple items, encouraging product discovery and cross-selling. The discount activates when the cart contains a minimum number of items, and targets categories or products where bundling makes strategic sense.
Prerequisites
- Products exist in the catalog across multiple categories (
siteData.hasCatalog === true, checked at context load) - Categories with 2+ products suitable for bundling
Required APIs
Step 1: Use pre-loaded catalog data
Catalog analytics and product data are already in conversation context — do NOT re-fetch:
siteData.catalogAnalytics— category groups withmin(price),max(price),avg(profitMargin),count(). Loaded by the eCommerce Load Context.siteData.productCatalogData— per-product list sortedprice DESC, ordersCount DESCfor BUNDLE_AND_SAVE goal. Loaded by the run-a-sale orchestrator Step 5.
Extract the following from context:
min_price,max_price— from the "All Products" group insiteData.catalogAnalyticsavg_profit_margin— sets the discount ceilingcount— catalog breadth; more products = more bundling options- Top products by price and order count — from
siteData.productCatalogData
Step 2: Analyze cross-sell patterns
Evaluate the catalog for bundling opportunities:
- Category diversity: Look for categories with multiple products at complementary price points (e.g., a $50 main item + $15 accessories).
- Price range suitability: Wide price ranges (large gap between min_price and max_price) suggest tiered bundles. Narrow ranges suggest quantity-based bundles.
- High-margin categories: Categories with above-average profit margin are better candidates because the discount erodes less absolute profit.
- Popular + discoverable: Pair best-selling products (high ordersCount) with lower-visibility products to drive discovery.
Step 3: Set minimum item quantity
Determine the minItemQuantity based on catalog characteristics:
| Catalog Profile | Recommended minItemQuantity | Rationale |
|---|---|---|
| High-price items (avg price > price_p75) | 2 | Customers are less likely to buy 3+ expensive items |
| Medium-price items | 2-3 | Standard bundle size |
| Low-price items (avg price < price_p25) | 3-4 | Lower price per item makes larger bundles feasible |
| Many items in category (count > 10) | 3 | More products to choose from |
| Few items in category (count <= 5) | 2 | Limited selection constrains bundle size |
Default to minItemQuantity: 2 if data is ambiguous.
Step 4: Select discount percentage
Scale the discount to the average margin, rewarding multi-item purchases without eroding profitability:
| Margin Tier | Condition | Recommended Discount |
|---|---|---|
| Low margin | avg_profit_margin < 25% |
10% |
| Medium margin | 25% <= avg_profit_margin <= 50% |
15% |
| High margin | avg_profit_margin > 50% |
20% |
| No data | Margin unavailable | 10% |
Verify that the discount respects the global cap of 25% and the minimum margin threshold of 15% (discount <= avg_profit_margin - 15%).
Step 5: Determine discount scope
Select the scope based on bundling analysis:
- CATEGORY (preferred): When analytics show a clear category with cross-sell potential — multiple products, high margin, complementary items. Target that category.
- ITEMS: When specific complementary products are identified for bundling (max 5 productIds). Use when cross-sell pairs are specific rather than category-wide.
- SITE: When the goal is store-wide multi-buy incentive. Less targeted but simpler.
Step 6: Convert category names to GUIDs (if CATEGORY scope)
If scope is CATEGORY, call getCategoryIds to convert category names to GUIDs.
- Never use category names as scope IDs — always use the GUID.
- Exclude the "All Products" system category.
- Max 3 categoryIds per discount rule.
Step 7: Run guardrail checks
Run the pre-create guardrails in Create Discount Rule → "Guardrails" before creating the rule. Bundle discounts are especially prone to scope-overlap stacking (a customer buying 3 items in a category with both a bundle discount and a catalog-wide sale gets both) and coupon stacking — present any conflicts to the merchant and confirm.
Step 8: Create the discount rule with minItemQuantity condition
Endpoint: POST https://www.wixapis.com/ecom/v1/discount-rules
Request — Buy 2+ items from a category, get 15% off:
{
"discountRule": {
"name": "Buy 2+, Save 15% on Accessories",
"active": true,
"discounts": [
{
"discount": {
"discountType": "PERCENTAGE",
"percentage": 15
},
"scope": {
"id": "accessories-category-guid",
"type": "COLLECTION"
}
}
],
"conditions": {
"itemQuantityRange": {
"from": 2
}
}
}
}Response:
{
"discountRule": {
"id": "d4e5f6a7-b8c9-0123-def0-234567890123",
"revision": "1",
"name": "Buy 2+, Save 15% on Accessories",
"active": true,
"discounts": [
{
"discount": {
"discountType": "PERCENTAGE",
"percentage": 15
},
"scope": {
"id": "accessories-category-guid",
"type": "COLLECTION"
}
}
],
"conditions": {
"itemQuantityRange": {
"from": 2
}
}
}
}Request — Buy 3+ specific items, get 10% off:
{
"discountRule": {
"name": "Bundle 3 Best Sellers, Save 10%",
"active": true,
"discounts": [
{
"discount": {
"discountType": "PERCENTAGE",
"percentage": 10
},
"scope": {
"id": "product-uuid-1",
"type": "SPECIFIC_PRODUCTS"
}
},
{
"discount": {
"discountType": "PERCENTAGE",
"percentage": 10
},
"scope": {
"id": "product-uuid-2",
"type": "SPECIFIC_PRODUCTS"
}
},
{
"discount": {
"discountType": "PERCENTAGE",
"percentage": 10
},
"scope": {
"id": "product-uuid-3",
"type": "SPECIFIC_PRODUCTS"
}
}
],
"conditions": {
"itemQuantityRange": {
"from": 3
}
}
}
}Save the returned id and revision for later management.
Step 9: Verify the rule is active
- Query discount rules to confirm the new rule exists and is
active: true - Verify the minItemQuantity condition is correctly set
- Report to the merchant:
"Bundle discount is live: {discount}% off when buying {minItemQuantity}+ items from {scope description}. This encourages customers to explore more products and increases items per order."
Branching logic
| Merchant intent | Scope | minItemQuantity | Discount |
|---|---|---|---|
| "Encourage people to buy more" | Determined by analytics | 2-3 | Margin-tiered |
| "Bundle accessories together" | COLLECTION with category GUID | 2 | Margin-tiered |
| "Buy 3 get 20% off these products" (explicit) | SPECIFIC_PRODUCTS with product GUIDs | 3 (user override) | 20% (user override) |
| "Multi-buy deal on everything" | CATALOG (site-wide) | 2 | Margin-tiered |
| "Promote these 4 items as a set" | SPECIFIC_PRODUCTS (max 5) | 2-4 | Margin-tiered |
Error Handling
| Error | Cause | Fix |
|---|---|---|
DISCOUNT_RULE_NOT_FOUND |
Rule ID doesn't exist | Re-query discount rules for current IDs |
REVISION_MISMATCH |
Revision doesn't match | Re-fetch rule for latest revision, then retry |
| Too few products in category | Category has only 1 product — bundling not viable | Switch to SITE scope or suggest a different category |
| Margin data unavailable | No profit margin data in catalog | Default to 10% discount |
| Category GUID not found | Category name doesn't match any collection | Re-query categories or fall back to SITE scope |
| Max items exceeded | More than 5 productIds specified | Reduce to top 5 by ordersCount or switch to CATEGORY scope |