Set contact facets

Important

Facets that are loaded into session can be edited but are not saved to xConnect on session end. You must use the xConnect Client API to update facets.

You must update a contact’s facets directly in xConnect using the xConnect Client API and manually update the copy of that facet that exists in session. The tracker does not lock contact data, which means that a contact with an ongoing session can still be updated by other systems. Holding a facet in session and submitting that facet to xConnect on session end could result in a conflict if a more recent version of that facet is available.

This topic describes how to set facets for anonymous and known contacts, and how to update the the version of the facet that has been loaded into session.

Setting an new contact’s facets

In order to set facets of a new anonymous contact that has not yet been saved to xConnect, you must first save the contact. To set facets for an anonymous contact:

  1. If Sitecore.Analytics.Tracker.Current.Contact.IsNew is true, save the contact by calling contactManager.SaveContactToCollection. A contact must exist in xConnect before it can be updated.
  2. Build a tracker identifier from the contact’s tracker ID and a fixed source that is used exclusively by the tracker. This identifier can be used to retrieve the contact.
  3. Use the tracker identifier to retrieve the contact using xConnect Client API.
  4. Update facets and submit to xConnect - handle any conflict errors that occur.

The following example demonstrates how to save an anonymous contact and set the PersonalInformation facet:

using Sitecore.Analytics.Model;
using Sitecore.Analytics.Model.Entities;
using Sitecore.XConnect;
using Sitecore.XConnect.Client;
using Sitecore.XConnect.Collection.Model;

namespace Documentation
{
    public class TrackAnonymousContacts
    {
        public void Example()
        {
            if (Sitecore.Analytics.Tracker.Current.Contact.IsNew)
            {
                var manager = Sitecore.Configuration.Factory.CreateObject("tracking/contactManager", true) as Sitecore.Analytics.Tracking.ContactManager;

                if (manager != null)
                {
                    // Save contact to xConnect; at this point, a contact has an anonymous
                    // TRACKER IDENTIFIER, which follows a specific format. Do not use the contactId overload
                    // and make sure you set the ContactSaveMode as demonstrated
                    Sitecore.Analytics.Tracker.Current.Contact.ContactSaveMode = ContactSaveMode.AlwaysSave;
                    manager.SaveContactToCollectionDb(Sitecore.Analytics.Tracker.Current.Contact);

                    // Now that the contact is saved, you can retrieve it using the tracker identifier
                    // NOTE: Sitecore.Analytics.XConnect.DataAccess.Constants.IdentifierSource is marked internal in 9.0 Initial and cannot be used. If you are using 9.0 Initial, pass "xDB.Tracker" in as a string.
                    var trackerIdentifier = new IdentifiedContactReference(Sitecore.Analytics.XConnect.DataAccess.Constants.IdentifierSource, Sitecore.Analytics.Tracker.Current.Contact.ContactId.ToString("N"));

                    // Get contact from xConnect, update and save the facet
                    using (XConnectClient client = Sitecore.XConnect.Client.Configuration.SitecoreXConnectClientConfiguration.GetClient())
                    {
                        try
                        {
                            var contact = client.Get<Contact>(trackerIdentifier, new Sitecore.XConnect.ContactExpandOptions());

                            if (contact != null)
                            {
                                client.SetFacet<PersonalInformation>(contact, PersonalInformation.DefaultFacetKey, new PersonalInformation()
                                {
                                    FirstName = "Myrtle" // Replace with real input source
                                });

                                client.Submit();

                                // Remove contact data from shared session state - contact will be re-loaded
                                // during subsequent request with updated facets
                                manager.RemoveFromSession(Sitecore.Analytics.Tracker.Current.Contact.ContactId);
                                Sitecore.Analytics.Tracker.Current.Session.Contact = manager.LoadContact(Sitecore.Analytics.Tracker.Current.Contact.ContactId);
                            }
                        }
                        catch (XdbExecutionException ex)
                        {
                            // Manage conflicts / exceptions
                        }
                    }
                }
            }

        }
    }
}

Important

