Documentation Index Fetch the complete documentation index at: https://docs.synapsebuilder.org/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Discount Functions let you create custom discount logic beyond Shopify’s built-in discount types. Volume discounts, bundle pricing, tiered discounts, and customer-specific pricing.
How Discount Functions Work
Customer Action
Customer adds items to cart or enters checkout
Function Execution
Your function receives cart data and evaluates discount logic
Discount Applied
Function returns discount configuration
Price Updated
Shopify applies discount and updates cart/checkout
Discount Types
Volume Discounts Discount based on quantity
Buy 2 get 10% off
Buy 5 get 20% off
Tiered pricing
Bundle Discounts Discount on product combinations
Buy X + Y get Z free
Complete the set discount
Mix and match deals
Customer-Specific Personalized pricing
VIP customer discounts
Loyalty tier pricing
Wholesale pricing
Conditional Discounts Context-based pricing
First-time buyer discount
Time-based promotions
Location-based pricing
Example: Volume Discount
Generate a function that gives tiered discounts:
Describe Your Function
Create a discount function that gives 10% off when buying
2-4 units of the same product, 15% off for 5-9 units,
and 20% off for 10 or more units. Show the discount in
the cart and checkout.
Review Generated Code
Synapse creates:
Rust or JavaScript function
Input query for cart data
Discount calculation logic
Output configuration
Extension UI (optional)
Deploy & Test
Automatic validation
Deployed to dev store
Test with different quantities
Activate Function
Go to Discounts in admin
Create new discount using your function
Configure settings
Set active dates
Generated Function Structure
extensions/volume-discount/
├── src/
│ ├── run.rs # Function logic (Rust)
│ │ OR
│ ├── run.js # Function logic (JS)
│ └── run.graphql # Input query
├── shopify.extension.toml # Config
├── Cargo.toml # Dependencies (Rust)
│ OR
└── package.json # Dependencies (JS)
Function Code Examples
Rust (Recommended)
JavaScript
Input Query
Rust functions are faster and more efficient: use shopify_function :: prelude ::* ;
use shopify_function :: Result ;
#[shopify_function_target(query_path = "src/run.graphql" , schema_path = "schema.graphql" )]
fn run ( input : input :: ResponseData ) -> Result < output :: FunctionRunResult > {
let discounts = input
. cart
. lines
. iter ()
. filter_map ( | line | {
let quantity = line . quantity;
let percentage = match quantity {
2 ..= 4 => 10.0 ,
5 ..= 9 => 15.0 ,
10 .. => 20.0 ,
_ => return None ,
};
Some ( output :: Discount {
message : Some ( format! ( "{}% volume discount" , percentage )),
targets : vec! [ output :: Target {
product_variant : Some ( output :: ProductVariantTarget {
id : line . merchandise . id . clone (),
quantity : None ,
}),
}],
value : output :: Value :: Percentage ( output :: Percentage {
value : Decimal :: from ( percentage ),
}),
})
})
. collect ();
Ok ( output :: FunctionRunResult { discounts })
}
JavaScript functions are easier to modify: export function run ( input ) {
const discounts = input . cart . lines
. map ( line => {
const quantity = line . quantity ;
let percentage ;
if ( quantity >= 10 ) {
percentage = 20 ;
} else if ( quantity >= 5 ) {
percentage = 15 ;
} else if ( quantity >= 2 ) {
percentage = 10 ;
} else {
return null ;
}
return {
message: ` ${ percentage } % volume discount` ,
targets: [{
productVariant: {
id: line . merchandise . id
}
}],
value: {
percentage: {
value: percentage . toString ()
}
}
};
})
. filter ( discount => discount !== null );
return { discounts };
}
GraphQL query defines function input: query RunInput {
cart {
lines {
id
quantity
merchandise {
__typename
... on ProductVariant {
id
product {
id
title
hasAnyTag ( tags : [ "volume-discount" ])
}
}
}
}
}
}
Common Discount Patterns
Buy one product, get another free/discounted: // Check if customer has product X
let has_product_x = input . cart . lines . iter ()
. any ( | line | line . merchandise . product . id == "gid://shopify/Product/123" );
if has_product_x {
// Apply discount to product Y
discounts . push ( Discount {
targets : vec! [ Target {
product_variant : Some ( ProductVariantTarget {
id : "gid://shopify/ProductVariant/456" . to_string (),
}),
}],
value : Value :: Percentage ( Percentage { value : Decimal :: from ( 100 ) }),
message : Some ( "Free with purchase!" . to_string ()),
});
}
Prompt Example: "Create a discount function where if customers buy any t-shirt
(tagged 'tshirt'), they get 50% off any socks (tagged 'socks')"
Discount when cart total reaches threshold: use rust_decimal :: Decimal ;
let cart_total : Decimal = input . cart . lines . iter ()
. map ( | line | {
let price = Decimal :: from_str ( & line . merchandise . price) . unwrap ();
price * Decimal :: from ( line . quantity)
})
. sum ();
if cart_total >= Decimal :: from ( 100 ) {
// Apply 10% off entire cart
discounts . push ( Discount {
targets : vec! [ Target :: OrderSubtotal ],
value : Value :: Percentage ( Percentage {
value : Decimal :: from ( 10 )
}),
message : Some ( "10% off orders over $100" . to_string ()),
});
}
Prompt Example: "Create a discount that gives 15% off the entire order when
the subtotal is $150 or more"
Discount for specific customer groups: // Check customer tags
let is_vip = input . cart . buyer_identity
. as_ref ()
. and_then ( | identity | identity . customer . as_ref ())
. map ( | customer | customer . has_any_tag ( vec! [ "vip" ]))
. unwrap_or ( false );
if is_vip {
// 20% off for VIP customers
discounts . push ( Discount {
targets : vec! [ Target :: OrderSubtotal ],
value : Value :: Percentage ( Percentage {
value : Decimal :: from ( 20 )
}),
message : Some ( "VIP member discount" . to_string ()),
});
}
Prompt Example: "Create a discount function that gives 25% off to customers
tagged 'wholesale' on all products in the 'bulk' collection"
Discount for buying complete sets: let required_products = vec! [
"gid://shopify/Product/1" ,
"gid://shopify/Product/2" ,
"gid://shopify/Product/3" ,
];
let has_all = required_products . iter () . all ( | product_id | {
input . cart . lines . iter ()
. any ( | line | line . merchandise . product . id == * product_id )
});
if has_all {
// 30% off when buying complete bundle
discounts . push ( Discount {
targets : required_products . iter () . map ( | id | {
Target :: ProductVariant ( /* ... */ )
}) . collect (),
value : Value :: Percentage ( Percentage {
value : Decimal :: from ( 30 )
}),
message : Some ( "Bundle discount!" . to_string ()),
});
}
Prompt Example: "Create a bundle discount where if customers buy a camera,
lens, and memory card together, they get 25% off the total
for those three items"
Function Configuration
Functions can have configurable settings:
# shopify.extension.toml
[[ extensions . settings ]]
name = "min_quantity"
type = "number_integer"
description = "Minimum quantity for discount"
[[ extensions . settings ]]
name = "discount_percentage"
type = "number_decimal"
description = "Discount percentage to apply"
[[ extensions . settings ]]
name = "eligible_products"
type = "product_reference"
description = "Products eligible for discount"
Access settings in your function:
let min_quantity = input . discount_node . metafield
. as_ref ()
. and_then ( | m | m . value . parse :: < i64 >() . ok ())
. unwrap_or ( 2 );
let discount_percentage = input . discount_node . metafield
. as_ref ()
. and_then ( | m | m . value . parse :: < f64 >() . ok ())
. unwrap_or ( 10.0 );
Testing Discount Functions
Create Discount in Admin
Go to Discounts
Create → Discount
Select your function
Configure settings
Test in Storefront
Add eligible products to cart
Verify discount appears
Check discount amount is correct
Test edge cases
Review Logs
Check function execution logs: shopify app function logs
View input/output for each execution
Performance Testing
Test with many cart items
Measure execution time
Verify under 5ms threshold
Discount functions must execute in under 5ms:
Minimize Loops Avoid nested loops over cart items // Good: Single pass
let total = lines . iter () . map ( | l | l . price) . sum ();
// Bad: Nested loops
for line in & lines {
for other in & lines {
// ...
}
}
Use Rust Rust functions are 10-100x faster than JavaScript
Compiled to WebAssembly
No garbage collection
Type-safe
Recommended for production
Cache Calculations Don’t recalculate the same value // Calculate once
let cart_total = calculate_total ( & input . cart);
// Reuse
if cart_total > threshold {
// ...
}
Limit API Surface Only query data you need in run.graphql # Good: Specific fields
query RunInput {
cart {
lines {
quantity
merchandise { id }
}
}
}
Debugging Functions
Local Testing
Live Logs
Error Handling
Test functions locally before deploying: cd extensions/discount-function
# Test with sample input
shopify app function run
# Provide test input
cat test-input.json | shopify app function run
View function executions in real-time: shopify app function logs --watch
Shows:
Input received
Output generated
Execution time
Errors
Functions should never panic: // Good: Handle errors
let quantity = line . quantity . parse :: < i64 >()
. unwrap_or ( 0 );
// Bad: Panic on error
let quantity = line . quantity . parse :: < i64 >()
. expect ( "quantity must be number" );
Limitations
Discount Functions have certain restrictions:
Limitation Details
Execution Time Must complete in under 5ms No Network Calls Cannot fetch external data Deterministic Same input must give same output Stateless No access to previous executions Cart Data Only Limited to provided input query
Example Prompts
Create a discount function with multiple spend tiers:
- $50-$99: 5% off
- $100-$199: 10% off
- $200+: 15% off
Apply to entire order. Show the tier achieved in the discount message.
Create a discount where customers get 20% off when they buy
at least 3 items from the 'summer-collection'. Items can be
any combination. Show "Summer Mix & Match: 20% off" message.
Give first-time customers (tagged 'first-order') 15% off
their entire order. Check if customer is tagged, apply
discount to order subtotal. Message: "Welcome! First order discount"
Create tiered discounts based on customer tags:
- 'loyalty-bronze': 5% off
- 'loyalty-silver': 10% off
- 'loyalty-gold': 15% off
Apply to all products. Show tier name in message.
Next Steps
Payment Customization Customize payment methods
Shipping Customization Customize shipping rates
Functions Overview Learn about all function types
Debugging Debug and optimize functions