I would like to execute an a rule (condition and action) when a user clicks a link in an EXM email. The ability to trigger a goal would also be acceptable. This seems like a simple request, but nothing I try seems to work.

Each message gets an engagement plan, but EXM puts users directly into the Clicked Through state via the API so I don't think you can immediately execute actions as it enters that state. Each message also gets a campaign, but it does not appear that you can execute a rule or register a goal when that campaign is triggered. You can assign a user to an engagement plan state when a campaign is triggered, but this has the same problem as the engagement plan above.

Am I missing something? I am using Sitecore 8.1 update 3.


To clarify, I am looking for a solution that does not require custom code. It seems to me that this should be standard functionality.

1 Answer 1


I think the part you might be missing is that actual action of clicking a link in an EXM sent email message is that the link goes to a page that sits outside of the Sitecore item structure. That page is \sitecore\RedirectUrl.aspx. Because that's the case, there isn't an item in Sitecore that allows you to tap into that action through the Sitecore UI, instead, EXM runs the pipeline <redirectUrl> which triggers the campaign and sets the Engagement Plan state to Clicked Through Message.

You can register conditions and actions after the fact by modifying the EXM Engagement Automation plan, as shown in Part #1 below.

However, if you are looking to register conditions and actions before or in tandem with the Clicked Through Message state, then I think creating a custom processor will most likely be required, as show in Part #2 below.

Hope this helps!

1. Using Sitecore Engagement Automation

Every time a new EXM Message is created, a Campaign and Engagement Plan are created specific to the message that is being created.

Specifically, the Engagement Plan is copied from the Standard Message Plan that is located in /sitecore/system/Marketing Control Panel/Engagement Plans/Email Campaign/Standard/Message Plan

enter image description here

There is a state in this engagement plan called Clicked Through Message that contains a couple of out of the box conditions:

  • Valuable Visit
  • Visited One Page
  • Visit Had No Value
  • In Not Email Click Handler Session

Out of the box, there are no actions assigned to these conditions. However, if you have custom actions that you want to fire, you can adjust this standard Message Plan to add in your own Conditions and associated Actions following the Clicked Through Message state.

2. Programmatically - Creating a Pipeline Processor

If you are running a distributed environment (meaning you have Content Delivery servers in play, among other possible servers) you will want to make sure that the Sitecore.EmailExperience.ContentDelivery.config is enabled on the Content Delivery role.

