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

Deploying SolrCloud with Zookeeper on Azure Kubernetes Service (AKS)

SolrCloud on Azure Kubernetes Service (AKS) Running SolrCloud on Kubernetes — particularly Azure Kubernetes Service (AKS) — can provide you with a highly scalable, cost-efficient, and cloud-native architecture.  This guide walks through how I deployed SolrCloud 8.11.2 with Zookeeper on AKS . Why This Matters for Sitecore Deployments If you're running Sitecore XP or XM , you know that Solr is a mandatory dependency — powering xDB indexing, content search. While Sitecore provides a developer-friendly Solr container for local use, it clearly states: ⚠️ The included Solr image is intended only for development and testing . This means Sitecore does not provide a production-ready Solr setup. If you're deploying Sitecore in production — especially in Kubernetes — you need to create your own scalable, HA SolrCloud cluster. That’s why this deployment matters: You’re building a production-grade SolrCloud setup You’re deploying 3 Solr + 3 Zookeeper nodes for high availabilit...

Modern Observability for Sitecore 10.4 on AKS: Grafana, Alloy, Loki, and Prometheus

In this post, I’ll walk through how I extended the base Sitecore XM 10.4 AKS setup with a modern observability stack using Grafana, Alloy, Loki, and Prometheus. This setup provides deep insights into both infrastructure and application health, with powerful log aggregation and visualization. Project Overview Base:  Sitecore XM 10.4 running on Azure Kubernetes Service (AKS) Enhancements:  Added a full Grafana observability stack: Grafana  for dashboards and visualization Alloy  (Grafana Alloy, formerly Promtail) for log collection and multiline parsing Loki  for log aggregation and querying Prometheus  for metrics collection All configuration...

Post setup tips of Sitecore Commerce on Azure

Sitecore official documentation provides how to setup your instance on Azure. After you follow the instructions, you would need a few key steps to complete your setup. Use postman to bootstrap and initialize the Commerce Engine:   Call bootstrap method ( {{OpsApiHost}} / {{OpsApi}} /Bootstrap() ) for your environments. You would need to get token first ( {{SitecoreIdServerHost}} /connect/token ) Creating a new webshop: When you create a new webshop from Sitecore content editor, a new domain is created automatically on your content management server. But you will need to add manually to your CD and Identity servers. Update Domain.config file under app_config > security folder as below.   If you don’t add, you will get domain is missing error while customers sign in. You also need to register your domain to BizFX server.  Then, you will be able to see new domain while adding new customers in Sitecore Commerce panel. Configure produ...