Sitecore has great personalization features. Personalization in Sitecore is based on the content you visit and the actions you perform on the website.
You use content profiling to gain a better understanding of the interest of your visitor. You assign profile cards to your content items to indicate which "type" of user the content is interesting for.
You can use the outcome of content profiling for a particular visitor and any other information you have (like the visitor's location, contents of the cart etc.) to personalize the site.

Personalization conditions for Commerce

Out of the box, you get the following conditions in Sitecore XP when you install the Sitecore Commerce Connect Core package:

Cart conditions

  • where the quantity of all products in user's cart compares to specific value
  • where the user's cart total compares to specific value
  • where the quantity of product product id in user's cart compares to specific value

Stock count conditions

  • Current Product has stock count compares to specific stock count
  • Current Product has stock count compares to specific stock count in location equals to specific location
  • Product with ID specific product id has stock count compares to specific stock count
  • Product with ID specific product id has stock count compares to specific stock count in location equals to specific location

Stock status conditions

  • Current product has stock status equals to specific stock status
  • Current product has stock status equals to specific stock status in location equals to specific location

You can add your own conditions by implementing them in the normal way as you would a Sitecore XP condition. But be aware that if you need to call the commerce engine to get information for your condition, your condition could be costly with regards to performance. So make sure the data you are working with is cached in some way.

How does content profiling work on a catalog?

Content profiling in Sitecore XP basically works by labelling your content with values that tell which audience it is interesting for (and I know I'm simplifying). For example, if you have a company website, you have different audiences: potential customers, people that are already a customer, people looking for a job at your company etc.

By labelling your content with the intendend audience you can probably determine which kind of visitor is on your site by looking at the content she visits. If she is looking at content that is labelled for potential customers the likelyhood that your visitor is a potential customer goes up. You can use that information that personalize the site, for instance by adding banners or showing content on the homepage targeted at your visitor's audience group.

You can do this with "normal" content, but you can do exactly the same with your products (as they are also content).

You "label" your content for different audiences by assigning profile cards or set profile keys on your content. To assign profile cards to a catalog item you do the same as you would do for any normal content item. You click the Edit Profile Cards button for a sellable item or category and specify a profile card. Easy.

Now you just have to do this for the hundreds, thousands or hunderds of thousands of other products you have in your catalog.

Obviously, doing this by hand doesn't scale. So, how can we scale this up?

Scaling personalization

If we want personalization to scale we need some way to automate the assignment of profile cards to catalog items.

Profile cards are saved on a sellable item or category in the ExternalSettingsComponent. The ExternalSettingsComponent is the place where all Sitecore XP related settings are saved. They are saved in a serialized JSON format.

The ExternalSettingsComponent has one property called Settings which is used to store the Sitecore XP settings serialized as JSON.

The structure of the contents of Settings is as follows:

    {
        "<sitecore node id>": { 
            "<language 1>": {
                    <language specific settings for language 1>
                },
            "<language 2>": {
                    <language specific settings for language 1>
                },
            "shared": {
                <shared settings>
            },
        "<sitecore node id>": { 
            "<language 1>": {
                    <language specific settings for language 1>
                },
            "<language 2>": {
                    <language specific settings for language 1>
                },
            "shared": {
                <shared settings>
            }
            
    }

You might be wondering why there are two sitecore nodes (represented by two sitecore node id entries)? Well you have to realize that a sellable item has a different sitecore id based on the location of the item in the category tree. So the sitecore id of sellable item A in category B is different from the same sellable item A in category C.

The unique Sitecore id for a node is generated based on the sitecore id assigned to the sellable item by the engine concatenated with the sitecore id assigned by the engine on the category (using a pipe symbol to separate them) which is then hashed using MD5.

This also means that if you set the profile card for one location of a sellable item in the category structure, you will also need to set it for any other location. This does mean that your profile card configuration can be category (so context) specific which is a good thing and gives you more flexibility.

The profile cards are not language specific so are stored in the "shared" key.

Automating setting profile cards

How can we automate setting of profile cards? We first need to know which calls the data provider does to the commerce engine to retrieve sellable items. After some investigation using Fiddler, you can see it is doing calls to https://localhost:5000/api/GetCatalogItemAllLanguages(...) (this is on XC 9.2, depending on which version you have, you may have a different call).

This call executes a 'GetCatalogItemConnectCommand', which calls the IGetSellableItemConnectPipeline to retrieve the sellable item. Notice that the commands and pipelines that have Connect in their name are there specifically for the Commerce Data Provider in Sitecore XP.

So now we know we can extend the IGetSellableItemConnectPipeline to add a block that includes logic to set the profile card information. For this proof-of-concept, we're not going to save the profile information on the sellable item but depending on your needs you could do that as well. As saving is an expensive operation, just make sure you only do this once when retrieving the item for the first time.

You can find all the code for this example in this repository: https://github.com/ewerkman/Sitecore.Commerce.Plugin.ProfileCards

This repository contains two projects:

  • One (Sitecore.Commerce.Plugin.ProfileCards) for a plugin that extends the IGetSellableItemConnectPipeline with a block that parses the tracking field in the external settings component and puts the data into a nice model and then calls a custom pipeline called ISetTrackingFieldPipeline for each parent category;
  • Another plugin (Sitecore.Commerce.Plugin.ProfileCards.Sample) that is a sample implementation which adds a block to ISetTrackingFieldPipeline, which sets the profile card each time the pipeline is called.

Sitecore.Commerce.Plugin.ProfileCards

This plugin is not really complicated:

  • It contains ,odels so we can represent the information that is in the tracking field in the external settings component in an easier to use way.
  • Defines a custom pipeline called ISetTrackingFieldPipeline;
  • It extends the IGetSellableItemConnectPipeline with a block called SetTrackingFieldBlock that parses the external settings component on a sellable item, deserializes the XML in the __Tracking field using the models. It then calls the custom pipeline ISetTrackingFieldPipeline providing it with the sellable item and the tracking model. The result of that pipeline is then again serialized into the __Tracking field and set on the ExternalSettingsComponent.

Sitecore.Commerce.Plugin.ProfileCards.Sample

This is a sample plugin that shows you how to use the functionality in the Sitecore.Commerce.Plugin.ProfileCards plugin. It adds a block called SetInterestProfileCardBlock to the ISetTrackingFieldPipeline, which sets the Interest profile for any sellable item that is run through the pipeline. Of course this is a little bit basic functionality, but as you have the sellable item information available in the TrackingFieldArgument.SellableItem property you can act on the information you have there to set the correct profile information.

Conclusion

This is a sample and simple implementation, but you can imagine how you can extend this. The sample is now only for sellable items but it is possible to extend this to categories and catalogs.

One thing to consider is that while you can have different values for the profile based on the category a sellable item is in, you cannot change the profile based on any customer specific information as the information on a sellable item is cached and not specific for a user.

Happy profiling!