Tutorial: Send email based on field value using EXM, Forms, and Marketing Automation

I had some clients asking me how to send an e-mail based on a value selected in a field using the Sitecore Forms. Let us say, you have a field named “Topic” and if the visitor selects the option named “Gifts” he gets an email offering a free voucher for a Gift. If this same visitor selects the option “Books”, he gets a totally different email.

In this tutorial, I share how you can achieve this by using EXM, Forms, and Marketing Automation.

The first challenge I faced while working on it is that there is no link between a submitted form and a Xdb contact. If you look at the Sitecore Forms databases schema, you will notice that there is no field indicating which Xdb contact submitted that form.

Sitecore Forms (XP 9.3) database schema

So, how did I solve that?

First, I created a custom Xdb event model named Form Submission to populate the submitted form data. This way, I can link the contact with the submitted form.

Form Submission event in the Experience Profile

Next, I extended the forms.executeSubmit pipeline with a custom processor that registers the Form Submission event in every form submitted. It also stores the form fields and their respective values.

Xdb data for the FormSubmission event

Finally, a custom predicate (condition rule) was created to check if the existing contact’s events contains a Form Submission event with a specific field and value.

“Field in the form compares to value” predicate

This post is a detailed tutorial containing all the steps I did. If you are a seasoned Sitecore developer and has experience in using the Forms, EXM and Marketing Automation features, then feel free skip this tutorial and download the complete code and the Sitecore package in my Github repository.

Create a custom event model for the Form Submission

To understand events, we first need to talk about interactions.

An interaction describes any point at which a contact interfaces with a brand, either online or offline. Examples of interactions include:

  • Using an app
  • Browsing a website
  • A phone conversation

An event is anything significant that occurs within the context of an interaction, such searching for content and registering for a report.

  • An event needs to be associated with an interaction.
  • An interaction can have one or more events.
  • Interactions must have at least one event.
  • You track interactions and events by using the XConnect API.

See the illustration below for two interactions where in the first the visitor searches for a contact and in the second he registers for a report.

Event and Interaction

Events can be viewed in the Experience Profile.

Experience Profile displaying latest events

Besides an event, every interaction requires 4 attributes:

  • Contact: the visitor of your site, the person you spoke with, a user on your mobile app, etc.
  • Initiator: the participant sending the first message of an interaction. There are current three options available: Contact, Brand, Unknown. Examples:
    • When a visitor is browsing your site (Contact)
    • When you are sending e-mails to a contact (Brand)
    • When you are making phone calls to a contact (Brand)
    • When a contact is calling a customer service (Contact)
  • Channel: paths that contacts use to interact with your brand, such as webinars, e-mail campaigns, or a face-to-face conversation at a trade show. Channels can be either Online or Offline. In Sitecore, channels are stored in the Content Tree path /sitecore/system/Marketing Control Panel/Taxonomies/Channel. Sitecore comes with many out-of-the-box channels, but you can create your own.
  • User Agent: what the contact used to interact with your brand. Usually, it is the device user-agent and it must follow the format set out in the RFC. For example, the Nintendo Switch user agent is Mozilla/5.0 (Nintendo Switch; ShareApplet) AppleWebKit/601.6 (KHTML, like Gecko) NF/4.0.0.5.9 NintendoBrowser/5.1.0.13341. For offline interactions, or interactions that are initiated by the Brand, you can use as a User Agent, for example, “Experience Forms”, “Seminar Conference”, etc.

For more information about interactions such as duration, venues (for offline interactions) and campaigns, please refer to the official documentation Interactions.

Create the event definition item

Event definitions are items in Sitecore that give contextual meaning to an event in a reporting context. Marketers can use them to define properties such as the event name, description, classification, and engagement points.

When an event is triggered programmatically, the ID of an event definition needs to be passed into the constructor.

The following list contains the types of events that are available and their location in the Sitecore tree:

  • Goals: /sitecore/system/Marketing Control Panel/Goals
  • Outcomes: /sitecore/system/Marketing Control Panel/Outcomes
  • Generic events: /sitecore/system/Marketing Control Panel/Events
  • Page events: /sitecore/system/Settings/Analytics/Page Events

We are going to create a generic event called Form Submission.

  1. In the Content Tree, navigate to the path /sitecore/system/Marketing Control Panel/Events
  2. Right-click the Events folder > Insert > Event. Name it “Form Submission”.
  3. Enter the following values for the properties of the event you have just created
    • Name: Form Submission
    • Points: 20
    • Description: Indicates a form was submitted during a web session
    • IsLiveEvent: checked
  4. Deploy the event. In the Review tab, click the Deploy button in the Workflow section. This publishes the definition to the web database and deploys it to the Reference Data Service database.
