Track Client-side Events in Sitecore MVC

analytics client event tracking mvc Sitecore

Tracking events triggered on your site is obviously of vital importance to measure your visitors’ behaviour and level of engagement. Sitecore does a good job of tracking events associated to a page that are triggered upon page visit – but in reality, we are more concerned about tracking client-side events especially since almost everything happens on the client-side these days due to the emergence of JavaScript frameworks like Angular and Ember. Though Sitecore is somewhat limited in this aspect we can definitely utilize the very rich Sitecore Analytics API to accomplish this feat.

The Sitecore Analytics API works only if there’s an active session. The good news is you can create your own non-Sitecore MVC controllers and use them like REST endpoints, and you can expect that they will be executed in the same session as your Sitecore pages. With that in mind there’s no stopping you from registering your Sitecore page events from the client-side, and the only thing you need to know now is how to register page events programmatically.

The Controller code

Here’s a very basic controller action to register the page event:

[DisableTracking]
public class AnalyticsController : Controller
{
    [HttpPost]
    public ActionResult TrackEvent(string name, string data, string text)
    {
        var pageEventData = new PageEventData(name) { Data = data, Text = text };
        var interaction = Tracker.Current.Session.Interaction;
        var localPath = Request.UrlReferrer?.LocalPath;
        var page = interaction.GetPages().LastOrDefault(n => n.Url.Path == localPath);

        page?.Register(pageEventData);
        interaction.AcceptModifications();
            
        return new HttpStatusCodeResult(HttpStatusCode.OK);
    }
}

FYI: You may want to check if the page event has actually been registered and return an appropriate status code if it’s not. After the page.Register call you can check the last event in page.PageEvents to see if it maches the PageEventData.

You may have also noticed that I used the UrlReferrer’s local-path to determine the current executing page. It’s because an MVC controller action is treated as a page, therefore, you’re considered to be in the TrackEvent page when executing the path. And since it is a page you may want to disable tracking on it, hence, I added an Action Filter called ‘DisableTracking’ using the code below:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public sealed class DisableTrackingAttribute: ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        Sitecore.Analytics.Tracker.Current.CurrentPage.Cancel();

        base.OnActionExecuting(filterContext);
    }
}

Registering the Route

Assuming you’re already aware that by default attribute routing does not work in Sitecore 8, and that you’ve already nailed down registering MVC routes in the ‘Initialize’ pipeline, this is how you can register your action route:

private static void RegisterAnalyticsRoutes(RouteCollection routes)
{
    routes.MapRoute(
        name: "TrackEvent",
        url: "analytics/trackevent",
        defaults: new { controller = "Analytics", action = "TrackEvent" }
    );
}

The client-side

Before we can call the page-event on the client-side we need to create a client-side function to send the tracking information to our Controller action:

function trackClickEvent() {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (xhttp.status == 200) {
      // perform callback action here
    }
  };
  xhttp.open("POST", "/analytics/trackevent", true);
  xhttp.setRequestHeader("Content-type", "application/json");

  var obj = JSON.parse(this.getAttribute("data-tracking"));
  var json = JSON.stringify(obj);
  xhttp.send(json);
}

Now we just need to attach the trackClickEvent function to our trackable elements:

<a href="#" data-tracking="{"name":"Link Clicked","data":"some data","text":"some text"}">Click this link</a>

// for the sake of brevity let's use Array.prototype.forEach
Array.from(document.querySelectorAll('[data-tracking]'))
  .forEach(function(elem) {
    elem.onclick = trackClickEvent;
  });

Feel free to comment about suggestions to improve this approach.

5 Thoughts to Track Client-side Events in Sitecore MVC

Comments are closed.

  • Mark G
    Mark G

    Nice post! Very simple and clear!

    24.07.2019 20:05
  • Miguel
    Miguel

    awesome!, was looking for this, the line elems[i].onclick = trackEvent; should be elems[i].onclick = trackClickEvent;

    31.10.2016 02:06
    • Jeff Sulit
      Jeff Sulit

      Appreciate the feedback and correction, Miguel. Cheers!

      01.11.2016 09:58
    • Miguel
      Miguel

      great!, were you able to display the tracked info in a report?

      02.11.2016 01:44
    • Jeff Sulit
      Jeff Sulit

      The tracked event is shown in the Experience Profile if the event’s ‘Show in Events’ check field was ticked beforehand. As for the event data, you can retrieve the event text programmatically, for example, to create dimension keys for your custom report. Check out this topic on Sitecore Community: https://community.sitecore.net/developers/f/9/t/127

      03.11.2016 20:51