Create a custom contact facet
In the Sitecore Experience Database (xDB), if you want to extend the contact with your own custom, organization-specific data, then you can create custom contact facets.
A facet is a group of hierarchically organized, related attributes that describe a certain aspect of a contact. Facets are the smallest unit of attributes that can be added or removed from a contact during configuration.
Custom contact facets can have the following characteristics:
-
Attributes – attributes are an element's subitems. For example, the Address element could contain attributes such as country, state, town or email address. Attributes can be strings, GUIDs, integers, or floating point numbers.
-
Elements – an element is a data structure that contains one or more members or attributes, such as a facet.
-
Dictionaries – A dictionary contains named elements. Each element in a dictionary is identified by a unique key.
NoteThe
IFacet
interface is a marker interface that enables you to identify the root of the element tree
To create a custom facet you need to:
Create a contract
To create a contract:
-
Create a contract to define the structure of elements or facets. The contract is the definition of what attributes you want the facet to be able to store and return. To define a contract for an element, implement an interface that extends the
IElement
interface. For facets, extend theIFacet
interface.The following example defines a contract for the
Places
facet.RequestResponsepublic interface ICoordinate : IElement { float Longitude { get; set; } float Latitude { get; set; } } public interface IPlace : IElement { string Description { get; set; } ICoordinate Coordinate { get; } } public interface IPlaces : IFacet { IElementDictionary<IPlace> Places { get; } }
-
To add a simple attribute such as an integer, a date-time, a GUID, a string, or a floating-point number, add a property with both a getter and a setter that returns the type you need.
For example:
RequestResponsefloat Longitude { get; set; }
-
To add a child element, define a property with a getter only that returns the contract of the element in question.
For example:
RequestResponseICoordinate Coordinate { get; }
-
To add a dictionary or collection of child elements, define a property with a getter only. For example:
RequestResponseIElementDictionary<ICoordinate> Coordinates { get; } IElementCollection<ICoordinate> Coordinates { get; }
Dictionaries and collections of simple attributes are not supported. For example, if you need a dictionary of integer values, you can define an element with a single integer attribute and use this element in the collection or dictionary as the examples in this section show.
Implement the contract
To implement the contract:
-
Register the attributes, collections, and dictionaries with the base class in the constructor using the following helper methods:
RequestResponsethis.EnsureAttribute<TValue>( string name ); this.EnsureElement<TElement>( string name ); this.EnsureDictionary<TElement>( string name ); this.EnsureCollection<TElement>( string name );
These methods ensure that the member is registered with the model. Implement the properties of the contract as shown below:
RequestResponse[Serializable] internal class Coordinate : Element, ICoordinate { private const string LONGITUDE = "Longitude"; private const string LATITUDE = "Latitude"; public float Longitude { get { return this.GetAttribute<float>( LONGITUDE ); } set { this.SetAttribute( LONGITUDE, value ); } } public float Latitude { get { return this.GetAttribute<float>( LATITUDE ); } set { this.SetAttribute( LATITUDE, value ); } } public Coordinate() { this.EnsureAttribute<float>(LONGITUDE); this.EnsureAttribute<float>(LATITUDE); } }
NoteMake sure the class is marked with the
[Serializable]
attribute. This attribute is required to ensure that instances of this class can be stored in shared session and in the submit queue.Do not add any additional code to this implementation. The implementation classes for this example have not yet been implemented.
Configure the system to use the new facet
Once you have defined and implemented the facet structure, you must configure Sitecore to use the new facet.
-
Open the
Sitecore.Analytics.Model.config
configuration file and register all elements. Elements should only be registered once even if they are used in multiple facets.NoteFacets should be registered in the same way as all other elements.
RequestResponse<model> <elements> <element interface="type" implementation="type" /> </element> </model>
In the
Sitecore.Analytics.Model.config
file, the interface attribute is the type defined in the contract the data model, such asICoordinate
,IPlace
, orIPlaces
. The implementation type is the actual implementation of the contract that is instantiated by Sitecore to hold the data in memory.
Update the model configuration
To update the model that you want to extend:
-
Locate the entity type to be extended and register the new facet:
RequestResponse<model> <entities> <entity> <facets> <facet name="name" contract="type" /> </facets> </entity> </entities> </model>
In this example, the node
<entity>
is replaced with the entity type that you are extending, for example,<contact>
. The name attribute is the name under which the facet is accessible on the contact model. This is the string value passed to theGetFacet<TFacet>( string name )
method.RequestResponseIPlaces places = contact.GetFacet<IPlaces>( "Visited Places" );