﻿![]()

#### 

#### About

Transactional emails are automated emails, that company sends to notify customer about any transaction happened.

Here there are few examples of transactional emails:

- account create
- order submit
- shipping notification
- password change

You can check out this [article](https://moosend.com/blog/transactional-emails/#how-to-send-transactional-campaigns), where Moosend explains how those emails can be sent.

#### How to send transactional emails via Moosend

1. Prepare the body of email
2. Enable and obtain SMTP credentials in Moosend: click [here](https://help.moosend.com/hc/en-us/articles/4405943965970-Enable-SMTP-to-send-transactional-emails) to learn, how to configure it
3. Send the email: see [this example](https://www.brimit.com/blog/sitecore-send-4-forms-integration#moosend-smtp) to send emails via Moosend SMTP from Sitecore

Sounds easy... The only question is how to prepare the email body? Where it can be managed? 

#### Templates for emails

Typically when it comes to transactional emails we have a **generic email template** with some placeholders in it (e.g. `{FirstName}` or `{address.City}`) and some dynamic **model** (which usually can be represented in JSON).

So during preprocess stage email placeholders are replaced with values from JSON model.

![Render Email Body Scheme](https://www.brimit.com/-/media/images/blog/sitecore-send-5-dynamic-transactional-emails/render-email-scheme.png)

How this can be done with **Moosend**?

#### Dynamic emails with custom model in Moosend

Moosend comes with lots of **predefined** email templates, but they are designed for static content management: you can edit Email Body in Sitecore Send with no option to use dynamic placeholders together with custom model by default.

Email template can be created and managed in the following areas of Moosend:

1. Regular **email campaign**. It's a great tool to work on your email campaigns, the only downside - you can't manage the template as soon, as campaign is send. It's implemented to be used as *one-time* campaign, which is not very useful for transactional emails - you lose ability to manage campaign with first email sent.
2. **Automation plan** campaigns - if the action 'Then send email' is added, then the new email campaign is created internally. That's a good way to use & manage it during any time, but not the best from 'role' perspective: automation plan was not fully designed for it. But it's still the **best currently available option**.

##### Campaigns API

[Campaigns API documentation](https://doc.sitecore.com/send/en/developers/api-documentation/index-en.html#UUID-693ec33b-457e-419c-b2b2-008f5145a72c)

To get all campaigns the following request can be used:

```
GET /v3/campaigns.json?apikey={ApiKey}
Host: api.sitecoresend.io
```

Example response:

```
{
    "Code": 0,
    "Error": null,
    "Context": {
        "Paging": {
            "PageSize": 10,
            "CurrentPage": 1,
            "TotalResults": 32,
            "TotalPageCount": 4,
            "SortExpression": null,
            "SortIsAscending": true
        },
        "Campaigns": [
            {
                "ID": "{CampaignId}",
                "Name": "Automation Campaign (02-02-2023 18:16:31) (Automation)",
                "Subject": "Your Order Confirmation #{{Order.Id}}",
                "SiteName": null,
                "ConfirmationTo": null,
                "CreatedOn": "/Date(1675358214843+0000)/",
                "ABHoursToTest": null,
                "ABCampaignType": null,
                "ABWinner": null,
                "ABWinnerSelectionType": null,
                "Status": 3,
                "DeliveredOn": "/Date(1675361225907+0000)/",
                "ScheduledFor": null,
                "ScheduledForTimezone": null,
                "MailingLists": [],
                "TotalSent": 2,
                "TotalOpens": 3,
                "UniqueOpens": 1,
                "TotalBounces": 0,
                "TotalForwards": 0,
                "UniqueForwards": 0,
                "TotalLinkClicks": 0,
                "UniqueLinkClicks": 0,
                "RecipientsCount": 2,
                "IsTransactional": false,
                "TotalComplaints": 0,
                "TotalUnsubscribes": 0,
                "CampaignSource": null
            },
            ...
        ]
    }
}
```

*Note*. To obtain Api Key use this [guide](https://doc.sitecore.com/send/en/developers/api-documentation/index-en.html#UUID-074d0224-5e6f-25b4-a58e-bb381ea1f42f).

To get information about any specific campaign by id the following API endpoint should be used:

```
GET /v3/campaigns/{CampaignId}/view.json?apikey={ApiKey}
Host: api.sitecoresend.io
```

Response:

```
{
    "Code": 0,
    "Error": null,
    "Context": {
        "ID": "{CampaignId}",
        "Name": "Automation Campaign (02-02-2023 18:16:31) (Automation)",
        "Subject": "Your Order Confirmation #{{Order.Id}}",
        "WebLocation": null,
        "HTMLContent": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\"><head> ...",
        "PlainContent": " Order #{{Order.Id}}Dear {{Order.FromUser.FirstName}} {{Order.FromUser.LastName}}, thanks for the order! ...",
        "Sender": {
            ...
        },
        "DeliveredOn": "/Date(1675361225907+0000)/",
        "ReplyToEmail": {
            ...
        },
        "CreatedOn": "/Date(1675358214843+0000)/",
        "UpdatedOn": "/Date(1675358366913+0000)/",
        "ScheduledFor": null,
        "Timezone": null,
        "FormatType": 0,
        "ABCampaignData": null,
        "MailingLists": [],
        "ConfirmationTo": null,
        "Status": 3,
        "IsTransactional": false
    }
}
```

#### Campaign Template with Placeholders in Sitecore Send

So in Sitecore Send we can configure the template for the campaign like this:

![Template with Placeholders in Sitecore Send](https://www.brimit.com/-/media/images/blog/sitecore-send-5-dynamic-transactional-emails/tempalte-campaign-in-moosend.png)

You can download this template [here](https://gist.github.com/izharikov/285db920d6bd74a7a6f68da5413926d3#file-template-json).

*Tip*. You can create custom blocks for reuse in other templates. See [documentation](https://help.moosend.com/hc/en-us/articles/5883583209106-Save-a-custom-item-for-reuse-in-the-Campaign-Editor).

#### Mustache + Campaign = Dynamic Transactional Email

As via API we can obtain `HTMLContent` of the campaign, we can use it as a **template** for our final email, which will be sent via Sitecore Sent SMTP.

In my example I use [Mustache](https://mustache.github.io) ***logic-less templates***. To integrate it with .NET I used [Nustache](https://github.com/jdiamond/Nustache), but any other library, e.g. [Stubble](https://github.com/StubbleOrg/Stubble) can be used as well.

How it all works together:

![Transaction email scheme with Moosend](https://www.brimit.com/-/media/images/blog/sitecore-send-5-dynamic-transactional-emails/transaction-email-final-scheme.png)

And via .NET Core:

```
https://www.brimit.com// from Moosend.Wrappers.CSharpWrapper
private readonly ICampaignsApi _campaignsApi;
https://www.brimit.com// service to send email via SMTP
private readonly IEmailService _emailService;
https://www.brimit.com// read settings from appsettings.json
private readonly IOptions<MoosendOptions> _options;

[HttpPost]
public async Task<IActionResult> SendFromCampaign([FromBody] OrderModel request)
{
    var config = _options.Value;
    // get the campaign via API
    var campaign = await _campaignsApi.GettingCampaignDetailsAsync(
        "json",
        config.ApiKey,
        config.Campaigns.OrderConfirmation);
    // replace placeholders via Nustache for subject
    var subject = Render.StringToString(campaign.Context.Subject, request);
    // replace placeholders via Nustache for body
    var body = Render.StringToString(campaign.Context.HTMLContent, request);
    // send the email!
    await _emailService.Send(request.Order.FromUser.Email, subject, body, config.Campaigns.OrderConfirmation);
    return new ObjectResult(new
    {
        Success = true,
    });
}
```

Full sources are available on [Github](https://github.com/izharikov/sitecore-send-proxy/blob/master/SitecoreSendProxy/Controllers/MoosendOrderController.cs).

#### Tracking

To track campaign analytics in the custom campaign (not the default 'Transactional Email Campaign') the header `campaign_guid` needs to be added:

[`EmailService.cs`](https://github.com/izharikov/sitecore-send-proxy/blob/master/SitecoreSendProxy/Services/Smtp/EmailService.cs)

```
public async Task Send(string to, string subject, string html, string campaignId = null)
{
    var from = _configuration.GetValue<string>("Smtp:From");
    var message = new MailMessage(from, to, subject, html)
    {
        IsBodyHtml = true,
    };
    if (!string.IsNullOrEmpty(campaignId))
    {
        message.Headers.Add("campaign_guid", campaignId);   // <-- here is the trick
    }
    _logger.LogInformation("Send Email '{subject}' to {to} (from '{from}')", subject, to, from);
    using var smtp = CreateClient();
    await smtp.SendMailAsync(message);
}
```

Check the Reports dashboards in Moosend:

![Custom Moosend transactional campaign analytics](https://www.brimit.com/-/media/images/blog/sitecore-send-5-dynamic-transactional-emails/campaign_track.png)

All sources are available on my [Git Repo](https://github.com/izharikov/sitecore-send-proxy).

#### Sitecore Send Series

- [Abandoned Cart with Sitecore Send](https://www.brimit.com/blog/sitecore-send-1-abandoned-cart)
- [Sitecore Send Tracking HTTP API](https://www.brimit.com/blog/sitecore-send-2-http-api)
- [Sitecore Send REST API](https://www.brimit.com/blog/sitecore-send-3-rest-api)
- [Sitecore Send Integration with Sitecore Forms](https://www.brimit.com/blog/sitecore-send-4-forms-integration)
- [Sitecore Send - Dynamic Transactional Emails (with Mustache)](https://www.brimit.com/blog/sitecore-send-5-dynamic-transactional-emails)

###### Author

[!\[Igor Zharikov - Senior Sitecore Developer, Sitecore MVP\](https://www.brimit.com/-/jssmedia/feature/blogs/authors/igor-zharikov-2.jpg?h=700&amp;iar=0&amp;w=700&amp;hash=292A84E8CB3E5CE57CA743385CFB1464)
Igor Zharikov
Sitecore MVP / Senior Sitecore Developer](https://www.brimit.com/blog/author?authors=Igor%20Zharikov)

#### More on Sitecore

[!\[How Vercel Will Help You Save Effort When Deploying Sophisticated Sitecore Projects\](https://www.brimit.com/-/jssmedia/project/brimit/blog/2024/vercel_cover-image.png)
#Guides#How-toDXPE-commerce
##### How Vercel Will Help You Save Effort When Deploying Sophisticated Sitecore Projects
Optimize and accelerate the development and deployment of complex multisite Sitecore projects.
Alexei Vershalovich on July 17, 2024](https://www.brimit.com/blog/how-vercel-will-help-you-save-effort-when-deploying-sophisticated-sitecore-projects)

[!\[Training Up Tomorrow's Sitecore MVPs: a Mentoring Success Story\](https://www.brimit.com/-/jssmedia/project/brimit/blog/2023/sitecore-mentoring---cover-image.png)
#How-toDXP
##### Training Up Tomorrow's Sitecore MVPs: a Mentoring Success Story
How to participate in the Sitecore Mentor program and help younger colleagues jump-start a career in Sitecore development.
Sergey Baranov on October 2, 2023](https://www.brimit.com/blog/training-up-tomorrows-sitecore-mvps)

[!\[Going Headless. Part 2: When a Headless CMS Is Your Best Bet (if you have Sitecore)\](https://www.brimit.com/-/jssmedia/project/brimit/blog/2022/headless/adobestock_456986731.jpg)
#How-toDXPE-commerce
##### Going Headless. Part 2: When a Headless CMS Is Your Best Bet (if you have Sitecore)
Discover how a headless CMS can benefit organizations that use Sitecore.
Daniil Raschupkin, Palina Trokhautsava on September 15, 2022](https://www.brimit.com/blog/going-headless-part-2-when-a-headless-cms-is-your-best-bet-if-you-have-sitecore)

![](https://bat.bing.net/action/0?ti=187017043&amp;tm=gtm002&amp;Ver=2&amp;mid=07147443-8249-4a01-b9d4-626d1a214aed&amp;bo=2&amp;gtm_tag_source=1&amp;pi=0&amp;lg=en-US&amp;sw=800&amp;sh=600&amp;sc=24&amp;nwd=1&amp;tl=Sitecore%20Send%20-%20Dynamic%20Transactional%20Emails%20(with%20Mustache)&amp;kw=sitecore%20send,moosend,transactional%20emails,mustache,template,json,model&amp;p=https%3A%2F%2Fwww.brimit.com%2Fblog%2Fsitecore-send-5-dynamic-transactional-emails&amp;r=&amp;lt=293&amp;evt=pageLoad&amp;sv=2&amp;asc=D&amp;cdb=AQAY&amp;rn=74368)