September 8th 2024
OrderCloud comes with a very powerful Promotions rules Engine.
It aligns perfectly with OrderCloud's "Flexibility over Features" motto.
But that flexibility comes with some level of complexity.
In this blog post, I will try to demystify some of this complexity by sharing some real-life examples from a recent Project. I will be focusing on the Eligible and Value Expressions specifically.
The basics:
OrderCloud Promotions are based on 2 types of expressions:
Eligible Expression: Eligible expression is made of one or multiple conditions to decide if a user qualifies or not for your promotion. For example: A minimum subtotal of 50$ or more, or Having specific products in your cart.
Value Expression: Value expression is the benefit you get from the promotion. It can be an amount or a percentage. For example 54 off of the cart subtotal, 20% off of a specific product or Free Shipping.
These expressions can refer to any properties from the order or the line items.
With order you can access properties directly from v1/orders response usins the 'order' token. Example: order.Subtotal.
With Line Items you have 2 options:
items: You can use 'items' token combined with functions such as any(), all(), total(), count()... to evaluate the properties from v1/lineitems response objects. Example: items.any(ProductID='123')
item: You can use 'item' token to directly access any property from the v1/lineitems response objects. Example: item.ProductID='123'.
N.B: To be able to use item in your expressions, the promotion must be set with LineItemLevel = true. Also, setting LineItemLevel to true makes usage of item mandatory in the Eligible Expression.
In addition to the Eligible Expression and Value Expression, there are many other properties you need to set when creating a promotion such as LinItemLevel mentioned above, redemption limits, Start and Expiration Dates and so on.
For more details and more examples please check OrderCloud documentation here.
Real-Life Scenarios:
Let's now get to some real-life scenario promotions and how you build your Eligibility and Value Expressions.
Let's start with an easy one to get warmed up!
First Scenario: 5$ off for all US shoppers
In this scenario your first thought would be:
Eligibility Expression: order.Currency='USD'
Value Expression: 5
However, there is an issue here, what if the order subtotal is less than 5$ ?
With the expressions above, you end up with a negative total amount, which doesn't make sense.
How do you fix this then?
First, you need to know and ask your Marketing department what is the expected outcome?
Option 1: You only qualify if your cart subtotal is >= 5.
Your Eligibility Expression becomes order.Currency='USD' and order.Subtotal >= 5
Your Value Expression remains the same.
Option 2: If the subtotal < 5 you get your order for free.
Your Eligibility Expression remains the same.
Your Value Expression becomes: min(order.Subtotal, 5)
Second Scenario: 10$ Off the order, excluding Sale Items.
This is an interesting one. If the value was in percentage, like 10% Off instead of the amount, the expressions would simply be:
Eligibility Expression: item.IsOnSale=false
Value Expression: item.LineSubtotal*0.1
This would exclude Sale Items because when you use item token in both Eligibility and Value Expressions, unqualified items are implicitly excluded from the value calculation.
In our example we want a Cart Level Amount Discount, but we still want to exclude Sales Items.
For example, if in your cart you have:
A regular priced item at 5$
A Sale Item at 10$
The expected discount is 5$.
To fulfill this requirement you need to use items token in your value expression to explicitly exclude the Sale items. Your expressions should then look like:
Eligibility Expression: item.IsOnSale=false
Value Expression: min(items.total(IsOnSale=false), 10)
Third Scenario: Free Shipping when you purchase a specific product, but only for Standard Rates.
In this scenario we want to offer users free shipping under condition, but only applies to Standard Shipping. If they decide to go with a premium shipping option then the discount shouldn't apply.
Let's say your shipping rates are:
Standard: 5$
Priority: 10$
Premium: 30$
Your Expression will look like this:
Eligibility Expression: items.any(ProductID='{ProductID}') and order.ShippingCost < 10
Value Expression: order.ShippingCost
A couple notes here:
I chose to use order.ShippingCost < 10 instead of order.ShippingCost=6 in the Eligible Expression to allow for some flexibility for the standard rate to go up.
I chose to use order.ShippingCost instead of the absolute rate of 6 in the Value Expression for the same reason. Flexibility.
Promotion Eligibility Management in your storefront:
Be aware that once a promotion is added to your order, it won't be automatically removed if the user is no longer Eligible.
If we use the example above where Eligiblity Expression = items.any(ProductID='12345') and order.ShippingCost < 10
If the user adds the promotion, then removes the Product '12345', he's no longer eligible, but the promotion is still in the order, and the order cannot be submitted.
My solution to this situation was the following:
On order/direction}/{orderId}/calculate, catch specific error codes Promotion.NotEligible and Promotion.Expired then capture the promotion code from the response and call DELETE orders/{direction}/{orderId}/promotions/{promotion code} to remove it from the order.
Ensure order calculate is called every time there is a change in the order that implies monetary changes:
Product added to Cart
Product removed from Cart
Shipping Method Changed
Shipping Address Changed (Tax Impact)
And so on...
P.S: There might be other solutions, so please do your own research and engage with OrderCloud team if needed. I am sharing the approach that worked well for us.
Other Important considerations when you create a Promotion:
RedemptionLimit : Allows you to limit the overall usage of the promotion.
RedemptionLimitPerUser: Allows you to limit the usage per user.
RedemptionCount: A read-only field that indicates how many times the promotion was redeemed. Can be useful for reporting and marketing decision making.
AllowAllBuyers: If set to false, you need to explicitly assign promotions to Buyers.
AutoApply: If set to true, the promotion applies without having to enter a code.
CanCombine: If set to true, allows the promotion to be combined with other 'CanCombine' promotions.
Conclusion:
Rules-Based Promotion Expressions is very flexible and can be complex when you get started. But there are many tools and resources to help you get a grasp on it:
Also, OrderCloud offers free Sandboxes for everyone to explore. The best way to learn is to spin up a Sandbox, play with the API and build your proof of Concept.
For Folks attending Sitecore Symposium in Nashville this year, you don't want to miss this great Deep Dive session/workshop by OrderCloud Team. it's a fantastic opportunity to get hands-on and explore a variety of uses-cases. You can find it in the Agenda here
I hope you find this blog post helpful. Feel free to reach out if you have any questions or comments.
Comments