In latest versions of Sitecore there are two new features available for public audience. Sitecore Forms and integrated EXM.
Typical usecase for use of these two features will involve newsletter subscribing offered by Newsletter Subscription Form and maintaining double opt-in process inside of EXM.
Unfortunately, there is no straightforward way how to manage double opt-in together with Sitecore Forms, and we will need to make some additional (development) steps.
What we will need to do?
To make everything working, we will need several steps. It involves:
- Configure EXM
- Configure double opt-in prerequisities
- Configure contact lists and mailing campaign
- Subscription
1. Configuration of EXM
If we still haven’t configured EXM, we need to process basic configuration values which enables sending emails from EXM.
1.1 SMTP configuration
As a first step, SMTP configuration must be checked prior any further steps.
EXM has SMTP configuration in file App_Config\Sitecore\EmailExperience\Sitecore.EDS.Providers.CustomSMTP.config. Default configuration provided by Sitecore expects locally running SMTP server on port 25.
1.2 EXM configuration
If you haven’t yet configured EXM, there is necessary to perform basic EXM intial setup.
Open Sitecore Launchpad, and click on Email Experience icon:
When EXM opens, select Default settings to configure default settings.
Configuration screen appears. Few fields should be filled:
Base URL – base URL used for links used in sent emails
From email – email which will be used in From header and appears as sender of email
From name – name which will be used as sender
Reply to – email which will be used if recipient of email replies on received email
If everything was processed, new item tree appears in Sitecore /sitecore/Content node:
2. Double Opt-In prerequisities
EXM installation has all required mail templates for double opt-in predefined (you can find these templates in /sitecore/content/Email/Messages/Service Messages/Self-Service Subscription). The most interesting messages are Subscription Notification and Subscription Confirmation.
Subscription Confirmation – this email template is used for confirmation of double opt-in process and is automatically sent to user when subscribing into newsletter. It also utilizes $link$ token, which is replaced by link “final page” if user clicks on confirmation link. The page which will be used can be configured in Final Confirmation Page field on item /sitecore/content/Email.
Subscription Notification – this email template is used for confirmation of subscription, and it is sent when user confirms subscription by clicking on link in confirmation email.
3. Contact list and mailing campaign
For successful mailing sent via EXM, we need to have Contact List, which will be used as a source of contacts to which emails will be send, and content of email
3.1 Contact list creation
Contact list are created with help of List Manager application in Sitecore.
To create a list, follow these instructions:
Open List Manager application
Create new list by clicking on Create button
Select Empty Contact List
Fill the name of list
And the list is created.
3.2 Mailing campaign creation
Mailing campaign is the “key” functionality offered by EXM. Typically it represents one email sent to set of recipients (represented by contact list).
As soon as campaign is sent, EXM will evaluate campaign statistics, and you cannot send this campaign again.
Why we are creating this campaign now? Because Subscription mechanism used for subscribing recipients works with campaigns, instead of contact list (you need to pass ID of campaign in subscribe function, and this function adds recipient into first contact list used by this Campaign).
To create campaign, follow these steps:
Open EXM application
Click on Create button to create new Mailing Campaign
Select Regular Email Campaign
Select Plain Text Type message
On General step, fill the name of Campaign
On Recipients tab select the list created in step 3.1
On Message step, prepare some content for Mailing (you can skip this step, as this Campaign will be used for recipients subscribing)
On Review step, you can send testing mail to mail entered into box
On Delivery step click on Save button in top right and save campaign.
Switch to Content editor and navigate on item /sitecore/content/Email/Message/year/Month/Day/Name_of_Campaign and write ID of item somewhere on paper. We will use this ID later, when we will develop subscribe submit action.
4. Maillist subscription
So, at this moment, we have configured and prepared EXM to maintain our double opt-in process.
But, we need channel to allow visitors to subscribe to receive data from us.
We have several ways how to do that. We can implement our own form with subscribing logic, or we can utilize Sitecore Forms and use it’s editor to develop form quick and easy and use own Submit form activity to subscribe user.
In this article, I will use Sitecore Forms, but the code used for subscribing we can use on any other variant of subscribing.
Before we will continue, we need to know that subscribing user into mailing requires Sitecore identified contact.
For email subscription, we will use following API call:
1 |
IClientApiService.Subscribe(SubscribeMessage subscribeMessage); |
where SubscribeMessage class is defined by following way:
1 2 3 4 5 6 |
class SubscribeMessage { public Guid MessageId { get; set; } public ContactIdentifier ContactIdentifier { get; set; } public bool RequireSubscriptionConfirmation { get; set; } } |
MessageId – guid of the mailing. User will be subscribed to first contact list attached to this mailing.
ContactIdentifier – identification of XConnect contact to be subscribed
RequireSubscriptionConfirmation – value indicating whether double opt-in will be used. Set to true to initialize double opt-in process for this subscription.
To identify user, we can use Identify contact submit action in article Sitecore Forms: How to identify Contact? .
I will assume that we already have some form created using Sitecore Forms from Sitecore Forms: How to identify Contact? article.
To subscribe, we need to use following Subscribe to newsletter submit action.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
using System; using System.Collections.Generic; using System.Linq; using Sitecore.DependencyInjection; using Sitecore.EmailCampaign.Cd.Services; using Sitecore.EmailCampaign.Model.Messaging; using Sitecore.ExperienceForms.Models; using Sitecore.ExperienceForms.Processing; using Sitecore.ExperienceForms.Processing.Actions; using Sitecore.XConnect; using Sitecore.XConnect.Client; using Sitecore.XConnect.Client.Configuration; using Sitecore.XConnect.Collection.Model; namespace Sitecore.Demo.SitecoreExtensions.Forms.Actions { /// <summary> /// Save action for identifying contact in Sitecore Forms. /// </summary> public class SubscribeToNewsletter : SubmitActionBase<string> { /// <summary> /// EXM client service. /// </summary> private readonly IClientApiService clientApiService; /// <summary> /// Initializes a new instance of the <see cref="SubscribeToNewsletter"/> class. /// </summary> /// <param name="submitActionData">The submit action data.</param> public SubscribeToNewsletter(ISubmitActionData submitActionData) : base(submitActionData) { this.clientApiService = ServiceLocator.ServiceProvider.GetService(typeof(IClientApiService)) as IClientApiService; } /// <inheritdoc /> protected override bool Execute(string data, FormSubmitContext formSubmitContext) { using (var client = this.CreateClient()) { try { var source = "sitedemo"; var email = GetFieldByName("Email", formSubmitContext.Fields); var id = GetValue(email); var trackerIdentifier = new IdentifiedContactReference(source, id); var expandOptions = new ContactExpandOptions(CollectionModel.FacetKeys.PersonalInformation, CollectionModel.FacetKeys.EmailAddressList); var contact = client.Get(trackerIdentifier, expandOptions); var subscriptionMessage = new SubscribeMessage() { ContactIdentifier = contact.Identifiers.FirstOrDefault(), RequireSubscriptionConfirmation = true, MessageId = new Guid("{61B088B4-2876-4C19-BBCE-CF58AA30A44F}") }; this.clientApiService.Subscribe(subscriptionMessage); Logger.Info("Contact submitting newsletter form was subscribed to newsletter."); return true; } catch (Exception ex) { Logger.LogError(ex.Message, ex + ex.StackTrace); return false; } } } /// <summary> /// Creates the client. /// </summary> /// <returns>The <see cref="IXdbContext"/> instance.</returns> protected virtual IXdbContext CreateClient() { return SitecoreXConnectClientConfiguration.GetClient(); } /// <summary> /// Parses object data send as parameter to action. /// </summary> /// <param name="value">Input value.</param> /// <param name="target">Target value.</param> /// <returns>A value indicating whether conversion was successfull.</returns> protected override bool TryParse(string value, out string target) { target = string.Empty; return true; } /// <summary> /// Gets the field by <paramref name="id" />. /// </summary> /// <param name="name">The field identifier.</param> /// <param name="fields">The fields.</param> /// <returns>The field with the specified <paramref name="id" />.</returns> private static IViewModel GetFieldByName(string name, IList<IViewModel> fields) { return fields.FirstOrDefault(f => f.Name == name); } /// <summary> /// Gets the <paramref name="field" /> value. /// </summary> /// <param name="field">The field.</param> /// <returns>The field value.</returns> private static string GetValue(object field) { return field?.GetType().GetProperty("Value")?.GetValue(field, null)?.ToString() ?? string.Empty; } } } |
How to customize
On line 43 you should adjust identification source to any string you are using to identify contacts. If you are using this submit action together with Contact Identification Submit Action, this value should be the same with value on line 41 in those submit action.
On line 50, instead of guid provided me there is necessary to provide guid representing campaign you created in chapter 3.
When developed and compiled, register this submit action in Sitecore Forms (steps to register are also noted in referenced article) and attach this action to form AFTER contact identification submit action.
2 thoughts on “How to configure double opt-in in EXM and Sitecore 9.0.1 using Sitecore Forms”