Try our conversational search powered by Generative AI!

K Khan
Jul 24, 2016
(2 votes)

Custom Promotions - eCommerce developer handout


Define metadata of Criteria and Reward. It should contain all properties needed to evaluate an order and apply a reward. For example, a PromotionData contains entries to which the promotion applies and the discount. Add to this type any property that a marketer should edit when setting up a promotion.  The base class provides basic metadata properties, such as name and valid dates.

  • EntryPromotion. Applies reward to a specific entry. Inherited from PromotionData
  • OrderPromotion. Applies reward to full order. Inherited from PromotionData
  • ShippingPromotion. Applies reward to order's shipping cost. Inherited from PromotionData

Note: Use one of those related class to create custom promotion meta data.


Decorate meta data properties like as colours to communicate meaning of properties to editors.
Colors make it easier to communicate what each property means in the UI. By adding the PromotionRegion attribute to a promotion property, it is marked for being included in the connection to the description. You also can use the PromotionRegion attribute on a block property, to connect properties in a block to the same part of the promotion description.


Promotion reward that can be either percentage of the purchase amount, or an absolute amount of for a given currency.

Localization in promotions

Like all content types, it is possible to translate the name and description by adding an element in the XML file whose name matches the content type. You can use a new formdescription sub-element to connect properties with the description. By adding "{regionname}some text{/}" in the text, the part "some text" gets the color matching that region. Both{regionname} and {/} are removed before the UI displays the description. e.g. For
[ContentType(GUID = "76EBFEFF-2CFB-42F2-B4A3-EA5EA5A41515")]

public class CustomPromotion : EntryPromotion

XML will be like

<name>My custom promotion</name>
<create see="/contenttypes/custompromotion/name" />
<description>Buy at least X items from categories/entries and get a % discount on the cheapest item.</description>
<formdescription>Buy {condition} at least X items from categories/entries{/} and get {reward}a % discount{/} on the cheapest item.</formdescription>


Very important object that is passed into promotion processors and reward applicators, which contains discount information about the affected items. Contains properties like Entry Prices, Shipment Prices, Current order Form Sub Total, Order Form and Order Group etc.

Promotion Processor

A class that evaluates if a promotion should apply a reward to an order and returns a Reward description from Promotion engine.


Abstract class inherited from IpromotionProcessor, You can inherit this class to build promotion processor but the recommended way is to inherit from the abstract EntryPromotionProcessorBase<TEntryPromotion>,  OrderPromotionProcessorBase<TOrderPromotion>, or  ShippingPromotionProcessorBase<TShippingPromotion> depending on the type of promotion being created.


Object that contains information about if and how a reward is applied. Importantant properties are

  • List of Redemption Description - one for each of the maximum amount of redemptions that could be applied to the current order
  • Reward Type - Depending on the type, the discount value is read from the properties UnitDiscountPercentage orQuantity
  • Status(Fulfilment status) - Orders with status Fulfilled will be honoured by promotion engine. (NotFulfilled, PartiallyFulfilled, Fulfilled, CouponCodeRequired, Excluded, VisitorGroupRequired, RedemptionLimitReached, InvalidCoupon, InvalidCombination, MissingVisitorGroup, NoRedemptionRemaining)


Describes one redemption of a reward. Its primary goal is to identify the objects to which the redemption should apply. Other than that, the RedemptionDescription also says how much this redemption saves on the order, and has a status flag that is set if the promotion engine (for some reason) decides not to apply this redemption. Most commonly, that is because a redemption limit was reached.


List of Affected entries for redemptions, if its an entry level promotion.


List of Affected shipments for redemptions, if its a shipment level promotion.


List of Affected orders for redemptions, if its and order level promotion.


defines which affected entries, received from the price matrix, should receive a discount. The method has two parameters: skip and take. The example "Buy 3, get the cheapest for free" should make the call SetDiscountRange(2, 1), which skips the first two items, and gives the discount (free) to the third. If all items get the discount, e.g. there is 20% off all items, SetDiscountRange does not have to be called.


  • A promotion may need a collection of currencies and amounts as part of the condition evaluation or reward logic. To achieve this, add an IList<Money> property to the custom promotion class. The same applies to the MonetaryReward type.
  • To include help text for custom groups on a campaign or promotion form, add the Display attribute with the GroupNameproperty set to the name of a specific node within the <groups> section in the resource files. The groups sections are content-type specific, so should be placed under <contenttypes> node for your specific type.
    [Display(GroupName = "MyNewGroup")]
    public virtual decimal Money { get; set; }
    The resource file will be like this
            <help>This is help text for my new group</help>
  • use base processor's method CreateRedemptionDescription
  • RewardDescription.CreateMoneyOrPercentageRewardDescription  can be used  to retrieve reward type.
  • Only promotions with the status Fulfilled will have their rewards applied.


Jul 24, 2016


Please login to comment.
Latest blogs
Optimizely Web... 6 Game Changing Features in 2024

If you are interested in learning about what's new within Optimizely Web, you are in the right place. Carry on reading to learn about the 6 greates...

Jon Jones | Mar 3, 2024 | Syndicated blog

Headless forms reloaded (beta)

Forms is used on the vast majority of CMS installations. But using Forms in a headless setup is a bit of pain since the rendering pipeline is based...

MartinOttosen | Mar 1, 2024

Uploading blobs to Optimizely DXP via PowerShell

We had a client moving from an On-Prem v11 Optimizely instance to DXP v12 and we had a lot of blobs (over 40 GB) needing uploading to DXP as a part...

Nick Hamlin | Mar 1, 2024 | Syndicated blog

DbLocalizationProvider v8.0 Released

I’m pleased to announce that Localization Provider v8.0 is finally out.

valdis | Feb 28, 2024 | Syndicated blog

Epinova DXP deployment extension – With Octopus deploy

Example how you can use Epinova DXP deployment extension in Octopus deployment.

Ove Lartelius | Feb 28, 2024 | Syndicated blog

Identify Azure web app instance id's for an Optimizely CMS site

When running Optimizely CMS in Azure, you will be using an instance bound cloud license. What instances are counted, and how can you check them? Le...

Tomas Hensrud Gulla | Feb 27, 2024 | Syndicated blog