Custom xDB Contact FACETS

In SiteCore xDB, if you want to extend contact attributes with your own organization specific data then you can create custom contact facets.

A Facet is a group of hierarchically organized related attibutes that describe certain aspect of a Contact.

For example, say you are a Pictures product company and you want to collect additional information about customers as they browse your website and you want to track a custom and unique identity like MediaName as well as a MediaURL property for each of your customers. These two pieces of information are related into a collection called “Marketing Analytics Data”. This is what we say Sitecore xDB Facet.

A contact is made up of facets. Here are all the facets Sitecore uses (you will find the facets in \App_Config\Include\Sitecore.Analytics.Model.Config):

<facets>
<facet name=”Personal” contract=”Sitecore.Analytics.Model.Entities.IContactPersonalInfo, Sitecore.Analytics.Model” />

<facet name=”Addresses” contract=”Sitecore.Analytics.Model.Entities.IContactAddresses, Sitecore.Analytics.Model” />

<facet name=”Emails” contract=”Sitecore.Analytics.Model.Entities.IContactEmailAddresses, Sitecore.Analytics.Model” />

<facet name=”Phone Numbers” contract=”Sitecore.Analytics.Model.Entities.IContactPhoneNumbers, Sitecore.Analytics.Model” />

<facet name=”Picture” contract=”Sitecore.Analytics.Model.Entities.IContactPicture, Sitecore.Analytics.Model” />

<facet name=”Communication Profile” contract=”Sitecore.Analytics.Model.Entities.IContactCommunicationProfile, Sitecore.Analytics.Model” />

<facet name=”Preferences” contract=”Sitecore.Analytics.Model.Entities.IContactPreferences, Sitecore.Analytics.Model” />

</facets>

In this example I will add facet that consists of MediaName and MediaURL of type strings, I will call  it “MediaDownloads” facet – this is my custom facet.

Follow below mentioned Steps to create custom Facets:

Step1 :  The “MediaDownloads” is a Facet, the list below consists of Elements. So I need to create a IFacet interface and a IElement interface.

using Sitecore.Analytics.Model.Framework;

public interface IMediaElement : IElement
{
string MediaName { get; set; }
string MediaURL { get; set; }
}

public interface IMediaFacet: IFacet
{
IElementCollection<IMediaElement> Downloads { get; }

}

Step2 : Now, we need to create concrete classes implementing IMediaFacet and IMediaElement:

Below is MediaFacets concrete class:

[Serializable]
public class MediaFacet : Facet, IMediaFacet
{
private const string DOWNLOADS = “Downloads”;
private const string UPLOADS = “Uploads”;

public IElementCollection<IMediaElement> Downloads
{
get { return GetCollection<IMediaElement>(DOWNLOADS); }
}

public IElementCollection<IMediaElement> Uploads
{
get { return GetCollection<IMediaElement>(UPLOADS); }
}

public MediaFacet()
{
EnsureCollection<IMediaElement>(DOWNLOADS);
EnsureCollection<IMediaElement>(UPLOADS);
}

}

Below is the MediaElement concrete class:

[Serializable]
public class MediaElement : Element, IMediaElement
{
private const string MEDIANAME = “MediaName”;
private const string MEDIAURL = “MediaURL”;

public string MediaName
{
get
{
return GetAttribute<string>(MEDIANAME);
}
set
{
this.SetAttribute(MEDIANAME, value);
}
}

public string MediaURL
{
get {
return GetAttribute<string>(MEDIAURL);
}
set
{
this.SetAttribute(MEDIAURL, value);
}
}

public MediaElement()
{
EnsureAttribute<string>(MEDIANAME);
EnsureAttribute<string>(MEDIAURL);
}

Getting and setting properties are done using GetAttribute and SetAttribute methods retrieved from Sitecore.Analytics.Model.Framework.Element and Sitecore.Analytics.Model.Framework.Facet.

Step 3: Register Facet in Sitecore configuration file that includes Elements as shown below :

<model>
<elements>
<element patch:after=”element[@interface=’Sitecore.Analytics.Model.Entities.IContactPreferences, Sitecore.Analytics.Model’]” interface=”AppWeb.Controllers.Renderers.Composite.IMediaElement, AppWeb” implementation=”AppWeb.Controllers.Renderers.Composite.MediaElement, AppWeb”>
<element patch:after=”element[@interface=’Sitecore.Analytics.Model.Entities.IContactPreferences, Sitecore.Analytics.Model’]” interface=”AppWeb.Controllers.Renderers.Composite.IMediaFacet, AppWeb” implementation=”AppWeb.Controllers.Renderers.Composite.MediaFacet, AppWeb”></element>
</elements>
<entities>
<contact>
<facets>
<facet patch:after=”facet[@name=’Preferences’]” name=”MediaDownloads” contract=”AppWeb.Controllers.Renderers.Composite.IMediaFacet, AppWeb”></facet>
</facets>
</contact>
</entities>
</model>

So as you can see, both my interfaces are defined in <elements/>. The <elements/> describes the implementation of the interface.

The facet is defined in <facets/> with a unique name. This unique name is the name you use to find the facet when you need to access it.

Validate Your configuration by checking /sitecore/admin/showconfig.aspx

Step 4:

var mediaDownloads = Tracker.Current.Contact.GetFacet<IMediaFacet>(“MediaDownloads”);
var download = mediaDownloads.Downloads.Create();
download.MediaName = “Sukesh”;
download.MediaURL = “https://google.com&#8221;;

Notice the contact.GetFacet<>() method. Here you specify the name of the facet you defined in the <facets/> section of the config file.

Remember that facets are not written to MongoDB before your session ends.

Below the data that gets stored in Mongo DB for Facets:

CustomFacets