Hide menu Last updated: Mar 07 2017
Area: Episerver Commerce Applies to versions: 10 and higher
Other versions:

Episerver Recommendations [Beta]

The Recommendations package integrates Commerce with Episerver Perform, allowing you to track user behavior then use that information to show personalized product recommendations. The Recommendations package constitutes the Commerce half of the integration. You also need an Episerver Perform environment to receive tracking data and serve recommendations.

Note: Episerver Recommendations (Beta) is a work in progress. The functionality described here may change significantly at any time without notice.

Obtaining an Episerver Perform environment

During the Beta period, there is no automated way to order an Episerver Perform environment. Contact Episerver to place your order. When your environment is ready, you will receive an email containing values needed to configure the Recommendations package.

Installing and configuring the Recommendations package

The Recommendations package is available for installation via the Episerver NuGet feed. When the installation is completed, you must modify the configuration to include settings for your Episerver Perform environment.

Recommendations reads its configuration from the <appSettings> section. The following keys are used.

Key Description
episerver:RecommendationsBaseApiUrl The URL of the Episerver Perform environment to be used. This should only contain the protocol and host name.
episerver:RecommendationsSite The site name used to identify the requests to the tracking server.
episerver:RecommendationsClientToken The token used to authenticate tracking requests to the REST API.
episerver:RecommendationsAdminToken The token used to authenticate admin requests to the REST API.
episerver:RecommendationsSilentMode [Optional] The switch to turn recommendations on or off. If set to true, no tracking data is sent, and the TrackingService returns no recommendations.
episerver:CatalogFeedBatchSize [Optional] The number of products processed in one batch when the product feed is generated. A higher value can be faster but puts more pressure on the memory. The default value is 50.
episerver:CatalogNameForFeed [Optional] Selects the catalog used to generate product feed if you have multiple catalogs. If this value is not set, the first catalog is used.
Note: This property will be removed when Product feed support for multiple catalogs is added.

 

The export function has a few settings in addition to those mentioned in the configuration table. These settings need to be set via code on the default CatalogFeedSettings instance:

var catalogFeedSettings = ServiceLocator.Current.GetInstance<CatalogFeedSettings>();
catalogFeedSettings.DescriptionPropertyName = "...";
Property Description
ExcludedAttributes Names of product properties you want to exclude from the catalog feed.
DescriptionPropertyName The product feed requires each item (product) to have a description. Set this value to a property name you want to use as description. Default value is "Info_Description".
AssetGroupName The first asset in this group is used for the item's image link. The default value is "default".

Exporting your catalog to Episerver Perform

In order for Episerver Perform to provide accurate and valuable recommendations, your catalog must be exported to Episerver Perform on a regular basis. Start your site, enter admin mode, and start the Export Product Feed scheduled job. If the job finishes with a successful status, your catalog was successfully exported to Episerver Perform. It is recommended to schedule the export job to run every 24 hours.

The scheduled job has two parts:

  • Serialize the catalog to XML, compress it, and store as a blob.
  • Notify Episerver Perform that a new catalog is available for download.

To notify Episerver Perform that a new catalog export is available, the scheduled job calls the Episerver Perform REST API (via HTTPS) and passes a callback address and an authorization token. When the Episerver Perform environment has the resources to handle downloading the catalog, it calls the specified callback method and passes the token. If the callback method determines that the passed token is valid, the download is allowed.

The callback address is calculated using SiteDefinition.SiteUrl as the host and a static path. It is recommended that the SiteUrl be set to use the HTTPS protocol.

Export Flow

Tracking and recommendations

Tracking user activities and retrieving recommendations are performed simultaneously in a single roundtrip to the Episerver Perform environment. This roundtrip is made synchronously and adds a small processing overhead to all tracked requests. The following diagram describes the flow for page requests that end up in a controller action decorated with a TrackingAttribute. The flow is identical for tracking requests not triggered by the TrackingAttribute except the custom tracking code replaces the OnActionExecuting step.

Tracking flow

User identification

To provide good recommendations, Perform needs to track a visitor's activities over time. This is accomplished by assigning each visitor a consolidated user ID (CUID). CUIDs are stored in cookies and, if the visitor is authenticated, in the Commerce database. For each request, the CUID is selected in this order of preference:

  1. Use CUID stored in the database.
  2. Use CUID stored as a cookie.
  3. Create and use a new CUID, store it in the database (if user is authenticated) and cookie.

Each user session is also assigned a session ID stored as a session/transient cookie. This means that CUIDs for anonymous visitors are stored as cookies, and if that visitor logs in at a later stage, the CUID in the database overwrites the cookie CUID. Or, if there is no CUID in the database, the cookie CUID is saved to database. If the CUID changes during a session (as in the former case above), the session ID makes it possible to associate all session activities with the correct user.

Tracking types

User activities that can be tracked are contained in the TrackingType enum. They listed in the following table. Try to track as many activities as possible - more activities tracked result in better recommendations. The Attribute Support column indicates whether the activity can be tracked by decorating controller actions with an attribute - see TrackingAttribute.

