First goal triggered: Extending Sitecore xDB



At Yoyo, we love pushing technology to the limits and taking a creative approach to problem-solving.

Yoyo is a Certified Sitecore Partner and, as is often the case when working with any 3rd party platform, we regularly get under the hood to better understand how it works at a low level and how Sitecore themselves would like it to be used.

Despite being an extremely flexible and powerful content management system and digital marketing suite, occasionally our customers would like it to work in a way that it wasn’t designed for, in order to achieve their own business objectives. Fortunately, Sitecore usually has an answer to this, or at least enough flexibility to allow you to adapt it to meet your needs.

In this article, I will describe one such real-world scenario. I should also mention that this article is largely technical in nature and assumes you already have a basic understanding of Sitecore and its experience platform (XP) architecture, including concepts such as Renderings, Goals, Campaigns and Engagement Plans.

First, a bit of context.

Out of the box, Sitecore doesn’t care what order goals get registered by visitors, as conceptually goals are designed to help measure a user’s engagement value over time.

However, sometimes you need to take action based on the first goal (or one of a number of potential goals) registered for a given campaign. For example, an email campaign might contain multiple calls to action in a single mailshot, each with its own landing page with page view goals associated with it. In this scenario, you would typically have a single Sitecore campaign and engagement plan to handle your remarketing and overall engagement experience for the user, with different actions triggered based on the first goal registered.

This is a problem as, at best, your engagement plan would only be able to process its goal-based rules in order, top to bottom and just by clicking around from page to page, a campaign user might inadvertently trigger multiple campaign goals in a single visit.

So, what to do?

A solution to this is to do away with standard page view goals and create a custom rendering on your landing pages instead which would programmatically register a campaign goal, based on specific criteria.

As mentioned, this is a real-world scenario and it just so happens that we recently built such a rendering for a high-profile Sitecore customer who happens to also use the Sitecore Email Experience Manager (EXM) module to send out their email campaigns. We called it the Campaign Goal rendering. This rendering can be added to any content page in Sitecore (but would typically be reserved for email landing pages), whereby the content editor can specify the goal to be fired when a user is enrolled in a certain Sitecore campaign browses to it, or is sent via an email link that page, assuming they have not already triggered one or a number of other specified goals. Furthermore, due to the transient nature of sessions, we have added the option to force Sitecore to take into account historical interaction data, rather than just in-session interactions, for that user.

The new rendering is designed to be entirely programmatic, but show its configuration information to the content editor when viewed within the Sitecore Experience Editor (nothing will be rendered on the web page itself when the web page is viewed by a standard user, however).

When adding the component to a page, the editor is asked to choose a data source for the component. They choose the goal they want to be triggered on the page.

Once added to the page, the editor can further configure the rendering within the Component Properties. We created a custom rendering parameters template to the rendering such that the following additional values can be set at design time:

  1. Applicable Campaign; the specific Sitecore campaign the user must belong to.
  2. Invalidating Goals; a list of goals that, if at least one has already been triggered by the user, would prevent the page goal from being registered.
  3. Include Historical Data; a checkbox to control whether or not to take into account all historical interactions, or just the user’s current session. This is in terms of checking what Sitecore campaigns they are enrolled in and what goals they have registered.

Anything else?

Anecdotally, it’s worth considering the Sitecore cache.  Being a Sitecore rendering, it’s possible for it to be cached by Sitecore, either at the rendering or the instance level. In which case, the rendering logic may not execute on every page load – which is another problem. One way to get around this is to bypass the Sitecore cache entirely for this rendering. Again, there’s no out of the box way to do this in Sitecore but there are a couple of hacks you can try, including temporarily disabling the Sitecore CacheManager for the page in question. However, it’s a sledgehammer approach and it’s not a very good idea to disable the entire cache at any time, as Sitecore relies heavily on its various caching layers for performance.

Instead, a nice approach we employed is detailed here -, whereby you intercept the Sitecore MVC render rendering pipeline to disable HTML caching only for your specific controller rendering, rather than the entire page. Big thanks to Mikael Högberg for posting his work.

To wrap up.

So all of this is just one way you can achieve a first-past-the-post approach to acting on registered goals in Sitecore. Another advantage of this approach is that the Campaign Goal rendering can be extended to include other fields you might want to consider, such as including an external redirect URL. This could be used to have a Sitecore page acting as an interstitial page for redirecting to an external website that, perhaps, is not a Sitecore site (and isn’t running the Sitecore FXM). In this scenario, the Sitecore page goal could still be potentially registered prior to the user being redirected to the external website in question, meaning they could still be entered into an engagement plan for processing, even though they were sent to an entirely different website.