How to Track ItemWebApi Сalls with Sitecore Analytics

How to Track ItemWebApi Сalls with Sitecore Analytic

ItemWebApi has been introduced in Sitecore 6 and became obsolete today due to Sitecore.Services.Client API and MVC that enable easy Ajax calls to controller actions. Yet, there are still several reasons to use ItemWebApi and Sitecore mobile SDK is one of them. Just a reminder - Sitecore mobile SDK allows to create iOS apps with content coming from the Sitecore items.

ItemWebApi calls belong to ‘httpRequestBegin’ pipeline launched by ‘Sitecore.Nexus.Web.HttpModule’ on BeginRequest application event (https://msdn.microsoft.com/en-us/library/system.web.httpapplication_events%28v=vs.110%29.aspx ). That means the pipeline cuts out Sitecore Analytics because Analytics leverages the session state, which is not yet created by ASP.NET at that stage. How can we enable Sitecore Analytics for such ‘untrackable’ calls that are finished even before the Tracker is initialized?

ItemWebApi calls

Let's look inside the Sitecore.ItemWebApi.config. There we have a ‘LaunchRequest’ processor defined which does the main job and then aborts the pipeline. Essentially, its job is to run the ‘itemWebApiRequest’ pipeline, a set of low-level HttpRequest processors finished with simple ‘response.Write(...)’:

...
HttpResponse response = arguments.Context.HttpContext.Response;
  ...
  response.Write(arguments.ResponseText);
 response.End();

In order to track access to items in Sitecore Analytics we need to add our processor to this pipeline, for example after ‘ <processor type="Sitecore.ItemWebApi.Pipelines.Request.ResolveItems, Sitecore.ItemWebApi" />’ and track resolved items. However, Tracker.StartTracking(); call will fail and throw an exception because Tracker cannot be initialized without session state.

To avoid the exception we can implement simple trick with ‘LaunchRequest’ processor. Create new processor to replace the old one with very similar code but instead of running ‘itemWebApiRequest’ pipeline, we ‘redirect’ request to the new HttpHandler:

public class LaunchRequest : HttpRequestProcessor
    {
        public override void Process(HttpRequestArgs arguments)
        {
            Assert.ArgumentNotNull(arguments, "arguments");
            try
            {
                Sitecore.ItemWebApi.Context current = Sitecore.ItemWebApi.Context.Current;
                if (current == null)
                {
                    return;
                }

                //instead of  CorePipeline.Run("itemWebApiRequest", new RequestArgs());
                arguments.Context.RemapHandler(new SessionActionHandler());

                arguments.AbortPipeline();
            }
            catch (Exception ex)
            {...}
    }
}

This handler will ask ASP.NET to initialize session for us and run the same ‘itemWebApiRequest’ pipeline:

public class SessionActionHandler : IHttpHandler, IRequiresSessionState
{
    private HttpContext context;

    public bool IsReusable { get { return false; }}

    public void ProcessRequest(HttpContext httpContext)
    {
        Assert.ArgumentNotNull(httpContext, "httpContext");

        CorePipeline.Run("itemWebApiRequest", new RequestArgs());
    }
}

Now we can safely use Tracker at our ‘TrackItems’ processor and write code like this:

public class TrackItems : RequestProcessor
{
    public override void Process(RequestArgs arguments)
    {
        if (!Tracker.IsActive)
        {
            Tracker.StartTracking();
        }
            Tracker.Current.Interaction.CurrentPage.SetUrl(LinkManager.GetItemUrl(Sitecore.ItemWebApi.Context.Current.Item));
    }
}

After some time you will see ItemWebApi calls in your analytics reports. Once the Tracker.Current.Interaction.CurrentPage.SetUrl() method was used to set the Page URL, iOS app api call will look like regular visit with zero ‘Time on page’, otherwise it will start with ‘/-/item’ in the analytics.

Happy coding!