Event definition for the form submission

The IsLiveEvent property is used by Marketing Automation to determine if an event should be processed immediately rather than on session end.

Note: Although you can create events in the code without needing to create an event definition in the Content Tree, it is very important to have an event definition item so that marketers can change some of its properties without having you to recompile and deploy code every time.

Create a custom event model

In Visual Studio, create a new project using the template ASP .NET Web Application (.NET Framework). Name it “Custom.Foundation.Xdb”, for example. Because I am running a Sitecore XP 9.3 instance, I selected the 4.8 version of the .NET Framework.

Because we are going to deploy the generated assembly to the XP and XConnect sites, as well as, the ProcessingEngine, AutomationEngine, and IndexWorker services, I strongly recommend you keeping in this project only the code related to the custom event model.

Next, install the following NuGet packages (without dependencies):

  • Sitecore.XConnect, 9.3.0
  • Sitecore.XConnect.Collection.Model, 9.3.0
  • Sitecore.XConnect.Core, 9.3.0

In my example, I am using the Sitecore XP 9.3 Nuget Package versions.

In a folder named Events, create a class named FormSubmission extending the base class Sitecore.XConnect.Event. Add the following code:

Code for the FormSubmission.cs class

The EventDefinitionId property must match to the ID of the Event Definition item we have created previously.

Next add a class named FormsModel in a folder named “Models”. Add the following code:

Figure 5: FormsModel.cs class

Create a configuration file under the folder App_Config/Include/Foundation. Name it Xdb.Models.config. Add the following text:

Xdb.Models.config configuration file

Deploy the Custom.Foundation.Xdb.dll assembly as well as the configuration file to your Sitecore XP instance.

Now, we need to create a new project to generate a JSON file that needs to be deployed to the XConnect and IndexWorker services.

In Visual Studio, create a new project using the template Console App (.NET Framework). Name it “Custom.Foundation.Xdb.Deploy”, for example. Because I am running a Sitecore XP 9.3 instance, I selected the 4.8 version of the .NET Framework.

Next, install the Sitecore.XConnect NuGet package with the lowest dependencies. At the end, you should have the following Nuget packages installed:

  • Microsoft.Extensions.DependencyInjection.Abstractions, 2.1.1
  • Newtonsoft.Json, 11.0.2
  • Remotion.Linq, 2.2.0
  • Sitecore.Framework.Conditions, 4.0.0
  • Sitecore.XConnect, 9.3.0
  • Sitecore.XConnect.Core, 9.3.0
  • Sitecore.XConnect.Diagnostics, 9.3.0
  • Sitecore.XConnect.Search, 9.3.0
  • System.Interactive.Async, 3.1.1
  • System.Interactive.Async.Providers, 3.1.1

In my example, I am using the Sitecore XP 9.3 Nuget Package versions.

Add reference to the Custom.Foundation.Xdb solution.

Finally, in the Program.cs class, add the following code:

Set the console app as the startup project (Right-click > set as Startup Project) and run it.

Console App generating .json file

Note: Before running the Console app make sure you have a Temp folder at the root of the C:\ drive.

Now, copy the file named FormsModel, 1.0.json to the following locations:

  • <XConnect Instance>\App_data\Models
  • <XConnect Instance>\App_data\jobs\continuous\IndexWorker\App_data\Models

Also, copy the assembly file Custom.Foundation.Xdb.dll to the following location:

  • <XConnect Instance>\App_data\jobs\continuous\AutomationEngine\
  • <XConnect Instance>\App_data\jobs\continuous\IndexWorker\
  • <XConnect Instance>\bin
  • <Sitecore XP Instance>\bin

Restart the MarketingAutomationService and IndexWorker Windows services.

That’s all we need to have our custom event for the form submission done and properly configured.

Now, let’s implement the Forms part.

Create a Pipeline processor to register the Form Submission Event

We want that every time a form is submitted, the event Form Submission is registered, and the fields and values of this form are stored in the XConnect database. This way we can have a link between the form and the contact that submitted it.

In Visual Studio, create a new project using the template ASP .NET Web Application (.NET Framework). Name it “Custom.Foundation.Forms”, for example. Because I am running a Sitecore XP 9.3 instance, I selected the 4.8 version of the .NET Framework.

