EXM: Token Replacement In Messages With A Contact Custom Field

Versions

Sitecore 8 Update 2

EXM 3 rev 150223

Task

Add a custom token to replace with a custom field added to the contact record in an EXM Message when sending the email, such as the salutation like “Ms.”, “Mr.”, or “Mrs.”.

Details

In my one of my previous blogs, I described adding a custom facet with fields to a contact which included a Salutation field.  The Saluation field was added to the index as well.

http://hiblog.wpengine.com/2015/06/30/list-manager-segmented-list-from-custom-rules-using-custom-facet-fields/

Once we have a field that we would like to replace with a token, we can add the token to Sitecore:

In Sitecore, from the desktop, switch to the “core” database Add a new field to the Subscriber template

Template Id: {11D403EC-C755-471B-852D-AC2799EF0739}
SitecoreTokenInCore

Note: You may wish to create a new template with all the custom fields and inherit that template for easier upgrades

Confirm you can see the new token in the Insert Fields from EXM Message body editing:

TokenInEXMMessageRichText

Configuration

Modify /App_Config/Include/Sitecore.EmailCampaign.config as follows (or add a patch file)

In /sitecore/pipelines/getXdbContactRecipient, add a processor to assign the token to the value.

[sourcecode language=”text”]
<processor type="LaunchSitecore.Extensions.EXM.Pipelines.AssignSalutationProperty, LaunchSitecore">
<EXMContactFacetName ref="model/entities/contact/facets/facet[@name=’EXMContact’]/@name" />
</processor>
[/sourcecode]

The model referred to is what you previously added for your custom facet and fields.

The code for “AssignSalutationProperty.cs”

[sourcecode language=”text”]
using Sitecore.Analytics.Model.Entities;
using Sitecore.Analytics.Model.Framework;
using Sitecore.Diagnostics;
using Sitecore.Modules.EmailCampaign.Core.Pipelines.GetXdbContactRecipient;
using Sitecore.Modules.EmailCampaign.Recipients;

namespace LaunchSitecore.Extensions.EXM.Pipelines
{
public class AssignSalutationProperty
{
public void Process(GetXdbContactRecipientPipelineArgs args)
{
Assert.ArgumentNotNull(args, "args");
if (args.IsPropertyRequested<EXMPbsContactInfo>())
{
try
{
var facet = args.SourceContact.GetFacet<IEXMContact>(this.EXMContactFacetName);
if (facet != null)
{
EXMContactInfo info = new EXMContactInfo();
info.Salutation = facet.Salutation;
if (!string.IsNullOrEmpty(info.Salutation))
{
args.TargetRecipient.GetProperties<EXMContactInfo>().DefaultProperty = info;
}
}
}
catch (FacetNotAvailableException)
{
}
}
}

public string EXMContactFacetName { get; set; }
}

public class EXMContactInfo : Property
{
public string Salutation { get; set; }
// Other custom fields like ContactType, Age
}
}
[/sourcecode]

Replace the default “recipientPropertyTokenMap” in Sitecore.EmailCampaign.config or a patch file

[sourcecode language=”text”]
<!– Customization for EXM Custom Contact field tokens in Sitecore.EmailCampaign.CustomTokens.config–>
<!–<recipientPropertyTokenMap type="Sitecore.Modules.EmailCampaign.Core.Personalization.DefaultRecipientPropertyTokenMap, Sitecore.EmailCampaign" singleInstance="true" />–>
<recipientPropertyTokenMap type="LaunchSitecore.Extensions.EXM.Recipients.DefaultRecipientPropertyTokenMap, LaunchSitecore" singleInstance="true" />

[/sourcecode]

The code for DefaultRecipientPropertyTokenMap.cs:

[sourcecode language=”text”]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using Sitecore.Diagnostics;
using Sitecore.Modules.EmailCampaign.Core.Personalization;
using Sitecore.Modules.EmailCampaign.Recipients;
using LaunchSitecore.Extensions.EXM.Pipelines;

namespace LaunchSitecore.Extensions.EXM.Recipients
{
public class DefaultRecipientPropertyTokenMap : RecipientPropertyTokenMap
{
private static readonly Dictionary<Token, RecipientPropertyTokenBinding> TokenBindings;

static DefaultRecipientPropertyTokenMap()
{
RecipientPropertyTokenBinding[] bindingArray = new RecipientPropertyTokenBinding[] { RecipientPropertyTokenBinding.Build<PersonalInfo>(new Token("fullname"), personalInfo => personalInfo.FullName),
RecipientPropertyTokenBinding.Build<PersonalInfo>(new Token("name"), personalInfo => personalInfo.FirstName),
RecipientPropertyTokenBinding.Build<PersonalInfo>(new Token("firstname"), personalInfo => personalInfo.FirstName),
RecipientPropertyTokenBinding.Build<PersonalInfo>(new Token("lastname"), personalInfo => personalInfo.LastName),
RecipientPropertyTokenBinding.Build<Email>(new Token("email"), email => email.EmailAddress),
RecipientPropertyTokenBinding.Build<Phone>(new Token("phone"), phone => phone.PhoneNumber),
RecipientPropertyTokenBinding.Build<EXMContactInfo>(new Token("salutation"), salutation => salutation.Salutation)
};
TokenBindings = (from b in bindingArray
orderby b.Token.Key
select b).ToDictionary<RecipientPropertyTokenBinding, Token, RecipientPropertyTokenBinding>(b => b.Token, t => t);
}

public override RecipientPropertyTokenBinding GetTokenBinding(Token token)
{
RecipientPropertyTokenBinding binding;
Assert.ArgumentNotNull(token, "token");
TokenBindings.TryGetValue(token, out binding);
return binding;
}

public override IList<RecipientPropertyTokenBinding> GetTokenBindings()
{
return TokenBindings.Values.ToList<RecipientPropertyTokenBinding>();
}
}
}
[/sourcecode]

That’s all you have to do to replace the salutation token ($salutation$) in an email message with the value of the salutation field in the contact.