Sitecore Send + OrderCloud : Welcome email setup

Igor Zharikov on November 29, 2023
Sitecore Send + OrderCloud: welcome email

About

Welcome emails are great example of transactional emails (check my article about different email campaigns in Sitecore Send). In this article I'll show how to configure Welcome email (with multi-language support) in OrderCloud Headstart solution using Sitecore Send.

Architecture

The architecture of the solution is shown on this diagram:

Sitecore Send + OrderCloud: welcome email architecture

Explanation:

  1. Webhook configuration on endpoint PUT v1/me/register - the endpoint, which is called to register a new user. See documentation for more details.
  2. In the Headstart solution we can implement webhook handler.
  3. Inside webhook we will map payload from request to a new subscriber request in Sitecore Send.
  4. Sitecore Send marketing automation will handle message send, as soon, as the subscriber appears in the list.

Webhook implementation

Controller
[Route("api/webhook")]
public class CustomerNotificationsController : CatalystController
{
    private readonly ICustomerNotificationsCommand customerNotificationsCommand;

    public CustomerNotificationsController(ICustomerNotificationsCommand customerNotificationsCommand)
    {
        this.customerNotificationsCommand = customerNotificationsCommand;
    }

    [HttpPost, Route("sendcustomerwelcomenotification")]
    [OrderCloudWebhookAuth]
    public async Task SendCustomerWelcomeNotification([FromBody] WebhookPayloads.Me.Register payload)
    {
        await customerNotificationsCommand.SendCustomerWelcomeNotification(payload?.Request?.Body);
    }
}
Command

In the command we map the data from payload to request body to add subscriber to the list.

public class CustomerNotificationsCommand : ICustomerNotificationsCommand
{
    private readonly IMailingListService _mailingListService;
    private readonly ILogger _logger;

    public CustomerNotificationsCommand(IMailingListService mailingListService,
        ILogger<CustomerNotificationsCommand> logger)
    {
        _mailingListService = mailingListService;
        _logger = logger;
    }

    public async Task SendCustomerWelcomeNotification(MeUser? meUser)
    {
        try
        {
            if (string.IsNullOrEmpty(meUser?.Email)
                || string.IsNullOrEmpty(meUser?.FirstName)
                || string.IsNullOrEmpty(meUser?.LastName))
            {
                _logger.LogWarning(
                    $"SendCustomerWelcomeNotification: Some of the request parameters is null or empty");
                return;
            }

            var customFields = BuildCustomFields(meUser);
            var tags = BuildTags(meUser);

            var listId = _mailingListService.DefaultListId;

            var succeed = await _mailingListService.AddToMailingList(listId,
                new AddingSubscribersRequest()
                {
                    Email = meUser.Email,
                    Name = $"{meUser.FirstName} {meUser.LastName}",
                    CustomFields = customFields,
                    Tags = tags,
                });
            _logger.LogInformation(
                $"SendCustomerWelcomeNotification: User {meUser.Username} ({meUser.Email}) subscribes to the list {listId}, succeess: {succeed}");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "SendCustomerWelcomeNotification: Error");
        }

        return;
    }


    private static IEnumerable<string> BuildCustomFields(MeUser user)
    {
        var list = new List<string>();

        AddKeyValueIfNotNull(list, Constants.CustomFields.BuyerGroupName, user.CompanyID);
        AddKeyValueIfNotNull(list, Constants.CustomFields.FirstName, user.FirstName);
        AddKeyValueIfNotNull(list, Constants.CustomFields.LastName, user.LastName);
        AddKeyValueIfNotNull(list, Constants.CustomFields.PhoneNumber, user.Phone);
        AddKeyValueIfNotNull(list, Constants.CustomFields.CountryCode, user.xp?.CountryCode);
        AddKeyValueIfNotNull(list, Constants.CustomFields.StorefrontClientID, user.xp?.StorefrontClientId);
        AddKeyValueIfNotNull(list, Constants.CustomFields.PreferredLanguage, user.xp?.Language);
        AddKeyValueIfNotNull(list, Constants.CustomFields.StorefrontName, user.xp?.StorefrontName);


        return list;
    }

    private static IEnumerable<string> BuildTags(MeUser? user)
    {
        var tags = new List<string>();

        if (user?.xp == null)
        {
            return tags;
        }

        const string separator = Constants.Separators.Tag;
        AddKeyValueIfNotNull(tags, Constants.Tags.Country, user.xp.CountryCode, separator);
        AddKeyValueIfNotNull(tags, Constants.Tags.Lang, user.xp.Language, separator);
        AddKeyValueIfNotNull(tags, Constants.Tags.Shop, user.xp.StorefrontName, separator);

        return tags;
    }

    private static void AddKeyValueIfNotNull(ICollection<string> list, string key, string value,
        string separator = Constants.Separators.Field)
    {
        if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(value))
        {
            list.Add($"{key}{separator}{value}");
        }
    }
}
MailingListService.cs implementation
public class MailingListService : IMailingListService
{
    private readonly IFlurlClientFactory _flurlFactory;
    private readonly SitecoreSendSettings _sitecoreSendSettings;
    private IFlurlClient ApiClient => _flurlFactory.Get($"{_sitecoreSendSettings.BaseUrl}/v3/");

