EXM: Token Replacement In Messages With A Contact Custom Field

Image

VersionsSitecore 8 Update 2

EXM 3 rev 150223

TaskAdd 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.".DetailsIn 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.