Tags

, , , , , , , ,

umbrellasContent Targeting is one of the strongest points of Sitecore’s Digital Marketing Suite (DMS). Marketeers are able to set up rules and conditions for rendering conditional content on the website. The conditions provided by Sitecore out-of-the-box include: checking how many times the visitor has visited the website, checking what language version the website is in, and checking the “profile” of the visitor (in which predefined category the visitor fits). Marketeers could also check from which city the visitors is requesting the web page. This is done by looking up the GeoLocation of the visitor by his IP address.

Thusfar most focus is on coming up with rules and conditions for profiling the visitor. On a website for cars, the visitor will be profiled as a customer looking for a sports car, a family car, a budget car, etc. When the visitor is profiled in one of these categories, appropriate content is served specifically for his tastes and needs.

But the GeoIp could become a much richer variable, if we could combine it with all sorts of other data. For example: the weather. Imagine a customer visiting a website for outdoor equipment. When it’s raining at the location of the visitor, the website could be aware of this, and show a conditional rendering with a text like “Preparing for a rainy day?”, and offers of an assortment of waterproof clothing and bags. Likewise, when it’s sunny and a high temperature, the website could respond to it, and offer sunglasses and sandals, etc.

We already have the GeoLocation from the standard Sitecore DMS installation. Now in order to determine the weather at this location, we need another datasource with which we can cross-reference our Geo-data. An example for the Netherlands is the website Buienradar.nl, which exposes it’s data from 53 metereological station at the URL http://xml.buienradar.nl.

We can use this data to cross-reference with the given GeoIP data. For this we will use a WeatherService class, which contains a private method that is responsible for getting named weather-related properties from the provided weather data (for example “temperature”, “rainfall”, “humidity”, etc.)

private string GetWeatherProperty(GeoCoordinate currentGeoCoordinate, string weatherPropertyName)
{
string weatherPropertyValue = string.Empty;

XDocument xDocument = XDocument.Load("http://xml.buienradar.nl/");

XElement weatherStations = (from xmlNode in xDocument.Descendants("weerstations") select xmlNode).FirstOrDefault();

string nearestWeatherStationName = string.Empty;

double nearestDistance = 0;

// 53 metereological stations in the Netherlands
foreach (XElement weatherStation in weatherStations.Nodes())
{
	XElement xElementLatitude = weatherStation.Element("latGraden");
	XElement xElementLongitude = weatherStation.Element("lonGraden");
	double weerstationLatitude = Convert.ToDouble(xElementLatitude.Value);
	double weerstationLongitude = Convert.ToDouble(xElementLongitude.Value);
	GeoCoordinate geoCoordinateWeatherStation = new GeoCoordinate(weerstationLatitude, weerstationLongitude);

	double distanceToWeatherStation = currentGeoCoordinate.GetDistanceTo(geoCoordinateWeatherStation);

	if (distanceToWeatherStation < nearestDistance || nearestDistance == 0)
	{
		nearestDistance = distanceToWeatherStation;
		XElement weatherPropertyElement = weatherStation.Element(weatherPropertyName);
	weatherPropertyValue = weatherPropertyElement.Value;
	// set nearest weather station name as well, for logging purposes
	nearestWeatherStationName = weatherStation.Element("stationnaam").Value;
	}
}
Sitecore.Diagnostics.Log.Info("Nearest weather station: " + nearestWeatherStationName, this);
return weatherPropertyValue;
}

This code does the following. First we load the weather data XML, and get all the 53 weather station node. Then we are going to get a GeoCoordinate from each weather station, by it’s latitude and longitude. We use a System.Device.Location.GeoCoordinate object for this purpose. With this object, we also calculate the distance from the weather station to the provided coordindate from the GeoIP. Brain Pedersen has made a program that also calculates the distance between two coordinates, but I prefer to let .Net take care of it.

Now we go though all the weather stations to see if we can find a station that is nearer, and then we pass the value of the weather-related property of the nearest station back to the process.

