![Sitecore Send + OrderCloud: welcome email](https://www.brimit.com/-/jssmedia/images/blog/sitecore-send-order-cloud-welcome-email/logo-transparent.png?h=820&iar=0&w=1362&hash=6E4A8E6AA58957F67F4C397F391D8592)
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:
Explanation:
- Webhook configuration on endpoint
PUT v1/me/register
- the endpoint, which is called to register a new user. See documentation for more details. - In the
Headstart
solution we can implement webhook handler. - Inside webhook we will map payload from request to a new subscriber request in Sitecore Send.
- 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 settingsBaseUrl
- set it tohttps://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:
Subscriber
In Sitecore Send subscribers will appear as on example:
Also the subscriber contains some 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:
- 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:
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.