Next, install the following NuGet packages (without dependencies):

  • Microsoft.Extensions.DependencyInjection, 2.1.1
  • Microsoft.Extensions.DependencyInjection.Abstractions  , 2.1.1
  • Sitecore.Analytics, 9.3.0
  • Sitecore.Analytics.Model, 9.3.0
  • Sitecore.Analytics.XConnect, 9.3.0
  • Sitecore.ExperienceForms, 9.3.0
  • Sitecore.ExperienceForms.Mvc, 9.3.0
  • Sitecore.Kernel, 9.3.0
  • Sitecore.Mvc, 9.3.0
  • Sitecore.XConnect, 9.3.0
  • Sitecore.XConnect.Client, 9.3.0
  • Sitecore.XConnect.Client.Configuration, 9.3.0
  • Sitecore.XConnect.Collection.Model, 9.3.0
  • Sitecore.XConnect.Core , 9.3.0

Add reference to the Custom.Foundation.Xdb solution.

Create an interface named IXdbContactService in a folder named Services. Add the following code:

IXdbContactService interface

In my example, I have abstracted all the XConnect API into a class named XdbContactService which extends the interface IXdbContactService. I will not go into details of its implementation, but you can find the complete code in my Github repository. Please, copy the implementation (or add your own) before you proceed with this tutorial.

Create a configuration file under the folder App_Config/Include/Foundation. Name it Forms.DI.config. Add the following text:

Forms.DI.config file

The configuration file above registers both the IXdbContactService and the XdbContactService for the Dependency Injection resolver. To learn more about the embedded Sitecore Dependency injection, please refer to the official documentation Dependecy Injection.

Next, add a class named RegisterInteraction in a folder named Pipelines/ExecuteSubmit. Extend the base class Sitecore.Mvc.Pipelines.MvcPipelineProcessor and add the following code:

RegisterInteraction class

The code above is quite straightforward. The only thing I want to comment is that I am storing the form fields and their values into the CustomValues property. This property is member of the base class Sitecore.XConnect.Event (which the FormSubmission class extends).

The reason why I am doing it, instead of having created a custom field, is because the Marketing Automation service always returns Events as the base class type Sitecore.XConnect.Event and never returns any derived class.

Create a configuration file under the folder App_Config/Include/Foundation. Name it Forms.Mvc.Pipelines.config. Add the following text:

Forms.Mvc.Pipelines.config file

Deploy the Custom.Foundation.Forms.dll assembly as well as the configuration file to your Sitecore XP instance.

Identify the Contact when Form is submitted

In order to be able to send e-mails to a contact through EXM and Marketing Automation we need it to be identified.

Contact identification is the process of connecting the current session, device, and contact session to an identifier. A contact is identified through the XConnect API. e.g. Sitecore.Analytics.Tracker.Current.Session.IdentifyAs("source", "someone@gmail.com");

To learn more about identifying a contact, please refer to the official documentation Identifying contacts.

The contact also needs to have a valid e-mail address registered (EmailAddressList facet).

As per the Sitecore XP 9.3 release, Sitecore Forms does not come with an out-of-the-box feature for identifying contacts. However, you can install the Sitecore Forms Extensions module developed by Bart Verdonck which comes with a identify contact submit action.

In my sample code, I have implemented a custom identify contact submit action that I copied from Bart’s module and adapted for my example. You can use it as well.

Identify Contract submit action

Create a sample form

Before going further, create a sample form with the following fields:

  • First name: Single-line text field
  • Topic: Dropdown list with static options “Gifts”, “Books”, “Magazines”
  • Email address: E-mail field

Also add a Submit Button with the following submit actions:

  • Save Data
  • Identify Contact: use the E-mail address field as the identifier field
  • Redirect to Page: any page
Sample form

Save and publish the form.

Note: You need to add this form to a page in order to be able to test it. Please refer to the official documentation Add a form to a webpage.

Create two EXM automated email campaigns

For this tutorial, I have create two automated email campaigns with slightly different messages. One contains the word “Gifts”, while the other contains “Books”.

EXM: Create e-mail campaign / list dialog

I won’t go into details about the creation of an email campaign, but you can follow through by referring to the official documentation Create an email campaign.

When creating the e-mails, make sure you select the option Service email campaign option. This will make an email message be sent to all recipients regardless of whether they are part of an opt-out or suppression list. This is useful, for example, when you want to send a subscription confirmation to contacts who sign up for a newsletter or to send a Forgot Password email message. See more at The service messages.

Service email campaign option

If you want to test e-mails locally, you can install a local SMTP server such as Papercut and smtp4dev. Also, please refer to the official documentation Use a Custom SMTP for email delivery for more information about configuring a local SMTP server.