Now we add a public method, that is responsible for retrieving the temperature. The public method calls the above private method:

public string GetCurrentTemperature(GeoCoordinate currentGeoCoordinate)
{
	return GetWeatherProperty(currentGeoCoordinate, "temperatuurGC");
}

Next, we add a few new conditions to Sitecore. We navigate to the node “/sitecore/system/Settings/Rules/Conditional Renderings/Conditions”, and add a folder “Weather Conditions”. In that folder, we add an item of the template “/sitecore/templates/System/Rules/Condition”. The field “Type” of this item should refer to the class we are about to make. The field “Text” is used to contain the text that the user will see eventually when he is configuring his own rules.

Weather condition item
Finally we are going to add the class that we just referred to in the “Type” field. We call it “TemperatureCondition”, and we inherit from the class Sitecore.Analytics.Rules.Conditions.VisitCondition. Inside this class, we just retrieve the GeoCoordinate from the provided VisitRow, and pass that to the WeatherService that we already added above.

public class TemperatureCondition<T> : VisitCondition<T> where T : RuleContext
{
    private NumberFormatInfo _numberFormatInfo;
    protected NumberFormatInfo NumberFormatInfo
    {
        get
        {
            if (_numberFormatInfo == null)
            {
                _numberFormatInfo = new NumberFormatInfo();
                _numberFormatInfo.NumberDecimalSeparator = ".";
            }

            return _numberFormatInfo;
        }
    }
    
    protected override bool Execute(T ruleContext)
    {
        double benchmark = Convert.ToDouble(this.Value);
        double temperature = Convert.ToDouble(GetTemperature(), NumberFormatInfo);
        
        Item operatorItem = Sitecore.Context.Database.GetItem(this.OperatorId);

        string operatorName = operatorItem.Name;

        bool isValid;
        switch (operatorName.ToLower())
        {
            case "is equal to":
                isValid = temperature == benchmark;
                break;
            case "is greater than":
                isValid = temperature > benchmark;
                break;
            case "is greater than or equal to":
                isValid = temperature >= benchmark;
                break;
            case "is less than":
                isValid = temperature < benchmark;
                break;
            case "is less than or equal to":
                isValid = temperature <= benchmark;
                break;
            case "is not equal to":
                isValid = temperature != benchmark;
                break;
            default:
                isValid = false;
                break;
        }

        return isValid;
    }

    private string GetTemperature()
    {
        VisitorDataSet.VisitsRow visit = Sitecore.Analytics.Tracker.CurrentVisit;
        double latitude = visit.Latitude;
        double longitude = visit.Longitude;

        System.Device.Location.GeoCoordinate currentGeoCoordinate = new System.Device.Location.GeoCoordinate(latitude, longitude);

        IWeatherService weatherService = new WeatherServiceBuienradar();

        string temperature = weatherService.GetCurrentTemperatureCelsius(currentGeoCoordinate);

        return temperature;
    }

    protected override string GetColumnValue(VisitorDataSet.VisitsRow visit)
    {
        return string.Empty;
    }
}

Now the Marketeer is able to add rules based on the temperature in the visitor’s location! The Marketeer just makes use of our Condition to target a specific temperature range. For example, if it were a car website, the Marketeer could change the DataSource of the Conditional Rendering to “Porsche 911 Convertible”.

Porsche Convertible Rule
We can add more Weather Conditions, for example Rainfall, Humidity and Atmospheric Pressure. Just use the WeatherService class, and let it retrieve these properties from your weather data. If you add more conditions, you also enable the Marketeer to combine the conditions into more and more specific rules, and also more and more specific content targeting!

The downside to this story is that Sitecore DMS uses the IP Address to locate the visitor. This is not the most accurate method to determine the exact location of the visitor, because the internet providers often use the city of the company as the location of the IP addresses. The accuracy of this method fluctuates between 50 and 80 %, but weather conditions can be much more localized. So it could be worthwhile to look for other methods of GeoLocations, and use that in conjunction with the WeatherService class.

Advertisements