Tevpro insights

Customizing Order-Level Promotions in Salesforce Commerce Cloud (SFCC)

Learn how to extend Salesforce Commerce Cloud promotions with custom order-level logic for more flexible discounts and business rules.

Salesforce

Key takeaways

  • This example combines two order promotions: a qualifying-product rule and an order-value discount. The dependency between them requires custom logic in this implementation.
  • Store the prerequisite promotion ID in a custom Promotion attribute so the calculation logic can determine which discount depends on another promotion.
  • The example customizes basket calculation to inspect the discount plan and remove discounts whose prerequisite was not met; test the result against the storefront and basket totals.
  • Treat the cartridge and hook changes as a project-specific pattern, not a drop-in SFCC configuration. Verify promotion behavior, stacking, and calculation hooks in your own environment.

A Salesforce Commerce Cloud order promotion can check basket conditions or order value. In this project, the team needed both: a qualifying product in the basket and an order total above a threshold before applying the discount. The existing promotion setup did not cover that combination, so they linked two promotions and adjusted the basket calculation.

Why link two promotions?

The first promotion checks for the qualifying product but offers no discount. The second checks the order threshold and applies the discount. A custom Promotion attribute records the prerequisite ID so the calculation logic can withhold the second discount when the first condition is not met.

A related approach was described by Oleg Sapishchuk in 2019. The steps below reflect the implementation this team used, rather than a built-in configuration option.

Set up the promotions in Business Manager

Create the dependency field first, then configure the two order promotions:

  1. Add a custom attribute to the Promotion system object type to hold the prerequisite promotion ID or IDs.
  2. Add the attribute to a Business Manager attribute group so it can be edited.
  3. Create an order promotion requiring the qualifying product in the basket, with a $0 discount.
  4. Create a second order promotion with a $75 threshold and a 10% order discount.
  5. On the discounting promotion, set the custom attribute to the ID of the qualifying-product promotion.

Enforce the dependency in basket calculation

In this project, the cartridge had no existing calculation customization. The team copied calculate.js into its cartridge and pointed hooks.json at that copy. Helper functions then inspected the discount plan and removed the order discount when its prerequisite promotion had not applied. The code below shows the project-specific logic; verify its APIs and hooks against your SFCC environment before adapting it.

Code example
javascript
function validateDiscountPlan(basket) {
    var activePromos = PromotionMgr.getActiveCustomerPromotions();
    const dependant = promotionsWithDependencies(activePromos.promotions);
    const firstDiscount = PromotionMgr.getDiscounts(basket, activePromos);
    const activeOrderDiscounts = promotionsInOrderDiscountPlan(firstDiscount);
    dependant.forEach(function (promo) {
        var list = promo.custom.DependentPromotionID;
        for(let i = 0; i < list.length; i++)
            if (!idExists(activeOrderDiscounts, list[i]))
                activePromos.removePromotion(promo);
    })
    const discountPlan = PromotionMgr.getDiscounts(basket, activePromos);
    return discountPlan;
}

function idExists(items, id) {
    for (var i = 0; i < items.length; i++) {
        if (items[i] == id)
            return true;
    }
    return false;
}

function promotionsWithDependencies(promotions) {
    return collections.reduce(promotions, function (accu, item) {
        if (item.custom.DependentPromotionID && item.custom.DependentPromotionID.length > 0)
            accu.push(item);
        return accu;
    }, [])
}

function promotionsInOrderDiscountPlan(discountPlan) {
    return collections.reduce(discountPlan.orderDiscounts, function(accu, discount) {
        const id = discount.promotion.ID;
        accu.push(id);
        return accu;
    }, [])
}

Validate the promotion behavior

Test the qualifying product alone, the order threshold alone, both conditions together, and neither condition. Check the discount plan and the final basket total for each case. Also test interactions with other promotions so a different discount does not unexpectedly change the result.

When this pattern is useful

A linked-promotion pattern is useful when a project needs a condition the standard promotion setup does not express in its environment. It adds calculation code that the team must own and retest, so confirm the requirement before customizing the cartridge.

Need help planning or validating a Salesforce Commerce Cloud promotion? Get in touch with Tevpro.

Sources

Why work with us

Why Tevpro?

Whether you’re a startup with a bold product idea or an established company seeking a stronger delivery partner, Tevpro delivers results. Our expert consultants specialize in building secure, scalable applications that simplify operations and drive real ROI.

FAQ

Why we linked two SFCC order promotions

The decisions behind this project-specific promotion setup.

The requirement combined two conditions: a specific product had to be in the basket and the order total had to pass a threshold before the discount applied. The team used one promotion to represent each condition and added dependency logic in its calculation script. That describes this implementation, not a blanket limit on every SFCC promotion configuration.