Skip to main content

Sitecore 9 - Creating Custom Segmentation Rule

Predicates are important to create rules for marketing automation and segmented lists. Before going through the details, I am going to remind what I am implementing again.

Imagine that you have a website displaying movies. Visitors are able to see movie details and take some actions like save movie or share it. 

You want to follow the visitors' activities and you want to take some marketing actions based on those activities. For example, if a contact visits a movie more than X time or she/he saves a movie, you want to send those movies to an external system. In addition, there is going to be a limit to send same movie. Such as, it will not be possible to send same movie more than 2 times. 

According to my scenario, I need a rule to filter contacts who visits a movie more than X time. Maybe, we can add one more condition there like in Y days. To creating rule will give flexibility to marketing managers that then they can easily add or remove multiple rules and proceed their needs.

When we read Sitecore official predicate documentation, we see that we need to implement two interfaces to create custom rules. These are ICondition and IContactSearchQueryFactory.

ICondition interface includes Evaluate method which is used for marketing automation rules. IContactSearchQueryFactory includes CreateContactSearchQuery method that is used for segmentation rules.

Before going to code details, I am going to create a rule in Sitecore.


Then, we need to configure our rule. It is important that your config file must start with "sc". I created my config file sc.MovieDetailVisitedCustom.xml under "xconnect root\App_data\jobs\continuous\AutomationEngine\App_Data\Config\sitecore\Segmentation".


<Settings>
    <Sitecore>
        <XConnect>
        <Services>
            <DescriptorLocator>
            <Options>
                <PredicateDescriptors>
                    <MovieDetailVisitMatches>
                        <id>{289BED04-0B96-4B58-B8B1-95FB25FD743A}</id>
                        <type>Playground.Rules.Segmentation.MovieDetailVisitMatches, Playground</type>
                    </MovieDetailVisitMatches>      
                </PredicateDescriptors>
            </Options>
            </DescriptorLocator>
        </Services>
        </XConnect>
    </Sitecore>
</Settings>

Let's write the rule now.

public class MovieDetailVisitMatches : ICondition, IContactSearchQueryFactory
{
    public NumericOperationType Comparison => NumericOperationType.IsGreaterThanOrEqualTo;

    public int VisitCount { get; set; }

    public int InDays { get; set; }

    public bool Evaluate(IRuleExecutionContext context)
    {
        var contact = context.Fact<Contact>();

        var events = new List<MovieDetailEvent>();

        foreach (var contactInteraction in contact.Interactions)
        {
            var movieDetailEvents = contactInteraction.Events.OfType<MovieDetailEvent>().Where(x => x.DefinitionId == MovieDetailEvent.EventId).ToList();

            if (!movieDetailEvents.Any()) continue;

            events.AddRange(movieDetailEvents);
        }

        return events.Where(x => x.Timestamp.AddDays(InDays) >= DateTime.UtcNow).GroupBy(x => x.MovieId).Any(x => x.Count() >= VisitCount);
    }

    public Expression<Func<Contact, bool>> CreateContactSearchQuery(IContactSearchQueryContext context)
    {

        return contact => contact.GetFacet<MovieDetailCalculatedFacet>().AnyXVisitInYDays;
    }
}

You see same logic but two different implementation of rules. In evaluate method, I am able to filter interactions and apply my logic as I want. However, I use my calculated facet in CreateContactSearchQuery for the segmentation rule.

Why? Can't I use the same logic which used in Evaluate method? Unfortunately no. It is not allowed to use complex queries inside segmentation rule. We cannot use linq methods like where, any, count etc. In addition, you will see in Sitecore documentation that there is no access "contact.Interactions" in that scope. Instead, you need to write your code against "contact.InteractionCache()" which limits you.

That's why my calculated facet helped me out.

How to test your code?

You can debug easily your segmentation rule with attaching w3wp.exe process of your website as usually you do.

Since everything is ready, we configured and wrote our rule, we can see it inside List Manager, segmentation section.


Keep in mind that, if you are debugging at this moment, once you click "OK" button, your code should be hit.

However debugging Evaluate method is a bit different than CreateContactSearchQuery. Because as I mentioned, it is called by marketing automation service.

Let's see how to do this on next post: Debugging marketing automation rules

Comments

  1. Thanks for sharing this great informaton. Would also like to share one of Best customer segmentation tool i have come across. Propellor is best customer segmentation tool.

    ReplyDelete

Post a Comment

Popular posts from this blog

Sitecore 9 - Custom Page Events & Filtering with XConnect

This is the first article of a series. I am going to start with creating a custom page event and will show how we can fetch event data using xconnect api. Let's start with reminding demo scenario: Imagine that you have a website displaying movies. Visitors are able to see movie details and take some actions like save movie or share it.  You want to follow the visitors' activities and you want to take some marketing actions based on those activities. For example, if a contact visits a movie more than X time or she/he saves a movie, you want to send those movies to an external system. In addition, there is going to be a limit to send same movie. Such as, it will not be possible to send same movie more than 2 times.  You want to configure this as a marketing automation plan to give flexibility to your marketing managers. They should be able to add configurable rules and activities.  My first focus is movie detail page. I want to track visitors when they visit the

Sitecore Commerce – XC9 Tips – Missing Commerce Components in SXA Toolbox on Experience Editor

I've recently had an issue that commerce components were missing in SXA Toolbox. I setup Sitecore Commerce on top of an existing instance and I already had a SXA website working on it. The idea was to add commerce components and functionality to my existing website. But after commerce setup, the toolbox was still showing default SXA components and commerce components were missing although I add commerce tenant and website modules: I checked Available Renderings under Presentation folder, there was no problem, commerce renderings were there. I created another tenant and website to see if it shows the commerce components in toolbox. Nothing seemed different but I was seeing commerce components for new website and it was missing on existing one. Then, I noticed two things: 1- Selected catalog was empty in content editor (/sitecore/Commerce/Catalog Management/Catalogs) even if I see Habitat_Master catalog in Merchandising section on commerce management panel. 2- Bootstrap

Sitecore Commerce – XC9 Tips – Configuring Postman

In this post, I am going to show how to setup postman and run the scripts. When you download Sitecore Commerce, it includes ready to use postman sample requests (inside Sitecore.Commerce.Engine.SDK.x.x.x folder). You need to import that postman folder to postman app. The steps are written in official documentation , just click import and choose postman folder. You will see some parameters in sample requests such as  {{SitecoreIdServerHost}}, {{OpsApiHost}}, {{OpsApi}} Those are environment based variables that you can change according to your environment details. When you click "setting" icon, you will see predefined environments: AdventureWorks and Habitat. For example, click "Habitat Environment" to edit its variables. You see that AuthoingHost is using port 5000, it is the default port if the that port is available. You can check which port is using your Authoring role from IIS. If your Authoring port is different than 5000, you ne