Quantcast
Channel: The grumpy coder.
Viewing all articles
Browse latest Browse all 43

Triggering Sitecore Campaigns With External Campaign Codes

$
0
0

If there is one thing that marketers seem to love it is Google campaigns and utm tracking codes or any other kind of campaign codes for that matter - well that is, all campaign codes other than the ones that Sitecore provides.

sc_camp=0ED397C4784E4FA1834897A35461992A

For some “weird” reason marketers really don’t seem to dig the campaign code format in Sitecore. Maybe it is because of the userfriendly sc_camp query string parameter that really makes normal people try every key combination possible to find the underscore sign that is for some reason never used by anyone other than programmers and database designers or maybe it is just the fun fact that most normal people don’t seem to be able to memorize and type in a 32 character guid. Whatever the case may be marketers just really don’t like the internal Sitecore campaign codes and for a good reason. It is a bit ironic that we spend so much time trying to win over the marketers and persuade them that Sitecore really is a serious marketing tool when they can’t even expect to use sensible campaign codes as they are used to in pretty much every other marketing tool. Not to mention that you have to possess near photographic memory to be able to remember exactly which campaign is tied to which guid.

Also as most marketers seem to use Google Analytics and utm tracking codes a lot and really like having them in the campaign urls to be able to track their campaigns in Google, wouldn’t it be really neat if we could somehow use the same utm codes to trigger a campaign in Sitecore?

Of course it would be. So let’s fire up the trusty old text editor and try to fix that.

First we need to find a suitable place to hook into Sitecore’s campaign logic and as luck would have it there is a pipeline called startTracking that we can use for this, so let’s go ahead and add our own processor to the pipeline with the following config.

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <startTracking>
        <processor patch:after="*[@type='Sitecore.Analytics.Pipelines.StartTracking.ProcessQueryStringCampaign, Sitecore.Analytics']"
            type="TGC.Feature.Campaigns.Pipelines.ProcessExternalCampaign, TGC.Feature.Campaigns" />
      </startTracking>
    </pipelines>
  </sitecore>
</configuration>

Ok with the configuration in place, let’s turn to write the processor.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Web;
using System.Linq;
using System.Runtime.Caching;
using Sitecore.Analytics;
using Sitecore.Analytics.Data.Items;
using Sitecore.Analytics.Pipelines.StartTracking;
using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.Marketing.Core;
using Sitecore.Marketing.Definitions;
using Sitecore.Marketing.Definitions.Campaigns;

namespace TGC.Feature.Campaigns.Pipelines
{
    public class ProcessExternalCampaign : StartTrackingProcessor
    {
        private const double CacheExpiration = 1440;
        private const string ExternalCampaignCodeField = "ExternalCampaignCode";
        private const string CampaignsWithExternalCodesCacheKey = "CampaignsWithExternalCodes";

        public override void Process(StartTrackingArgs args)
        {
            try
            {
                Assert.ArgumentNotNull(args, "args");
                Assert.IsNotNull(args.HttpContext, "The HttpContext is not set.");
                Assert.IsNotNull(args.HttpContext.Request, "The HttpRequest is not set.");
                if (Tracker.Current?.Session?.Interaction?.CurrentPage == null)
                    return;

                CacheCampaignsWithExternalCodes();
                TriggerCampaign(args.HttpContext.Request);
            }
            catch (Exception ex)
            {
                Log.Error("An error occurred in ProcessQueryStringExternalCampaign", ex, this);
            }
        }

        private void CacheCampaignsWithExternalCodes()
        {
            if (MemoryCache.Default.Contains(CampaignsWithExternalCodesCacheKey))
                return;

            List<Item> campaignsWithExternalCodes = new List<Item>();

            IDefinitionManager<ICampaignActivityDefinition> manager = DefinitionManagerFactory.Default.GetDefinitionManager<ICampaignActivityDefinition>();
            ResultSet<DefinitionResult<ICampaignActivityDefinition>> allCampaigns = manager?.GetAll(CultureInfo.InvariantCulture);

            if (allCampaigns != null)
            {
                foreach (var campaign in allCampaigns.DataPage)
                {
                    Item campaignItem = Sitecore.Context.Database.GetItem(campaign.Data.Id);
                    string externalCampaignCode = campaignItem[ExternalCampaignCodeField];
                    if (!string.IsNullOrEmpty(externalCampaignCode))
                    {
                        campaignsWithExternalCodes.Add(campaignItem);
                    }
                }
            }
            MemoryCache.Default.Add(CampaignsWithExternalCodesCacheKey, campaignsWithExternalCodes, DateTimeOffset.UtcNow.AddMinutes(CacheExpiration));
        }

        private void TriggerCampaign(HttpRequestBase request)
        {
            if (Tracker.Current.Session.Interaction.CampaignId != null)
                return;

            List<Item> campaignsWithExternalCodes = (List<Item>)MemoryCache.Default.Get(CampaignsWithExternalCodesCacheKey);

            Item campaignItemWithExternalCode = campaignsWithExternalCodes?.FirstOrDefault(item => request.RawUrl.ToLowerInvariant().Contains(item[ExternalCampaignCodeField].ToLowerInvariant()));
            if (campaignItemWithExternalCode == null)
                return;

            Tracker.Current.CurrentPage.TriggerCampaign((CampaignItem)campaignItemWithExternalCode);
        }
    }
}

Basically the processor will cache all campaign items that have a value in the field ExternalCampaignCode and match this value against the current request raw url to find a match.

For this to work we will also have to extend the Campaign template in Sitecore. So create a new template with a single line text field called ExternalCampaignCode and add it as a base template to the /sitecore/templates/system/Analytics/Campaign template.

With the processor in place, you will now be able to trigger your Sitecore campaigns with any external code simply by adding it to the ExternalCampaignCode field of the campaign item.

But wait there is more!

Because we are simply matching again the raw url of the request you can use any part of the url to trigger your Sitecore campaign. So not only can you trigger a campaign with a Google utm tracking code, you can even trigger the campaign with no code at all simply by using for instance the path from the url as a trigger. So you can have a page called https://www.mywebsite.com/thecoolestcampaign and it will still work. How cool is that?


Viewing all articles
Browse latest Browse all 43

Trending Articles