Track a visitors coordinates in the Sitecore DMS

phoneAndTabletMaxMind is great for tracking visitors – It gives you all kind of information based on the IP address.

Today when more and more users/visitors are using handheld devices with GPS for browsing the internet, I wanted to get the actual location for the visitor using HTML5 Geolocation API
Note: Since it can compromise user privacy, the position is not available unless the user approves it.

In order to get the location/coordinates, following javascript is used (window.coordinates is a global variable):

if (navigator)
    navigator.geolocation.getCurrentPosition(geoSuccess, geoError);

function geoSuccess(p) {
    window.coordinates = p.coords;
}

function geoError(data) {
    //Do some error handling
	
}

I added the geolocation to my previous post, Client side tracking with Sitecore DMS.

var Sandbox = Sandbox || {};
 
jQuery(document).ready(function () {
    Sandbox.Alert.DomReady();
});
 
Sandbox.Alert = {
    DomReady: function () {
 
		Sandbox.Alert.InitSandbox();
 
        jQuery("#closeAlert").click(function () {
 
            Sandbox.Alert.TrackCloseEvent();
 
        });
 
    },
 
	InitSandbox: function () {

        if (navigator)
            navigator.geolocation.getCurrentPosition(geoSuccess, geoError);

        function geoSuccess(p) {
            window.coordinates = p.coords;
        }

        function geoError(data) {
            //Some error handling
        }


    },
 
    TrackCloseEvent: function () {
 
        var dataContainer = jQuery(".alert alert-info fade in");
 
	    var requestParamAndValues = {};
        requestParamAndValues["PageEventId"] = dataContainer.data("goal");
        requestParamAndValues["PageUrl"] = dataContainer.data("pageurl");
 
		if (window.coordinates)
			requestParamAndValues["Coordinates"] = Sandbox.Alert.StringFormat("{0},{1}", window.coordinates.latitude, window.coordinates.longitude, '1');

 
        var jsonObject = {};
        jsonObject["requestParamAndValues"] = requestParamAndValues;
 
        var analyticsEvent = new AnalyticsPageEvent(jsonObject);
        analyticsEvent.trigger();
    },
	
	StringFormat : function () {
        var s = arguments[0];
        for (var i = 0; i < arguments.length - 1; i++) {
            var reg = new RegExp("\\{" + i + "\\}", "gm");
            s = s.replace(reg, arguments[i + 1]);
        }
        return s;
    }
};

In the aspx page, ClientEventTracker, we need to add some lines of code (TrackerService):

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();
 
	        TrackerService.SetCurrentVisitorCoordinates(inputData.GetValueByKey(InputDataKeys.Coordinates));
 
            TrackerService.RegisterEventToAPage(inputData.GetValueByKey(InputDataKeys.PageEventId), inputData.GetValueByKey(InputDataKeys.PageUrl));
 
            Tracker.Submit();
        }
    }
}

TrackerService is defined here:

namespace Sandbox.Tracking.Infrastructure
{
    public class TrackerService
    {

        public static void RegisterEventToAPage(string eventId, string url)
        {

            if (string.IsNullOrWhiteSpace(eventId))
                return;

            if (string.IsNullOrWhiteSpace(url))
                return;

            if (!Tracker.IsActive)
                return;

            PageEventItem pageEvent = new PageEventItem(Sandbox.Framework.SitecoreEnhancements.SitecoreItemRepository.Get(eventId));

            VisitorDataSet.PagesRow pagesRow = Tracker.CurrentVisit.GetPages().LastOrDefault(p => p.Url.Contains(url));

            if (pagesRow == null)
                return;

            pagesRow.Register(pageEvent);

        }

        public static void SetCurrentVisitorCoordinates(string coordinates)
        {

            GeoCoordinate? geoCoordinate = GeoCoordinateRepository.Get(coordinates);

            if (!geoCoordinate.HasValue)
                return;

            if (!Tracker.IsActive)
                return;

            Tracker.CurrentVisit.Latitude = geoCoordinate.Value.Latitude;
            Tracker.CurrentVisit.Longitude = geoCoordinate.Value.Longitude;

        }

    }
}

GeoCoordinate object:

namespace Sandbox.Tracking.Model
{
    public struct GeoCoordinate
    {
        private readonly double _latitude;
        private readonly double _longitude;

        public double Latitude { get { return _latitude; } }
        public double Longitude { get { return _longitude; } }

        public GeoCoordinate(double latitude, double longitude)
        {
            _latitude = latitude;
            _longitude = longitude;
        }


        public override string ToString()
        {
            return string.Format("{0},{1}", Latitude, Longitude);
        }

        public override bool Equals(Object other)
        {
            return other is GeoCoordinate && Equals((GeoCoordinate)other);
        }

        public bool Equals(GeoCoordinate other)
        {
            return Math.Abs(Latitude - other.Latitude) < double.Epsilon && Math.Abs(Longitude - other.Longitude) < double.Epsilon;
        }

        public override int GetHashCode()
        {
            return Latitude.GetHashCode() ^ Longitude.GetHashCode();
        }

    }
}

GeoCoordinateRepository:

namespace Sandbox.Tracking.Model.Repositories
{
    public class GeoCoordinateRepository
    {

        public static GeoCoordinate? Get(string latitude, string longitude)
        {
            if (string.IsNullOrWhiteSpace(latitude) || string.IsNullOrWhiteSpace(longitude))
                return null;


            string coordinates = string.Concat(latitude, ",", longitude);
            return GeoCoordinateFactory.Create(coordinates);

        }

        public static GeoCoordinate? Get(string coordinates)
        {
            if (string.IsNullOrWhiteSpace(coordinates))
                return null;

            return GeoCoordinateFactory.Create(coordinates);

        }

        public static IEnumerable<GeoCoordinate?> Get(IEnumerable<string> manyCoordinates)
        {
            return manyCoordinates.Select(Get);

        }
    }
}

Finally the GeoCoordinateFactory:

namespace Sandbox.Tracking.Model.Factories
{
    internal class GeoCoordinateFactory
    {
        internal static GeoCoordinate? Create(string coordinates)
        {

            string[] coordinateArray = coordinates.Split(',');

            if (coordinateArray.Length == 0)
                return null;

            if (string.IsNullOrWhiteSpace(coordinateArray[0]) || string.IsNullOrWhiteSpace(coordinateArray[1]))
                return null;

            return new GeoCoordinate(double.Parse(coordinateArray[0], NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture), double.Parse(coordinateArray[1], NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture));


        }
    }
}

That’s all for now folks 🙂


9 thoughts on “Track a visitors coordinates in the Sitecore DMS

    1. Thank you. I haven’t thought about it but yes it’s possible. It’s a really good idea. I will work with it and update you how it’s developing.

      Like

Leave a comment

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