Try our conversational search powered by Generative AI!

Tobias Nilsson
Apr 17, 2015
(3 votes)

An Example Product Level Pricing Provider


For some e-Commerce projects out there it might be more logical to store the prices on a product level than to store it on the variants. One example is clothing stores. A T-Shirt product might have four different sizes but they all cost the same. Then it makes sense to store the price on the product level instead of on the variant level.

Out of the box EPiServer Commerce UI only supports storing the prices on the variant level by using the default IPriceDetailService and IPriceService implementations. The good news is that the default implementation actually supports pricing on products and it’s very easy to create your own pricing implementation! The former part means we can keep our implementation of the two interfaces to a minimum and rely on the default implementations as much as possible.

Ready for the bad news? The Catalog UI does not support prices directly on products; all operations (CRUD) will be on variants or packages. For editors, this means that any price change must be performed on a variant. Our provider then needs to intercept any price changes coming from the UI and make them into a product price change. How this is done will be explained briefly later in the post.

Product Level Pricing Provider


Installing the Product Level Pricing Provider (PLPP) is easy. The PLPP consists of 4 files. Two are the implementation of the IPriceService and IPriceDetailService. The project also comes with a IConfigurableModule class which will configure EPiServer to use our providers instead of the default ones. The last file contains helper extension methods that will help us find the product parent of a variant or translate the prices from a variant price to a product price. You install it by either adding the project to your EPiServer solution or you build the project and place the assembly in the bin directory.


The PLPP adds one new configuration setting and that is if you want to store the prices on the variants or the products. I’ll explain the difference between the two values below.

<add key="ProductLevelPricing" value="true|false" />  

If no “ProductLevelPricing” setting is found, the default pricing implementations will be used instead.

Store the product prices on the variants (ProductLevelPricing == false)

Storing the prices on the variants means that each variant for a product will have the same set of prices stored on all of them. If you have a product with two variants linked to it and three product prices, those three prices will be stored for each variant resulting in a total of six prices in the database. This works by assuming that all the variants start out with the same price (or no prices) and then synchronizing the variants when a price change is done to either of them. The read performance of this mode is the same as the default implementation as the price is still stored on the variants. The write performance however will take a toll as it needs to update the variant, get the new prices, find the sibling variants, delete the siblings’ prices and update each sibling with the new prices. This is to ensure they are synchronized. As you can imagine, this will result in a performance hit and the hit will scale with the number of children/variants a parent product has. However, writing prices is generally an infrequent action so the performance hit will not matter on most sites.

Store the product prices on the product (ProductLevelPricing == true)

The other option is to store the prices on the product. If you have three prices on a product, then three prices will be stored in the database. This results in less redundant data but it also means a small incurred cost when fetching prices for a variant as we always need to find the product parent of the variant first. In your site you can avoid this cost by being sure only to query for product prices directly and by a sensible caching policy. This incurred cost cannot be avoided in the Catalog UI/Commerce Manager because the UI only deals with variant prices, but those are internal functions and the delay should be small.


This is only an example implementation and is offered as is. This is not a supported pricing provider by EPiServer and is not garanteed with upgrade/updates. If you find bugs or want to suggest improvements, feel free to contact me at the email below.


  • A variant can only be linked to one product.
  • The implementation assumes that all API calls are for one type of entry. It’s either variants or products never a mix of the two.
  • For the API call IList<IPriceDetailValue> Save(IEnumerable<IPriceDetailValue> priceValues) priceValues is an array of prices that belongs to one variant or product
  • This implementation was only tested on latest Commerce.Core and Commerce.UI Nuget package (8.11.1).
  • If product level pricing is not used (store prices on variants) and a price change is for a product, the price will not be saved on the product’s children and will be saved on the product.


You can find the source on Expert Services Bitbucket account:

If you need to solve this problem, I hope this helps. Please feel free to contact me with any questions/suggestions/bugs in EPiServer Expert Services at

Apr 17, 2015


K Khan
K Khan Apr 17, 2015 12:48 PM

Can we avoid GetCatalogEntryDto used in public static Boolean IsVariant(this ContentReference catalogContentReference)?


Apr 17, 2015 06:24 PM

Hi Khurram,

At first I used the Get(ContentReference), but that caused a deadlock as I was trying to read the same entry twice in the same thread. And apparently there's a read lock on the database table/row. So I had to resort to using the old method of getting the entry.

Please login to comment.
Latest blogs
Optimizely Opal... what it does actually do?

At Opticon 2023, Optimizely announced its first AI product Opal. AI is definitely the new tech buzzword in 2024 and with promises that AI will be...

Jon Jones | Feb 25, 2024 | Syndicated blog

How to add more Content Area Context Menu Item in Optimizely CMS 12

Hey folks, today I will share something related to Context Menu customization in the Content Area of Optimizely CMS. As you know, the content area ...

Binh Nguyen | Feb 25, 2024

Developer meetups in Stockholm & Helsinki

It's time for developer meetups! Next month we will be in Stockholm and Helsinki. Join us for getting the latest updates from Optimizely, be inspir...

Magnus Kjellander | Feb 23, 2024

Roll Your Own Security Headers

Proper security headers are a must for your Optimizely driven website. There are a variety of tools out there that will help with this, but when...

Ethan Schofer | Feb 21, 2024