SalesForce

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

2 min. read

Salesforce Commerce Cloud (SFCC) is one of the best cloud-based e-commerce platforms. With it, businesses can create and manage online stores, streamline customer interactions, and optimize the digital shopping experience. Using the SFCC promotion engine is one way to drive customer engagement and increase sales.

The promotion engine is capable of enabling both product-based promotions and order-level promotions. Product-based promotions can specify items, categories, etc, and offer both percentage and currency-based discounts. Order-level promotions have similar capabilities and allow for promotions when certain products are in the basket (cart) or a particular price in the customer's total order has been crossed.

Unfortunately, order-based promotions are less capable when a promotion has multiple requirements. For example, with the native functionality, it's not possible to have a promotion that requires a specific product AND has a total order value over a particular dollar amount. Specifically, the promotion engine has problems with the word "AND."

The concept here is not unique. Oleg Sapishchuk provided an excellent analysis and seemed to have a solution in 2019. However, at the time of this writing, his solution provided more of a blueprint than an implementation in that the code linked in his post was no longer accessible from GitHub.

We understood conceptually that to make this work, we would need to perform the following actions in Business Manager and then modify the calculation script to take advantage of those changes.

  1. Modify the Promotion System Object Type
    1. Add a custom property as a strings or set of strings to allow for one or more dependant promotions (ID).
    2. Create a Attribute Grouping if one does not already exist.
    3. Add the newly created property to the grouping.
  2. Create a an Order Level promotion requiring a certain product to be in the basket with 0 dollars off.
  3. Create a an Order Level promotion requiring a currency limit ($75) that gives 10% discount on the order.
    1. Set the custom property to the ID of the prior promotion.

Since the cartridge we were working with did not have any customizations to the calculation engine, we made a copy of the calculate.js in our cartridge. We modified the hooks.json to call our copy of calculate. We modified the discounts applied to the cart using a set of helper functions to update the discount plan.

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;
    }, [])
}

Using this modification, the client can now build promotions of greater complexity. These promotions have contributed to both driving more sales and increasing the overall revenue from those sales.

Final thoughts

Customizations are not always needed in SFCC, but it was worth the extra time spent to make these modifications in this case. Tevpro has worked with many SFCC clients to deliver personalized and seamless B2B and B2C e-commerce experiences. Let us know what you are working on in Salesforce Commerce Cloud (SFCC) and if you have any questions. Reach us on Twitter or Linkedin, or send us a message.  

Keith Kikta

NestJS • C# • AWS • Azure • Integration • EPM • CPM