You must use contactManager.SaveContactToCollection to save contacts that do not yet exist in xConnct before setting any facets. Do not manually add the contact to xConnect using .AddContact. This bypasses the tracker and affects contact merge functionality.

Setting an existing contact’s facets

If a contact is known, it already exists in xConnect. Use the first available identifier to update the contact using the xConnect Client API as shown:

using Sitecore.Analytics.Model;
using Sitecore.Analytics.Model.Entities;
using Sitecore.XConnect;
using Sitecore.XConnect.Client;
using Sitecore.XConnect.Collection.Model;
using System.Linq;

namespace Documentation
{
    public class TrackKnownContacts
    {
        public void Example()
        {
            var manager = Sitecore.Configuration.Factory.CreateObject("tracking/contactManager", true) as Sitecore.Analytics.Tracking.ContactManager;

            if (!Sitecore.Analytics.Tracker.Current.Contact.IsNew)
            {
                var anyIdentifier = Sitecore.Analytics.Tracker.Current.Contact.Identifiers.FirstOrDefault();

                // Get contact from xConnect, update and save the facet
                using (XConnectClient client = Sitecore.XConnect.Client.Configuration.SitecoreXConnectClientConfiguration.GetClient())
                {
                    try
                    {
                        var contact = client.Get<Contact>(new IdentifiedContactReference(anyIdentifier.Source, anyIdentifier.Identifier), new Sitecore.XConnect.ContactExpandOptions(PersonalInformation.DefaultFacetKey));

                        if (contact != null)
                        {
                            if (contact.Personal() != null)
                            {
                                contact.Personal().FirstName = "Myrtle";

                               client.SetFacet<PersonalInformation>(contact, "MyFacetKey", contact.Personal());
                            }
                            else
                            {
                                client.SetFacet<PersonalInformation>(contact, "MyFacetKey", new PersonalInformation()
                                {
                                    FirstName = "Myrtle"
                                });
                            }

                            client.Submit();

                            // Remove contact data from shared session state - contact will be re-loaded
                            // during subsequent request with updated facets
                            manager.RemoveFromSession(Sitecore.Analytics.Tracker.Current.Contact.ContactId);
                            Sitecore.Analytics.Tracker.Current.Session.Contact = manager.LoadContact(Sitecore.Analytics.Tracker.Current.Contact.ContactId);
                        }
                    }
                    catch (XdbExecutionException ex)
                    {
                        // Manage conflicts / exceptions
                    }
                }
            }
        }
    }
}

Re-loading contact data

Contact data that has been cached in shared session state is not automatically updated when you submit changes to xConnect. From 9.0 Update-1, you can reload contact data by removing the contact from shared session state:

manager.RemoveFromSession(Sitecore.Analytics.Tracker.Current.Contact.ContactId); // Use tracker ID, not xConnect ID
Sitecore.Analytics.Tracker.Current.Session.Contact = manager.LoadContact(Sitecore.Analytics.Tracker.Current.Contact.ContactId);

The contact and its facets will be reloaded into shared session state during the next request. The RemoveFromSession() method is only available in 9.0 Update-1 onwards.

If you are using 9.0 Initial Release or do not wish to reload the contact from xConnect, you must manually updated the cached facet values. The following example demonstrates how to manually update a contact’s first name in session:

// Update legacy facet
var personalInfoTrackerFacet = Sitecore.Analytics.Tracker.Current.Contact.GetFacet<IContactPersonalInfo>("Personal");
personalInfoTrackerFacet.FirstName = "Myrtle"; // replace with real input source

// Update xConnect facet
var xConnectFacet = Sitecore.Analytics.Tracker.Current.Contact.GetFacet<Sitecore.Analytics.XConnect.Facets.IXConnectFacets>("XConnectFacets");

var personalInfoXConnectFacet = xConnectFacet.Facets[PersonalInformation.DefaultFacetKey] as PersonalInformation;
personalInfoXConnectFacet.FirstName = "Myrtle"; // Replace with real input source

Note

Custom facets are only loaded into IXConnectFacets and do not need to be updated anywhere else in the tracker. Some legacy facets must be updated in two locations - see table in Accessing facets in session for more information.