Sitecore 8 Profiling Visitors for Beginners

The first step to deliver Personalisation for Anonymous Visitors of your web site is knowing your Visitors through the pages that they have visited…

Sitecore allow you to Profile your customers interests and behavior through the Profile framework where you can define the Profile Keys, Profile Cards and PatternMatch Cards.

In order to be able to fully benefit from this feature, you need to have XDB & Analytics enabled so that you can fully track your customer behavior.

pofiledefinition

profilecard

patterncard

As you can see, there is not always a clear classification, but often the definition touch multiple dimensions…

Once that you have defined your Profiles, it is time to TAG your content so that you can classify your visitors….

contenttagging

contentsegmentation

Once that you have defined your Profiles and Tagged your content you can easily identify your Anonymous visitors and start delivering personalized content based on the interest and behavior that you were able to track….

Some example of personalisation rules are reported here…

personalisationrule

personalisationrulepatterncards

 

 

Sitecore MVT for Beginners

MVT stands for multivariate testing if you are not familiar with the concept and you know A/B testing is more or less the same thing and in the case you have never heard about it, the principle behind it is to expose your web site visitors to multiple variations of the website content/functionalities to TEST  what is the variant that perform better.

It is important to specify that Sitecore generate the TESTS variation server side and it requires XDB enabled to track analytics and to help you to understand the more effective variant.

There are two way that Sitecore use to deliver MVT functionalities:

Component Based Testing

you can configure it either in Page Editor Mode either from the presentation details here you can specify all the variations that you want to expose your customers and it is very easy to configure as you can see in the following screenshots.

testcomp

mvtcomponents

Page Based Testing

From here you can control all the running Tests and you can see Sitecore suggestions for the Pages to test…

When you create a new Test you will be asked for the page to Test and the Variations of the page to test (you can either use different pages or create different versions of the same page)

