Create a custom contact facet

Last updated Wednesday, October 19, 2016 in Sitecore Experience Platform for Developer, Administrator
Keywords: Contacts, Development

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.

    Note

    The 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:

  1. 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 the IFacet interface. 

    The following example defines a contract for the Places facet.

    public 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; }
    }
  2. 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:

    float Longitude { get; set; }
  3. To add a child element, define a property with a getter only that returns the contract of the element in question.

    For example:

    ICoordinate Coordinate { get; }
  4. To add a dictionary or collection of child elements, define a property with a getter only. For example: 
    IElementDictionary<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: 
    this.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:

      [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);
        }
      }

    Note

    Make 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.

    Note

    Facets should be registered in the same way as all other elements.

    <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 as ICoordinate, IPlace, or IPlaces. 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: 
    <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 the GetFacet<TFacet>( string name ) method.

     IPlaces places = contact.GetFacet<IPlaces>( "Visited Places" );
Send feedback about the documentation to docsite@sitecore.net.