Create a custom personalization token

Last updated Tuesday, April 18, 2017 in Email Experience Manager for Developer

The Email Experience Manager (EXM), you can use tokens to personalize your email campaign messages. For example, in the beginning of a message, you can use the token $name$ in the greeting so that when you send your email campaign, the token is replaced with the name in the contact.

If you want to use tokens that are not available by default, you can create a custom token that you can use for your email campaigns.

To create a custom token, you must:

Create a custom contact facet

In the Sitecore Experience Database, you can extend the contact with your own custom data by creating a new custom contact facet.

To create a custom contact facet:

  • Create the custom contact facet, for example, the Salutation facet, with the Title property that you want your custom personalization token to be replaced with.

Create a property for the custom facet

You must create a property class to represent your custom facet. You use this property in the new processor that you create in the next section.

For example, to create a Salutation property:

namespace Sitecore.Support.Modules.EmailCampaign.Recipients
{
    using Sitecore.Modules.EmailCampaign.Recipients;
    public class Salutation : Property
    {
        public string Title { get; set; }        
    }
}

Add a new processor

In the <getXdbContactRecipient> pipeline, add a new processor to assign a value to the new property. For example, for the Salutation property, the value is pulled from the Salutation facet.

To add a new processor:

  1. Add the following configuration file in the /Include folder:
    <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
    <sitecore>
        <pipelines>
          <getXdbContactRecipient>
            <processor type="Sitecore.Support.Modules.EmailCampaign.Core.Pipelines.GetXdbContactRecipient.AssignSalutationProperty, Sitecore.Support">
              <SalutationFacetName ref="model/entities/contact/facets/facet[@name='Salutation']/@name" />
            </processor>
          </getXdbContactRecipient>      
        </pipelines>
    </sitecore>
    </configuration>
  2. Compile the following to a custom DLL:
    namespace Sitecore.Support.Modules.EmailCampaign.Core.Pipelines.GetXdbContactRecipient
    {
        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;
        using Sitecore.Support.Modules.EmailCampaign.Recipients;
        using Support.Testing.ContactFacets.Model;    
        public class AssignSalutationProperty
        {
            public void Process(GetXdbContactRecipientPipelineArgs args)
            {
                Assert.ArgumentNotNull(args, "args");
                if (args.IsPropertyRequested<Salutation>())
                {
                    try
                    {
                        var facet = args.SourceContact.GetFacet<ISalutation>(this.SalutationFacetName);                    
                        if (facet != null)
                        {
                            Salutation info = new Salutation();
                            info.Title = facet.Title;
                            if (!string.IsNullOrEmpty(info.Title))
                            {
                                args.TargetRecipient.GetProperties<Salutation>().DefaultProperty = info;
                            }                        
                        }
                    }
                    catch (FacetNotAvailableException)
                    {
                    }
                }
            }
            public string SalutationFacetName { get; set; }
        }
    }

Override the default token map

Override the default implementation of the recipientPropertyTokenMap token map class that describes the bindings between tokens and properties of a contact.

To override the recipientPropertyTokenMap token map class and bind the Title token to the Salutation property:

  1. Add the following configuration file in the /Include folder:
    <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
      <sitecore>    
        <recipients>
          <recipientPropertyTokenMap type="Sitecore.Modules.EmailCampaign.Core.Personalization.DefaultRecipientPropertyTokenMap, Sitecore.EmailCampaign" singleInstance="true">
            <patch:attribute name="type" value="Sitecore.Support.Modules.EmailCampaign.Core.Personalization.DefaultRecipientPropertyTokenMap, Sitecore.Support" />
          </recipientPropertyTokenMap>
        </recipients>
      </sitecore>
    </configuration>
  2. Compile the following code to a custom DLL:
    namespace Sitecore.Support.Modules.EmailCampaign.Core.Personalization
    {
        using Sitecore.Diagnostics;
        using Sitecore.Modules.EmailCampaign.Core.Personalization;
        using Sitecore.Modules.EmailCampaign.Recipients;
        using Sitecore.Support.Modules.EmailCampaign.Recipients;
        using System;
        using System.Collections.Generic;
        using System.Linq;
        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<Salutation>(new Token("title"), salutation => salutation.Title)
                };
                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>();
            }
        }
    }

Now, you can use the $title$ token in email messages and it will be replaced with the value that is stored for the relevant contact in the Analytics database.

Note

If you want to import the new custom facet from a file, you can extend the Import contacts wizard to include the custom contact facet as a new mapping field.