    public MailingListService(SitecoreSendSettings sitecoreSendSettings, IFlurlClientFactory flurlFactory)
    {
        _sitecoreSendSettings = sitecoreSendSettings;
        _flurlFactory = flurlFactory;
    }

    public string DefaultListId => _sitecoreSendSettings.EmailListId;

    public async Task<bool> AddToMailingList(string emailListId, AddingSubscribersRequest request)
    {
        var url = AddSubscriberUrl(emailListId);
        var response = await ApiClient.Request(url)
            .PostJsonAsync(request)
            .ConfigureAwait(false);

        return response != null && response.ResponseMessage.IsSuccessStatusCode;
    }

    private string AddSubscriberUrl(string mailingList)
    {
        return
            $"subscribers/{mailingList}/subscribe.{_sitecoreSendSettings.Format}?apikey={_sitecoreSendSettings.ApiKey}";
    }
}
Settings
public class SitecoreSendSettings
{
    public string Format { get; set; } = "json";
    public string ApiKey { get; set; }
    public string BaseUrl { get; set; }
    public string EmailListId { get; set; }   
}
  • ApiKey - get it from Sitecore Send account settings
  • BaseUrl - set it to https://api.sitecoresend.io
  • EmailListId - email list, where your users will be added

Settings can be included in Headstart solution in Azure App Configuration.

Constants
public static class Constants
{
    public static class CustomFields
    {
        public const string BuyerGroupName = "BuyerGroup Name";
        public const string FirstName = "First Name";
        public const string LastName = "Last Name";
        public const string PhoneNumber = "Phone Number";
        public const string CountryCode = "Country Code";
        public const string StorefrontClientID = "Storefront Client ID";
        public const string PreferredLanguage = "Preferred Language";
        public const string StorefrontName = "Storefront Name";
    }

    public static class Tags
    {
        public const string Country = "country";
        public const string Lang = "lang";
        public const string Shop = "shop";
    }

    public static class Separators
    {
        public const string Field = "=";
        public const string Tag = ":";
    }
}

Sitecore Send

Mailing list

In the mailing list need to setup all custom fields we are populating from Headstart solution:

email list with custom fields

Subscriber

In Sitecore Send subscribers will appear as on example:

example subscriber

Also the subscriber contains some tags:

subscriber tags

In red I highlighted the tags, which were added by our webhook, in blue - tags, which are set by AI in Sitecore Send via Audience Discovery.

Welcome Email Automation

The 'Welcome email' automation in Sitecore Send looks like this:

marketing automation scheme

  • Automation triggers when the subscriber is added to the mailing list.
  • After that we can add some conditions to send different emails for different target groups (e.g. based on language - for multilanguage support).
Email template

Email template is configured using default Sitecore Send email editor. Inside it we use personalization tags to show personalized content for each user:

email template with personalization tags

In the template the following tags are used (highlighted in blue):

  • #recipient:name#
  • #recipient:email#

Reminder. You can use any custom field in the email template in the format #recipient:[CUSTOM FIELD NAME]#.

Conclusion

With Sitecore DXP products (like Send and OrderCloud) you can setup a distributed solution, which fully satisfy all commerce requirements. Stay tuned for more examples of configuring various transactional emails in Sitecore DXP solutions.