Skip to main content

Sitecore 9 - Creating Custom Marketing Automation Activity Part-1

We saw how to debug our marketing automation rule in previous post. Now, let's come back to our scenario first.

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. 

We have our rule, so we are able to filter contacts who visit a movie more than X time. The missing part is sending those movies to an external service. In addition, we need to keep somehow how many times a movie has been sent to service. To do this, I am going to create a custom activity which provides us to send movies and a custom facet which keeps the count we sent.

I am not going to show how to create custom facet, I've already showed it in the beginning post of this series. I created a facet called MoviesSentToExpressFacet that keeps a dictionary. The key is movie id and value is count. I am going to update this facet when the movies send in custom activity.

There are two parts to create a custom activity. The first part is to create back end code and the second is Angular part to build marketing automation user interface.

I created a class which implement IActivity interface.

public class SendMoviesToExpress : IActivity
    {
        public IActivityServices Services { get; set; }

        public ISendMoviesService SendMoviesService { get; set; }

        public int ProcessLimit { get; set; }

        public SendMoviesToExpress(ISendMoviesService sendMoviesService)
        {
            SendMoviesService = sendMoviesService;
        }

        public ActivityResult Invoke(IContactProcessingContext context)
        {
            Condition.Requires(context.Contact).IsNotNull();

            try
            {
                var moviesSentFacet = context.Contact.GetFacet<MoviesSentToExpressFacet>() ?? new MoviesSentToExpressFacet();

                var moviesNotToSend = moviesSentFacet.MoviesSent.Where(x => x.Value >= ProcessLimit).Select(x => x.Key).ToList();

                var movieDetailCalculatedFacet = context.Contact.GetFacet<MovieDetailCalculatedFacet>();

                if (movieDetailCalculatedFacet == null) return new SuccessMove();

                var moviesToSend = movieDetailCalculatedFacet.MovieVisits.Where(x => !moviesNotToSend.Contains(x.Key)).Select(x => x.Key).ToList();

                //Send Movies
                SendMoviesService.Process(context.Contact.Id.Value, moviesToSend);

                foreach (var movieId in moviesToSend)
                {
                    if (moviesSentFacet.MoviesSent.ContainsKey(movieId))
                    {
                        moviesSentFacet.MoviesSent[movieId]++;
                    }
                    else
                    {
                        moviesSentFacet.MoviesSent.Add(movieId, 1);
                    }
                }

                Services.Collection.SetFacet(context.Contact, MoviesSentToExpressFacet.DefaultFacetKey, moviesSentFacet);

                return new SuccessMove();
            }
            catch (Exception e)
            {
                //log do something
                return new SuccessMove();
            }
           

            return new SuccessMove();
        }      
    }

As you see in implementation, we have a parameter called ProcessLimit. It keeps how many times a movie can be sent. We have a custom service called SendMoviesService which is responsible sending movies.

We use custom facet to get info that how many time the movies have been already sent and if it is less than the limit we update the facet.

Let's add the activity in Sitecore panel and do configurations now. Here is the my custom activity, I created it under /sitecore/system/Settings/Analytics/Marketing Automation/Activity Types/ in Sitecore.


An important note that if you don't configure an icon, you get an error message in marketing automation page.


So, you have to configure an icon. Then add configurations. I registered activity class in sc.MarketingAutomation.ActivityTypes.xml file.


<MarketingAutomation.Activity.SendMoviesToExpress>
 <Type>Sitecore.Xdb.MarketingAutomation.Locator.ActivityTypeRegistration, Sitecore.Xdb.MarketingAutomation</Type>
 <LifeTime>Singleton</LifeTime>
 <Options>
  <Id>{C61C5489-B11B-40F1-AB36-23EB044C2E69}</Id>
  <ImplementationType>Playground.Activities.SendMoviesToExpress, Playground</ImplementationType>
 </Options>
</MarketingAutomation.Activity.SendMoviesToExpress>

Since we use a custom service, we need to configure it too. It is registered in sc.MarketingAutomation.ActivityServices.xml file.

<Playground.SendMoviesService>
 <Type>Playground.Services.Movie.SendMoviesService, Playground</Type>
 <As>Playground.Services.Movie.ISendMoviesService, Playground</As>
 <LifeTime>Transient</LifeTime>
</Playground.SendMoviesService>

And at last, we need to register the facets in sc.MarketingAutomation.ContactLoader.xml file. If you don't do this, you will get your facets as null in activity class.

<MarketingAutomation.Loading.ContactFacetsConfigurator>
  <Type>Sitecore.Xdb.MarketingAutomation.Loading.ContactFacetsConfigurator, Sitecore.Xdb.MarketingAutomation</Type>
  <As>Sitecore.Xdb.MarketingAutomation.Core.Loading.IContactExpandOptionsConfigurator, Sitecore.Xdb.MarketingAutomation.Core</As>
  <LifeTime>Singleton</LifeTime>
  <Options>
 <IncludeFacetNames>
   <Facet1>MovieDetailCalculatedFacet</Facet1>
   <Facet2>MoviesSentToExpressFacet</Facet2>
 </IncludeFacetNames>
 <ExcludeFacetNames />
  </Options>
</MarketingAutomation.Loading.ContactFacetsConfigurator>

Maybe you already noticed a line in activity class. The code to set facet.

Services.Collection.SetFacet(context.Contact, MoviesSentToExpressFacet.DefaultFacetKey, moviesSentFacet);

Sitecore provides preregistered services in activity class by implementing IActivity interface. Normally, how do you set a facet? If you read documentation, you can think that you need to use xconnect client api. But here, there is a limitation that you don't have access to xconnect. After I got error and some investigation, I noticed that Sitecore already provides a service to do this. It could be useful for you to have a look at preregistered services based on your needs.

And that's it! Everything is ready to work on back end part, now it is time to configure UI with Angular. 

Let's do that in part 2.

Comments

  1. This is such a great resource that you providing and you give it away for free. I love seeing websites that understand the value of providing a quality resource for free. It is the old what goes around comes around routine.marketing

    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

A React Example in Sitecore

That's true, Sitecore components are useful and provide lots of facilities. They allow to build fully flexible website. And there is not much problem using post-backs to display your contents. However, if your website has user interactions, then it could be a headache. Too many post-backs would occur a poor user experience. That's why client-side technologies are really powerful and popular for a long time. There are plenty of javascript libraries and frameworks which all try to provide better user experience in different ways. It is not a topic of this article why I chose React. There are some good articles about it (e.g. Jonne Kats' great article ). However, one of the reasons is React only focus on view part. It is not a fully framework like Angular, it is rich featured library instead. And that's what I was looking for! The idea was to benefit Sitecore server-side and React client-side power. It seems they are very good match! Let's dive into code... I&#

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 the