TrackingType Activity Attribute Support
Home View the start page. Yes
Product View a product. Yes
Category View a branch of the catalog tree, e.g. Fashion>Mens>Shoes. Yes
Attribute View products with a specific attribute value, e.g. Color: Red. No *
Brand View products of a specific brand. No *
SearchResults Search for a term. No **
Wishlist Modify the wishlist. Yes
Basket Modify the basket/cart. Yes
Checkout User is about to place and order. Yes
Order User has placed an order. No **
Other View a page not covered by other tracking types. Yes

* Attribute and Brand tracking are not supported by default, but you may be able create your own implementation of TrackingRequestFactory to support them. See Extending TrackingRequestFactory.

** SearchResults and Order tracking are not supported because the required tracking data is not available when the TrackingAttribute code is executed.

Sending tracking information

Using the TrackingAttribute

The TrackingAttribute is an ActionFilterAttribute designed to be placed on controller actions. The parameter for the TrackingAttribute constructor is one of the TrackingTypes from the table above. If the passed TrackingType is supported by the TrackingAttribute, it automatically collects the necessary data and performs a tracking request in the OnActionExecuting method. In the following example, the Index method of the start page controller sends a home page tracking request when executed.

[Tracking(TrackingType.Home)]
public ViewResult Index(StartPage currentPage)
{ ... }

Tracking without using the TrackingAttribute

If the TrackingType is not supported by the TrackingAttribute, or if the action to be tracked cannot be tied directly to a controller action, you need to handle tracking in a more hands-on way. In these cases, you need to manually:

  1. Create the relevant TrackingData object.
  2. Pass the TrackingData object to the TrackingService.Send method.

To construct TrackingData objects, call methods on TrackingDataFactory. TrackingDataFactory acts as a bridge between the Commerce system and the tracking system - accepting objects from the Commerce world as parameters and returning objects that are disconnected from Commerce. To send tracking data, call the Send method on the TrackingService. In the following example, both the TrackingDataFactory and the TrackingService (ITrackingService) are injected via constructor:

var trackingData = _trackingDataFactory.CreateCategoryTrackingData(category, httpContext);
var result = _trackingService.Send(trackingData, httpContext);

Consuming recommendations

Depending on how the Episerver Perform environment is configured, different types of tracking events may or may not return recommendations. This section explains a general case where recommendations are returned and should be displayed to the visitor.

Using the TrackingAttribute

As the TrackingAttribute executes code in the OnActionExecuting method, the recommendations are available as soon as the controller action method is entered. To get recommendations, call the Controller extension method GetRecommendations.

[Tracking(TrackingType.Home)]
public ViewResult Index(StartPage currentPage)
{
    var recommendations = this.GetRecommendations();
    ...
}

The method returns a collection of Recommendation objects, where each object has an Area and a collection of ContentReferences referencing the recommended products. The Recommendation object can then be used to create model data to display recommended products to the visitor.

The number of Recommendation objects and the names of the areas are dependent on how the Episerver Perform environment is configured. The corresponding name for these recommendation groupings on the Episerver Perform side is widgets. A widget contains information about where recommendations should be shown on the page (left, right, bottom etc.) and which algorithms to run to generate the recommendations (similar products, cross sells, etc.).

var productRefs = 
   this.GetRecommendations()
      .Where(x => x.Area == "someWidget")
      .SelectMany(x => x.RecommendedItems);

Without using the TrackingAttribute

In the current state of the code, the Send method of the TrackingService returns raw recommendation data from Episerver Perform, that is, it does not convert the data into Recommendation objects. The data is the same as in the TrackingAttribute case, but you need to parse the data yourself. Each RecommendationsResponseData object in the SmartRecs collection contains the same data as a Recommendation object in the TrackingAttribute case.

The following example uses ReferenceConverter, injected via constructor, to translate the reference codes into ContentRefereces. Note that the SmartRecs property can be null in this case - write your code accordingly.

var trackingData = _trackingDataFactory.CreateCategoryTrackingData(category, httpContext);
var result = _trackingService.Send(trackingData, httpContext);

var productRefs = 
   result.SmartRecs
      ?.Where(x => x.Position == Category)
      .SelectMany(x => x.Recs)
      .Select(x => _referenceConverter.GetContentLink(x.RefCode));

Extending TrackingRequestFactory

To support Brand and Attribute tracking via the TrackingAttribute, create your own version of TrackingRequestFactory and register it in the structure map container. For this to work, you must be able to calculate the correct brand/attribute value based on the current IContent instance. The following example overrides the TrackBrandPage method.

[ServiceConfiguration(ServiceType = typeof(TrackingRequestFactory), Lifecycle = ServiceInstanceScope.Singleton)]
public class CustomTrackingRequestFactory : TrackingRequestFactory
{
   protected override IEnumerable<Recommendation> TrackBrandPage(IContent content, HttpContextBase httpContext)
   {
      var brand = ((MyContentType) content).BrandProperty;
      var trackingData = _trackingDataFactory.CreateBrandTrackingData(brand, httpContext);
      var result = _trackingService.Send(trackingData, httpContext);
      //Return result converted to IEnumerable<Recommendation>.
   }
   ...
}

Comments