You can than define:

  1. The Percentage of the traffic visiting the page to run the test
  2. The Success criteria of your test (eg. if the user is visiting more pages / increasing the engagement value or if the user is triggering a specific Goal/Event eg. conversion rate
  3. The Duration of your test (for how long you want to run the test)
  4. The confidence level, when do you want Sitecore to decide the winner of the test and serve automatically the winner of the test

Happy Testing!

ExperienceOptimisation.png

checkouttest

testdefinition

testwinner

Sitecore Behavior Personalisation InSession

One of the key selling point of Sitecore 8 compared to the other CMS products is the Personalisation Engine.

The definition of “Behavior Personalisation” should be self Explanatory, providing personalised content based on the behavior of the user….

InSession Personalisation DOES NOT REQUIRE XDB license and MONGODB capabilities. Most of the features are enabled also if you are running Sitecore in CMSONLY mode.

The main advantage of XDB comes from the power of Analytics data and it will give you the ability to personalised based on the historic interactions and behavior (eg. checking if the customer has visited the page within the previous visits to the web site, or if the customer has never triggered a specific goal.)

The way of delivering personalised content within Sitecore is common within the personalisation framework and as you would expect you would need to define within your presentation details your personalisation rules.

Within the personalisation engine there are several way to define visitors behavior:

  • Visit user visit a page, or check the entrypage of the journey

personalvisit

  • Goal / Event /Outcome user trigger a goal -Event -Outcome during the visit

PersonalGoal.PNG

  • Campaigns  user come from a campaign landing page/email or his journey qualify with a campaign

PersonalCampaign.PNG

  • Referrals/search keyword user come from a specific website or through a specific keyword

personalgooglesearch

 

 

Integrate AKAMAI with Sitecore to deliver GeoIP personalisation

As probably not everybody knows AKAMAI offer as well GEOIP resolution capabilities based on MaxMind database.

OOTB Sitecore offer GeoIP personalisation based on their cloud service that consume MaxMind database, Sitecore charge customers for this service and in case you are not using Akamai, this could be an easy and effective way to have GeoIP in place without writing any code but just paying for Sitecore GeoIP service.

Therefore if you are already using AKAMAI and Sitecore GeoIP personalisation you should consider following this route…

In order to get AKAMAI to deliver personalisation you need to enable Content Targeting via property manager obviously you need to ensure that Content Targeting is included within your AKAMAI contract.

https://community.akamai.com/community/web-performance/blog/2016/03/16/content-targeting-a-basic-introduction

the-world-in-flags-570x293

Once that you have this in place, you will simply get GeoIp information injected within your http header that should look like:

X-Akamai-Edgescape: georegion=263,country_code=US,region_code=MA,city=CAMBRIDGE,dma=50 6,pmsa=1120,areacode=617,county=MIDDLESEX,fips=25017,lat=42.3933,l ong=-71.1333,timezone=EST,zip=02138-02142+02238-02239,continent=NA ,throughput=vhigh,asnum=21399

In order to configure Sitecore to read the following header instead than calling the original service, it is recommended to implement your custom lookup provider. Implementing your custom lookup provider is fairly simple since you need to inherit from Sitecore.Analytics.Lookups.LookupProviderBase and override WhoIsInformation to read your information from the HttpHeader and return the information as within the whoIsInformation object.

using Sitecore.Analytics.Lookups;
using Sitecore.Configuration;
using Sitecore.Diagnostics;
using System;
using System.Web;
using System.Web.Hosting;

namespace xxx.Akamai.LookupProvider
{
    public class AkamaiGEoIpProvider : LookupProviderBase
    {
        public string ExtractValue(string keyName, string headerValue)
        {
            //ToDo: nice regex to Parse Value
        }

        public override WhoIsInformation GetInformationByIp(string ip)
        {

            WhoIsInformation information = new WhoIsInformation();
            var headerValue = Request.Headers["X-Akamai-Edgescape"];
            information.Country = ExtractValue("country_code", headerValue);
            information.PostalCode = ExtractValue("zip", headerValue);
            //etc etc to set all the value for the information object

            return information;
        }
    }
}

Once that you have implemented your lookup provider you would need to regiter within the web.config your own provider

 <lookupmanager>
        <patch:attribute name="defaultProvider">akamai</patch:attribute>
        <providers>
          <add name="akamai" patch:after="processor[@type='Sitecore.Analytics.Lookups.MaxMindProvider,Sitecore.Analytics']" type="xxx.Akamai.LookupProvider.AkamaiGEoIpProvider,xxx.AkamaiGeoIp">/>
</add></providers></lookupmanager>

Useful resources to consider when you implement a custom lookup provider are the following ones:

Sitecore GeoLiteProvider: https://github.com/craigtfromatl/Sitecore-GeoLite-Lookup-Provider

CircuitBreaker design pattern: http://www.redmoon.london/sitecore-ip-geolocation-service-resolving-geoip-information-on-the-first-request-using-circuit-breaker-design-pattern/

Akamai Edgescape Parser: https://github.com/madglory/edgescape-parser

Create and configure XDB Custom Facet

In this post I am describing the required steps to create a custom facet on XDB and how to use it to personalize the experience…

  • Create your Interface extending IFacet
using System;
using System.Linq;
using Sitecore.Analytics.Model.Framework;

namespace Testing.ContactFacets.Model
{
    public interface ICRMSegment : IFacet
    {
        string CRMSegmentId { get; set; }
    }
}
  • Implement your Custom Facet
namespace Testing.ContactFacets.Model
{
    public class CrmSegment : Facet, ICRMSegment
    {
        private const string FIELD_CRMSegmentId = "CRMSegmentId";
        public CrmSegment()
        {
            base.EnsureAttribute< string>(FIELD_EMPLOYEE_ID);
        }
        public string CRMSegmentId
        {
            get { return base.GetAttribute< string>(FIELD_CRMSegmentId ); }
            set { base.SetAttribute< string>(FIELD_CRMSegmentId , value); }
        }
    }
}
  • Register your Facet via config file
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <model>
      <elements>
        <element interface="Testing.ContactFacets.Model.ICRMSegment,XXX.AssemblyName " implementation="Testing.ContactFacets.Model.CrmSegment, XXX.AssemblyName" />
      </elements>
      <entities>
        <contact>
          <facets>
            <facet name="CRMSegment" contract="Testing.ContactFacets.Model.ICRMSegment, XXX.AssemblyName" />
          </facets>
        </contact>
      </entities>
    </model>
  </sitecore>
</configuration>

  • Create a new XDB Contact
@using Sitecore.Web;
@using Testing.ContactFacets.Model;
@using Sitecore.Analytics.Model.Entities;
@{
 Sitecore.Analytics.Tracker.Current.Session.Identify("stelio.dibello@xxxxx.com");
 var contact =  Sitecore.Analytics.Tracker.Current.Contact;
 var data = contact.GetFacet<ICRMSegment>("CRMSegment");
 data.CRMSegmentId = "BargainHunter";

var personalInfo = Sitecore.Analytics.Tracker.Current.Contact.GetFacet<Sitecore.Analytics.Model.Entities.IContactPersonalInfo>("Personal");

personalInfo.FirstName = "Stelio";
personalInfo.Surname = "Di Bello";
personalInfo.Gender="M";

var contactEmail =  Sitecore.Analytics.Tracker.Current.Contact.GetFacet<IContactEmailAddresses>("Emails");

            // this email to show in the Experience Profiles backend.
 if (!contactEmail.Entries.Contains("Home"))
    {
      contactEmail.Entries.Create("Home");
    }
            // set the email
  var email = contactEmail.Entries["Home"];
  email.SmtpAddress = "stelio.dibello@xxxxx.com";
 contactEmail.Preferred = "Home";
}

CRM data contact facet updated.

Contact ID: @contact.ContactId.ToString() /b>

Employee #: <b> @data.CRMSegmentId </b>

  • Personalize based on CRMSegmentId rule

 

  • crmsegmentpersonalisation

Sitecore 8 Personalisation rules for beginners

Probably most of you are already aware of what it means personalisation in Sitecore 8 but in case you have not heard about it, this post will give you a better idea of how Sitecore has implemented it…

Within Sitecore the easier way to deliver a Personalised experience is through Personalisation Rules at Rendering level.

The starting point is defining a page with one rendering and click on the Personalise button

personalisebutton

From here you will be able to select your rule:

rulesselector

Once that you have selected your rule, you will than be able to select the actions associated to the conditional rendering that could be setting a different datasource, or Hiding the rendering or displaying a different rendering

personalisecomponent

Sitecore 8 allows the Developer to customise Rules but OOTB it comes with the following rules to personalise your content:

Sitecore Rules are grouped in the following logical categories:

Campaigns: Condition based on the campaign defined, newsletter, landing page, etc
Channel: Condition based on the channel, web, mobile etc
Date: Condition based on the date & time of the visit
Device: Condition based on Device capability (it rely on NetBiscuit service charged separately)
GeoIp: Condition based on user geolocation (rely on Sitecore service based on MaxMind, charged separately
Outcomes: Condition based on the engagement plan status and outcomes triggered
Security: Condition based on user security context, eg.  is anonymous etc
Social : Conditions based on Social network information, in the case the user has a federated identity via social network can be used to personalised on the profile information
Visit: Condition based on the current visit (eg. goal / event, campaign, previous interactions, engagement value, search keyword etc)
Visitor: Condition based on previous interactions (require analytics to be enabled)

 

 

Trigger an Outcome Programmatically

As you probably already know, the main difference between an outcome and a goal, is the possibility to assign a monetary value to an outcome so that you can use it to get better reporting within your analytics and eventually to understand which paths/content converted better.

Outcomes can only be assigned programmatically, this snippet simulate a controller rendering that trigger the ProductPurchase Outcome.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Sitecore.Mvc;
using System.Web.Mvc;
using System.Web;
using Sitecore.Analytics.Outcome.Extensions;
using Sitecore.Analytics.Outcome.Model; 

public ActionResult PurchaseOutcome()
    {
        // Register an outcome
        //It will only be saved to the database on session end

        var id = Sitecore.Data.ID.NewID;
        var interactionId = Sitecore.Data.ID.NewID;
        var contactId = Sitecore.Data.ID.NewID;

       // definition item for Purchase Outcome
      var definitionId = new Sitecore.Data.ID("{9016E456-95CB-42E9-AD58-997D6D77AE83}");

        var outcome = new ContactOutcome(id, definitionId, contactId);
        outcome.MonetaryValue = 153;
        Sitecore.Analytics.Tracker.Current.RegisterContactOutcome(outcome);
        return Content("Outcome purchase 153");
    }

These are the references required:

referencesoutcome

And this is the Outcome definition:

outcome