Client side tracking with Sitecore DMS

For not so long ago I wanted to track a client event for the DMS. In this case I wanted to know if a specific alert box has been closed.
Image1
I did some googling and found Sitecore Client Event Tracker on the Github. That was exactly what I needed.

I did some minor changes to it. Instead of passing a number of parameters to the javascript method, AnalyticsPageEvent, I changed it to take one parameter – a Json object.

function AnalyticsPageEvent(jsonData) {
   
    this.jsonData = jsonData;

    this.trigger = function () {
        var queryString = '';

        if (!this.jsonData) {
            return;
        }

        queryString += '&' + 'jsonData' + '=' + JSON.stringify(this.jsonData);

       
        var url = '/components/Tracking/Presentation/ClientEventTracker.aspx' + '?ra=' + eventTracker.randomstring() + queryString;
        eventTracker.request(url);

    };
}

The Json object is a serialized class with a dictionary

namespace Sandbox.Framework.SitecoreSpecific.Model
{
    [DataContract]
    public class InputData
    {
        [DataMember(Name = "requestParamAndValues")]
        public Dictionary<string, string> RequestParamAndValues { get; set; }


        public bool ContainsParamkey(InputDataKeys inputDataKeys)
        {
            return RequestParamAndValues != null && RequestParamAndValues.ContainsKey(inputDataKeys.ToString());
        }

        public string GetValueByKey(InputDataKeys inputDataKeys)
        {

            string value;
            RequestParamAndValues.TryGetValue(inputDataKeys.ToString(), out value);

            return value;
        }

        public void SetValueByKey(InputDataKeys inputDataKeys, string value)
        {
            if (RequestParamAndValues.ContainsKey(inputDataKeys.ToString()))
                RequestParamAndValues[inputDataKeys.ToString()] = value;
            else
                RequestParamAndValues.Add(inputDataKeys.ToString(), value);
        }
    }
}

The keys for the dictionary are defined in an enum

namespace Sandbox.Framework.SitecoreSpecific
{
    public enum InputDataKeys
    {
        None = 0,
        IpAddress = 1,
        Coordinates = 2,
        Language = 3,
        Device = 4,
        Browser = 5,
        PageEventId = 6,
        PageEventName = 7,
        PageEventText = 8,
        PageEventKey = 9,
        PageEventData = 10,
        PageUrl = 11,
        EngagementPlan = 12,
        EngagementPlanState = 13
    }
}

The event/goal in Sitecore:
Image2

The widget containing the alert box. The data-goal attribute contains the item id for the “Closed Alert box” event and the data-pageurl holds the path to actual page(in order for the tracker to find the correct page row).

<div class="alert alert-info fade in" 
        data-pageurl="<%= HttpContext.Current.Request.Url.PathAndQuery %>"
        data-goal=" <%# Sandbox.Alert.Constants.Analytics.Goals.CloseAlertBox %> ">
        <button type="button" class="close" id="closeAlert" data-dismiss="alert">×</button>
        <asp:PlaceHolder runat="server" Visible="<%# !string.IsNullOrWhiteSpace(this.GetDataSourceOrContextItem().GetString(Sandbox.Spots.Constants.Fields.Alert.AlertHeader)) || Sitecore.Context.PageMode.IsPageEditorEditing %>">
            <h4>
                <sc:Text runat="server" DataSource="<%# this.GetDataSourceOrContextItem().ID %>" Field="<%# Sandbox.Spots.Constants.Fields.Alert.AlertHeader%>" />
            </h4>
        </asp:PlaceHolder>

        <sc:Text runat="server" DataSource="<%# this.GetDataSourceOrContextItem().ID %>" Field="<%# Sandbox.Spots.Constants.Fields.Alert.AlertText%>" />
    </div>

The javascript for the widget:

var Sandbox = Sandbox || {};

jQuery(document).ready(function () {
    Sandbox.Alert.DomReady();
});

Sandbox.Alert = {
    DomReady: function () {

        jQuery("#closeAlert").click(function () {

            Sandbox.Alert.TrackCloseEvent();

        });

    },

    TrackCloseEvent: function () {

        var dataContainer = jQuery(".alert alert-info fade in");

        var requestParamAndValues = {};
        requestParamAndValues["PageEventId"] = dataContainer.data("goal");
        requestParamAndValues["PageUrl"] = dataContainer.data("pageurl");

        var jsonObject = {};
        jsonObject["requestParamAndValues"] = requestParamAndValues;

        var analyticsEvent = new AnalyticsPageEvent(jsonObject);
        analyticsEvent.trigger();
    }
};

The javascript for the tracking.

var eventTracker = false;

function AnalyticsPageEvent(jsonData) {
   
    this.jsonData = jsonData;

    this.trigger = function () {
        var queryString = '';

        if (!this.jsonData) {
            return;
        }

        queryString += '&' + 'jsonData' + '=' + JSON.stringify(this.jsonData);

       
        var url = '/components/Tracking/Presentation/ClientEventTracker.aspx' + '?ra=' + eventTracker.randomstring() + queryString;
        eventTracker.request(url);

    };
}

function EventTracker() {
    this.request = function (url) {
        var script = new ClientEventScript(url, true);
        script.load();
    };

    this.randomstring = function () {
        var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        var text = "";

        for (var i = 0; i < 32; i++) {
            text += possible.charAt(Math.floor(Math.random() * possible.length));
        }

        return text;
    };
}

function ClientEventScript(src, async) {
    this.src = src;
    this.async = async;

    this.load = function () {
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = this.src;
        script.async = this.async;

        var ssc = document.getElementsByTagName('script')[0];
        ssc.parentNode.insertBefore(script, ssc);
    };
}

eventTracker = new EventTracker();

The aspx page, ClientEventTracker, (which is requested from the EventTracker-method) will register the tracking

namespace Sandbox.Tracking.Presentation
{
    public partial class ClientEventTracker : System.Web.UI.Page
    {
        protected void Page_Init(object sender, EventArgs e)
        {
            Context.Response.ContentType = "application/javascript";
            TriggerEvent(this.Context);
        }

        private static void TriggerEvent(HttpContext context)
        {

            string jsonData = context.Request["jsonData"];

            InputData inputData = ConvertJsonToObjectService.Convert<InputData>(jsonData);

            if (!inputData.ContainsParamkey(InputDataKeys.PageUrl))
                return;

            if (!inputData.ContainsParamkey(InputDataKeys.PageEventId))
                return;

            Tracker.StartTracking();
            Tracker.CurrentPage.Cancel();

            VisitorDataSet.PagesRow pageRow = Tracker.CurrentVisit.GetPages().FirstOrDefault(p => p.Url.Contains(inputData.GetValueByKey(InputDataKeys.PageUrl)));

            if (pageRow == null)
                return;

            PageEventItem pageEvent = null;

            if (!string.IsNullOrWhiteSpace(inputData.GetValueByKey(InputDataKeys.PageEventId)))
                pageEvent = new PageEventItem(Sandbox.Framework.SitecoreEnhancements.SitecoreItemRepository.Get(inputData.GetValueByKey(InputDataKeys.PageEventId)));

            if (pageEvent == null) 
                return;

            pageRow.Register(pageEvent);

            Tracker.Submit();
        }
    }

That’s all for now folks 🙂


2 thoughts on “Client side tracking with Sitecore DMS

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.