Inside this config, you will find the <redirectUrl> pipeline.

     This pipeline is executed when Email Experience Manager receives a request to redirect
     a page request from an email link to the correct destination page.
    <!-- Retrieves the message item associated with the redirect event. -->
    <processor type="Sitecore.EmailCampaign.Cd.Pipelines.RedirectUrl.GetMessage, Sitecore.EmailCampaign.Cd"/>
    <!-- Determines whether the link provided in the request is a reference to a page on the local web site. -->
    <processor type="Sitecore.EmailCampaign.Cd.Pipelines.RedirectUrl.CheckInternalLink, Sitecore.EmailCampaign.Cd" />
    <!-- Constructs the URL to redirect the request to. -->
    <processor type="Sitecore.EmailCampaign.Cd.Pipelines.RedirectUrl.SetRedirectToUrl, Sitecore.EmailCampaign.Cd">
      <param desc="queryStringEncryption" ref="queryStringEncryption" />
      <internalCarryoverFields hint="list:AddInternalCarryoverField">
        <carryoverField type="Sitecore.EmailCampaign.Cd.Pipelines.RedirectUrl.CarryoverField, Sitecore.EmailCampaign.Cd">
          <param desc="fieldKey" ref="settings/setting[@name='QueryStringKey.MessageId']/@value" />
          <param desc="urlPattern">.*Unsubscribe.aspx|UnsubscribeFromAll.aspx.*|.*sc_pd_view=1.*</param>
        <carryoverField type="Sitecore.EmailCampaign.Cd.Pipelines.RedirectUrl.CarryoverField, Sitecore.EmailCampaign.Cd">
          <param desc="fieldKey" ref="settings/setting[@name='QueryStringKey.AnalyticsContactId']/@value" />
          <param desc="urlPattern">.*Unsubscribe.aspx|UnsubscribeFromAll.aspx.*|.*sc_pd_view=1.*</param>
        <carryoverField type="Sitecore.EmailCampaign.Cd.Pipelines.RedirectUrl.CarryoverField, Sitecore.EmailCampaign.Cd">
          <param desc="fieldKey" ref="settings/setting[@name='QueryStringKey.Campaign']/@value" />
          <param desc="urlPattern">.*Unsubscribe.aspx|UnsubscribeFromAll.aspx.*|.*sc_pd_view=1.*</param>
    <!-- Registers the link click event in emailEventStorage and attaches the result to the pipeline argument. -->
    <processor type="Sitecore.EmailCampaign.Cd.Pipelines.RedirectUrl.RegisterMessageEvent, Sitecore.EmailCampaign.Cd">
      <param desc="eventStorage" ref="emailEventStorage" />
      <param desc="duplicateProtectionIntervalSecs" ref="settings/setting[@name='EXM.DuplicateProtectionInterval']/@value" />
      <param desc="logger" ref="exmLogger" />
    <!-- Registers custom page events. Internal page references matching the IgnoredUrlPattern will not add the event. -->
    <processor type="Sitecore.EmailCampaign.Cd.Pipelines.RedirectUrl.RegisterPageEvents, Sitecore.EmailCampaign.Cd">
      <EventName>Click Email Link</EventName>
      <FirstEventName>First Click Email Link</FirstEventName>
    <!-- Triggers the campaign associated with the email message. -->
    <processor type="Sitecore.EmailCampaign.Cd.Pipelines.RedirectUrl.TriggerCampaign, Sitecore.EmailCampaign.Cd" />
    <!-- Marks the current session as an email click session. -->
    <processor type="Sitecore.EmailCampaign.Cd.Pipelines.RedirectUrl.MarkAsEmailClickSession, Sitecore.EmailCampaign.Cd" />
    <!-- Identifies the xDB contact related to the event in the xDB tracker. -->
    <processor type="Sitecore.EmailCampaign.Cd.Pipelines.RedirectUrl.IdentifyContact, Sitecore.EmailCampaign.Cd">
      <param desc="logger" ref="exmLogger" />
    <!-- Moves the identified contact to the Clicked state in the engagement plan of the email message. -->
    <processor type="Sitecore.EmailCampaign.Cd.Pipelines.RedirectUrl.MoveContactToEmailClickedState, Sitecore.EmailCampaign.Cd" />
    <!-- Updates the classification of the identified contact if it is currently greater than a given threshold. -->
    <processor type="Sitecore.EmailCampaign.Cd.Pipelines.RedirectUrl.UpdateContactClassification, Sitecore.EmailCampaign.Cd">
    <!-- Resets the email bounce counter of the identified contact to zero. -->
    <processor type="Sitecore.EmailCampaign.Cd.Pipelines.RedirectUrl.ResetContactEmailBounceCount, Sitecore.EmailCampaign.Cd">
      <EmailAddressesFacetName ref="model/entities/contact/facets/facet[@name='Emails']/@name" />
    <!-- Sets the channel id of the current visit according to the campaign activity associated with the email message. -->
    <processor type="Sitecore.EmailCampaign.Cd.Pipelines.RedirectUrl.SetVisitChannelId, Sitecore.EmailCampaign.Cd" />
    <!-- Sets the language of the current visit according to the language of the email sent to the current recipient. -->
    <processor type="Sitecore.EmailCampaign.Cd.Pipelines.RedirectUrl.SetVisitLanguage, Sitecore.EmailCampaign.Cd" />

If you have additional actions that you want to happen during the Click Email Link event, you can do so by adding a custom processor to this pipeline.

You'll most likely want to place your custom processor somewhere after Sitecore.EmailCampaign.Cd.Pipelines.RedirectUrl.RegisterPageEvents or Sitecore.EmailCampaign.Cd.Pipelines.RedirectUrl.TriggerCampaign processors.

  • Thanks, Pete. I was hoping for something that wouldn't require custom code. I have updated the question to be more explicit about that.
    – Ben Golden
    Nov 6, 2016 at 19:08
  • If it's just not possible without custom code, I will accept this as the answer, though.
    – Ben Golden
    Nov 6, 2016 at 19:10
  • I edited my answer to reflect your context. =) Nov 6, 2016 at 20:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.