Search code examples
sitecoreanalyticssitecore7sitecore-dmssitecore7.1

Making marketing campaigns in Sitecore Analytics behave like Google Analytics


The default behavior for Marketing Campaigns in Sitecore Analytics is such that they will only be applied to a visit if the campaign is applied on the first page of the visit. This could be a landing page flagged with that marketing campaign, or via the sc_camp query string parameter.

I find this behavior to be somewhat problematic in certain commerce scenarios. It's also different than how Google Analytics handles marketing campaigns. Google Analytics will start a new visit for the user if he/she re-enters the site via a different marketing campaign.

I'd like to emulate this behavior in Sitecore Analytics for a POC I'm working on. I've attempted this via the initializeTracker pipeline. I can successfully detect a change in the marketing campaign for the visit, but I'm unable to end and restart the visit. I've tried both utilizing Tracker.EndVisit() and simply changing the ID of the visit. Neither seems to result in a new visit, associated with the marketing campaign.

Does anyone know how I can successfully end the previous visit, and start a new one, within the same request?

I am working in CMS/DMS 7.1 rev 140130. My current code is below.

using System;
using System.Web;
using Sitecore.Analytics;
using Sitecore.Analytics.Pipelines.InitializeTracker;
using Sitecore.Analytics.Web;
using Sitecore.Configuration;
using Sitecore.Data;
using Sitecore.Web;

namespace ActiveCommerce.Training.PriceTesting.Analytics
{
    public class RestartVisitOnNewCampaign : InitializeTrackerProcessor
    {
        public override void Process(InitializeTrackerArgs args)
        {
            if (HttpContext.Current == null)
            {
                args.AbortPipeline();
            }

            //no need to restart visit if visit is new
            if (Tracker.CurrentVisit.VisitPageCount < 1)
            {
                return;
            }

            //look for campaign id in query string
            Guid campaign;
            var campaignStr = WebUtil.GetQueryString(Settings.GetSetting("Analytics.CampaignQueryStringKey")).Trim();
            if (string.IsNullOrEmpty(campaignStr) || !Guid.TryParse(campaignStr, out campaign))
            {
                return;
            }

            //don't restart if the campaign isn't changing
            if (!Tracker.CurrentVisit.IsCampaignIdNull() && Tracker.CurrentVisit.CampaignId == campaign)
            {
                return;
            }

            //Tracker.EndVisit(false);

            //restart visit by setting new ID
            var visitCookie = new VisitCookie();
            visitCookie.VisitId = ID.NewID.Guid;
            visitCookie.Save();
        }
    }
}

Solution

  • Thanks everyone for the input. Andrew's answer actually ended up being the closest, so I've awarded him the bounty.

    The issue in the end appeared to be the Visitor.Settings.IsFirstRequest property, which ultimately is derived from VisitCookie.IsFirstRequest. If this property is false, a new visit will not be created, and the current page request won't be associated with the new visit. This also needs to happen in order for the page to be classified as a "landing page," which would associate the campaign with it.

    IsFirstRequest is set in VisitCookie.Load(), and compares the ASP.NET Session ID in the cookie to the current ASP.NET Session ID. This is why invaliding the cookie, or changing the Visit ID was not enough. Unfortunately there's no way to change the Session ID value using the VisitCookie object, so the easiest thing to do, which appears to work, is to just empty the cookie value directly, before the Sitecore.Analytics.Pipelines.InitializeTracker.Initialize processor runs.

    From my testing, this results in a new visit whenever the campaign ID changes. I can see this in both the Visits table and when personalizing based on Campaign ID.

    namespace ActiveCommerce.Training.PriceTesting.Analytics
    {
        public class RestartVisitOnNewCampaign : InitializeTrackerProcessor
        {
            public override void Process(InitializeTrackerArgs args)
            {
                if (HttpContext.Current == null)
                {
                    args.AbortPipeline();
                    return;
                }
    
                //no need to restart visit if visit is new
                if (Tracker.Visitor.Settings.IsNew || Tracker.Visitor.Settings.IsFirstRequest || Tracker.CurrentVisit.VisitPageCount < 1)
                {
                    return;
                }
    
                //look for campaign id in query string
                Guid campaign;
                var campaignStr = WebUtil.GetQueryString(Settings.GetSetting("Analytics.CampaignQueryStringKey")).Trim();
                if (string.IsNullOrEmpty(campaignStr) || !Guid.TryParse(campaignStr, out campaign))
                {
                    return;
                }
    
                //don't restart if the campaign isn't changing
                if (!Tracker.CurrentVisit.IsCampaignIdNull() && Tracker.CurrentVisit.CampaignId == campaign)
                {
                    return;
                }
    
                var current = HttpContext.Current;
                var cookie = current.Response.Cookies["SC_ANALYTICS_SESSION_COOKIE"];
                if (cookie == null)
                {
                    cookie = new HttpCookie("SC_ANALYTICS_SESSION_COOKIE");
                    current.Response.Cookies.Add(cookie);
                }
                cookie.Value = "";
            }
    
        }
    }