For more information, I strongly recommend Pete Navarra’s series on Marketing Automation with EXM if you want to get started with EXM.

Create a custom predicate for the checking the field value in the submitted form

In Visual Studio, create a new project using the template ASP .NET Web Application (.NET Framework). Name it “Custom.Foundation.AutomationEngine”, for example. Because I am running a Sitecore XP 9.3 instance, I selected the 4.8 version of the .NET Framework.

Next, install the following NuGet packages (without dependencies):

  • Sitecore.Framework.Conditions, 4.0.0
  • Sitecore.Framework.Rules.Abstractions, 3.3.0
  • Sitecore.XConnect.Collection.Model”, 9.3.0
  • Sitecore.XConnect.Core, 9.3.0
  • Sitecore.XConnect.Segmentation.Predicates.Model, 9.3.0

Add reference to the Custom.Foundation.Xdb solution.

Next add a class named FieldValueCondition in a folder named Predicates/Forms. Add the following code:

FieldValueCondition class

Update (January 22, 2020): I mention above that the .Events property is always of the Sitecore.XConnect.Event type, but you can change it by configuring your Xdb Model in the following configuration file: \App_Data\jobs\continuous\AutomationEngine\App_Data\Config\sitecore\XConnect\sc.XConnect.Client.xml.

Deploy the assembly file Custom.Foundation.AutomationEngine.dll to the following location:

  • <XConnect Instance>\App_data\jobs\continuous\AutomationEngine\
  • <Sitecore XP Instance>\bin

In the folder <XConnect Instance>\App_Data\jobs\continuous\AutomationEngine\App_Data\Config\sitecore\Segmentation, create a file named sc.Custom.Forms.Predicates.xml. Add the following text:

sc.Custom.Forms.Predicates.xml file

Note: Sitecore Automation Engine expects configuration files to be prefixed by “sc.”. You can rename the file however you want as long as you keep the prefix “sc.”.

Restart the MarketingAutomationService.

Tip: If you want to debug the FieldValueCondition class, copy both the Custom.Foundation.AutomationEngine.dll and Custom.Foundation.AutomationEngine.pdb files to <XConnect Instance>\App_data\jobs\continuous\AutomationEngine\. Also, while running Visual Studio as administrator, attach to the Sitecore.MAEngine.exe process.

Create the condition descriptor item

  • In the Content Tree, navigate to the path /sitecore/system/Settings/Rules/Definitions/ElementGroups
  • Right-click the ElementGroups item > Insert > Group. Name it “Forms”.
ElementGroups Forms
  • Navigate to the path /sitecore/system/Settings/Rules/Definitions/Tags
  • Right-click the Tags item > Insert > Tag. Name it “Forms”.
Forms tag
  • Navigate to the path /sitecore/system/Settings/Rules/Definitions/Elements
  • Right-click the Elements item > Insert > Element Folder. Name it “Forms – Conditions”.
  • Right-click the Forms – Conditions item > Insert > Condition. Name it “Field in the form compares to value”.
  • Enter the following values for the properties of the condition you have just created
    • Text: where the [fieldId,Tree,root=/sitecore/Forms&selection=Field Type,specific] field in the form [Comparison,Tree,root=/sitecore/system/Settings/Rules/Definitions/XConnect - String Operators&resulttype=name,compares to]  [value,,,specific value]
    • Type: Custom.Foundation.AutomationEngine.Predicates.Forms.FieldValueCondition,Custom.Foundation.AutomationEngine
Field in the form compares to value condition
  • Navigate to the /sitecore/system/Settings/Rules/Definitions/Elements/Forms - Conditions/Tags/Default and update the property Tags with the following values: Forms and XConnect – Condition.
Updating the Tags of the Forms – Conditions item
  • Navigate to the /sitecore/system/Settings/Rules/XConnect - Conditions/Tags/Default and select the item Forms in the property Tags
Updating Tags of the XConnect – Conditions item

This last action is what actually makes our custom condition descriptor item visible in the Marketing Automation rule set editor.

“where the specific field in the form compares to specific value” conditional rule

Create a sample marketing automation plan

I have created the following marketing automation plan containing two possible routes. One is when the visitor submits a form with the “Gifts” topic selected. The other is when he selects the option “Books”.

Sample Marketing Automation Plan

For more information, please refer to the official documentation Create a marketing automation campaign.

And the end result should be you getting an e-mail after filling the form and selecting the “Books” topic.

Papercut local smtp server

Credits

Photo by Charles on Unsplash

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s