Take the community feedback survey now.


Apr 17, 2015
  2368
(0 votes)

An Example Product Level Pricing Provider

Introduction

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

Installation

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.

Configuration

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.

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

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.

Disclamer

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.

Limitations

  • 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.

Source

You can find the source on Expert Services Bitbucket account: https://bitbucket.org/episerver-es/product-level-pricing-provider/.

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 Tobias.Nilsson@episerver.com.

Apr 17, 2015

Comments

Please login to comment.
Latest blogs
A day in the life of an Optimizely OMVP - Opticon London 2025

This installment of a day in the life of an Optimizely OMVP gives an in-depth coverage of my trip down to London to attend Opticon London 2025 held...

Graham Carr | Oct 2, 2025

Optimizely Web Experimentation Using Real-Time Segments: A Step-by-Step Guide

  Introduction Personalization has become de facto standard for any digital channel to improve the user's engagement KPI’s.  Personalization uses...

Ratish | Oct 1, 2025 |

Trigger DXP Warmup Locally to Catch Bugs & Performance Issues Early

Here’s our documentation on warmup in DXP : 🔗 https://docs.developers.optimizely.com/digital-experience-platform/docs/warming-up-sites What I didn...

dada | Sep 29, 2025

Creating Opal Tools for Stott Robots Handler

This summer, the Netcel Development team and I took part in Optimizely’s Opal Hackathon. The challenge from Optimizely was to extend Opal’s abiliti...

Mark Stott | Sep 28, 2025

Integrating Commerce Search v3 (Vertex AI) with Optimizely Configured Commerce

Introduction This blog provides a technical guide for integrating Commerce Search v3, which leverages Google Cloud's Vertex AI Search, into an...

Vaibhav | Sep 27, 2025

A day in the life of an Optimizely MVP - Opti Graph Extensions add-on v1.0.0 released

I am pleased to announce that the official v1.0.0 of the Opti Graph Extensions add-on has now been released and is generally available. Refer to my...

Graham Carr | Sep 25, 2025