Application Insights - Track HTTP Referer

Application Insights is a free service to monitor your web and desktop applications. In a previous post, I showed how to find 404 errors using a custom requests. This is great, but I sometimes want to see where the user comes from. By default, the header Referer is not part of the telemetry data. Using Application Insights, you can add any custom data to an event. In fact, you can add a Dictionary<string, string> to the event. The idea is to be able to use the following analytic request:

requests
| where resultCode == 404
| project url=url, referer=customDimensions.Referer

There are two locations to add the additional data: client side (js) or server side (c#).

In client side, you can easily add additional data, such as the referrer, using an object:

appInsights.trackPageView(null, null, { urlReferrer: document.referrer });

This is great but I prefer tracking events on the server, so I'm sure I don't loose any events because of ad blockers. You can automatically add custom data to the events by creating a class that implements ITelemetryInitializer. Application Insights already provides a few initializers, so you'll find great examples by looking at the code on GitHub. In my case, the telemetry initializer is very basic:

using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.AspNetCore.Http;

public class RefererTelemetryInitializer : ITelemetryInitializer
{
    private const string HeaderNameDefault = "Referer";

    private readonly IHttpContextAccessor _httpContextAccessor;

    public RefererTelemetryInitializer(IHttpContextAccessor httpContextAccessor)
    {
        if (httpContextAccessor == null) throw new System.ArgumentNullException(nameof(httpContextAccessor));

        _httpContextAccessor = httpContextAccessor;
    }

    public void Initialize(ITelemetry telemetry)
    {
        var context = _httpContextAccessor.HttpContext;
        if (context == null)
            return;

        if (context.Request.Headers.TryGetValue(HeaderNameDefault, out var value))
        {
            telemetry.Context.Properties["Referer"] = value.ToString();
        }
    }
}

Then, you must register the initializer in the service collection, so Application Insights can use it.

public void ConfigureServices(IServiceCollection services)
{
    services.AddApplicationInsightsTelemetry(Configuration);
    services.AddSingleton<ITelemetryInitializer, RefererTelemetryInitializer>();

    services.AddMvc();
}

Voilà 😃

As you can see, you can very quickly improve the telemetry data with your own information. For instance, you can add the tenant id of the connected user, the value of a specific header, or any useful data in your context.