xConnect tutorial #2: Set contact and interaction facets

You need to complete xConnect tutorial #1 before starting this tutorial.

In the following tutorial you will:

  • Set facets on a new contact

  • Set facets on an interaction

Be aware of the following:

  • Default facets are listed in the collection model reference topic.

  • If a facet has any required properties, they must be passed in via the facet constructor. If the property is not in the constructor, it is not mandatory.

  1. Update the code from Tutorial #1. Populate the PersonalInformation facet in the "// Create a new contact with the identifier" section as shown:

    using Sitecore.XConnect;
    using Sitecore.XConnect.Client;
    using Sitecore.XConnect.Client.WebApi;
    using Sitecore.XConnect.Collection.Model;
    using Sitecore.XConnect.Schema;
    using Sitecore.Xdb.Common.Web;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Sitecore.Xdb.Common.Web;
    
    namespace Sitecore.Documentation
    {
        public class Program
        {
            private static void Main(string[] args)
            {
                MainAsync(args).ConfigureAwait(false).GetAwaiter().GetResult();
                Console.ForegroundColor = ConsoleColor.DarkGreen;
                Console.WriteLine("");
                Console.WriteLine("END OF PROGRAM.");
                Console.ReadKey();
            }
    
            private static async Task MainAsync(string[] args)
            {
                Console.WriteLine(" ");
    
                CertificateHttpClientHandlerModifierOptions options =
                CertificateHttpClientHandlerModifierOptions.Parse("StoreName=My;StoreLocation=LocalMachine;FindType=FindByThumbprint;FindValue=15E6693B0AECB63DE57D991EC363CA462DC52432");
    
                var certificateModifier = new CertificateHttpClientHandlerModifier(options);
    
                List<IHttpClientModifier> clientModifiers = new List<IHttpClientModifier>();
                var timeoutClientModifier = new TimeoutHttpClientModifier(new TimeSpan(0, 0, 20));
                clientModifiers.Add(timeoutClientModifier);
    
                var collectionClient = new CollectionWebApiClient(new Uri("https://xconnect/odata"), clientModifiers, new[] { certificateModifier });
                var searchClient = new SearchWebApiClient(new Uri("https://xconnect/odata"), clientModifiers, new[] { certificateModifier });
                var configurationClient = new ConfigurationWebApiClient(new Uri("https://xconnect/configuration"), clientModifiers, new[] { certificateModifier });
    
                var cfg = new XConnectClientConfiguration(
                    new XdbRuntimeModel(CollectionModel.Model), collectionClient, searchClient, configurationClient);
    
                try
                {
                    cfg.Initialize(); // cfg.InitializeAsync();
    
                    // Print xConnect if configuration is valid
                    var arr = new[]
                    {
                                @"            ______                                                       __     ",
                                @"           /      \                                                     |  \    ",
                                @" __    __ |  $$$$$$\  ______   _______   _______    ______    _______  _| $$_   ",
                                @"|  \  /  \| $$   \$$ /      \ |       \ |       \  /      \  /       \|   $$ \  ",
                                @"\$$\/  $$| $$      |  $$$$$$\| $$$$$$$\| $$$$$$$\|  $$$$$$\|  $$$$$$$ \$$$$$$   ",
                                @" >$$  $$ | $$   __ | $$  | $$| $$  | $$| $$  | $$| $$    $$| $$        | $$ __  ",
                                @" /  $$$$\ | $$__/  \| $$__/ $$| $$  | $$| $$  | $$| $$$$$$$$| $$_____   | $$|  \",
                                @"|  $$ \$$\ \$$    $$ \$$    $$| $$  | $$| $$  | $$ \$$     \ \$$     \   \$$  $$",
                                @" \$$   \$$  \$$$$$$   \$$$$$$  \$$   \$$ \$$   \$$  \$$$$$$$  \$$$$$$$    \$$$$ "
                            };
                    Console.WindowWidth = 160;
                    foreach (string line in arr)
                        Console.WriteLine(line);
    
                }
                catch (XdbModelConflictException ce)
                {
                    Console.WriteLine("ERROR:" + ce.Message);
                    return;
                }
    
                // Initialize a client using the validated configuration
                using (var client = new XConnectClient(cfg))
                {
                    try
                    {
                        var offlineGoal = Guid.Parse("ad8ab7fe-ab48-4ea9-a976-ae7a268ae2f0"); // "Watched demo" goal
                        var channelId = Guid.Parse("110cbf07-6b1a-4743-a398-6749acfcd7aa"); // "Other event" channel
    
                        // Identifier for a 'known' contact
                        var identifier = new ContactIdentifier[]
                        {
                                        new ContactIdentifier("twitter", "myrtlesitecore" + Guid.NewGuid().ToString("N"), ContactIdentifierType.Known)
                        };
    
                        // Print out the identifier that is going to be used
                        Console.WriteLine("Identifier:" + identifier[0].Identifier);
    
                        // Create a new contact with the identifier
                        Contact knownContact = new Contact(identifier);
    
                        PersonalInformation personalInfoFacet = new PersonalInformation();
    
                        personalInfoFacet.FirstName = "Myrtle";
                        personalInfoFacet.LastName = "McSitecore";
                        personalInfoFacet.JobTitle = "Programmer Writer";
    
                        client.SetFacet<PersonalInformation>(knownContact, PersonalInformation.DefaultFacetKey, personalInfoFacet);
    
                        client.AddContact(knownContact);
    
                        // Create a new interaction for that contact
                        Interaction interaction = new Interaction(knownContact, InteractionInitiator.Brand, channelId, "");
    
                        // Add events - all interactions must have at least one event
                        var xConnectEvent = new Goal(offlineGoal, DateTime.UtcNow);
                        interaction.Events.Add(xConnectEvent);
    
                        // Add the contact and interaction
                        client.AddInteraction(interaction);
    
                        // Submit contact and interaction - a total of two operations
                        await client.SubmitAsync();
    
                        // Get the last batch that was executed
                        var operations = client.LastBatch;
    
                        Console.WriteLine("RESULTS...");
    
                        // Loop through operations and check status
                        foreach (var operation in operations)
                        {
                            Console.WriteLine(operation.OperationType + operation.Target.GetType().ToString() + " Operation: " + operation.Status);
                        }
    
                        Console.ReadLine();
                    }
                    catch (XdbExecutionException ex)
                    {
                        // Deal with exception
                    }
                }
            }
        }
    }
    
  2. Press F5 to run the console. If the configuration initializes successfully, notice that three operations are now being executed - setting a facet is a separate operation from adding a contact:

    console-works-31.png
  3. Add a facet to the interaction as shown in the "// Add events" section below. An example of a built-in interaction facet is IpInfo, which is used in a tracking context.

    using Sitecore.XConnect;
    using Sitecore.XConnect.Client;
    using Sitecore.XConnect.Client.WebApi;
    using Sitecore.XConnect.Collection.Model;
    using Sitecore.XConnect.Schema;
    using Sitecore.Xdb.Common.Web;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Sitecore.Xdb.Common.Web;
    
    namespace Sitecore.Documentation
    {
        public class Program
        {
            private static void Main(string[] args)
            {
                MainAsync(args).ConfigureAwait(false).GetAwaiter().GetResult();
                Console.ForegroundColor = ConsoleColor.DarkGreen;
                Console.WriteLine("");
                Console.WriteLine("END OF PROGRAM.");
                Console.ReadKey();
            }
    
            private static async Task MainAsync(string[] args)
            {
                Console.WriteLine(" ");
    
                CertificateHttpClientHandlerModifierOptions options =
                CertificateHttpClientHandlerModifierOptions.Parse("StoreName=My;StoreLocation=LocalMachine;FindType=FindByThumbprint;FindValue=15E6693B0AECB63DE57D991EC363CA462DC52432");
    
                var certificateModifier = new CertificateHttpClientHandlerModifier(options);
    
                List<IHttpClientModifier> clientModifiers = new List<IHttpClientModifier>();
                var timeoutClientModifier = new TimeoutHttpClientModifier(new TimeSpan(0, 0, 20));
                clientModifiers.Add(timeoutClientModifier);
    
                var collectionClient = new CollectionWebApiClient(new Uri("https://xconnect/odata"), clientModifiers, new[] { certificateModifier });
                var searchClient = new SearchWebApiClient(new Uri("https://xconnect/odata"), clientModifiers, new[] { certificateModifier });
                var configurationClient = new ConfigurationWebApiClient(new Uri("https://xconnect/configuration"), clientModifiers, new[] { certificateModifier });
    
                var cfg = new XConnectClientConfiguration(
                    new XdbRuntimeModel(CollectionModel.Model), collectionClient, searchClient, configurationClient);
    
                try
                {
                    cfg.Initialize(); // cfg.InitializeAsync();
    
                    // Print xConnect if configuration is valid
                    var arr = new[]
                    {
                                @"            ______                                                       __     ",
                                @"           /      \                                                     |  \    ",
                                @" __    __ |  $$$$$$\  ______   _______   _______    ______    _______  _| $$_   ",
                                @"|  \  /  \| $$   \$$ /      \ |       \ |       \  /      \  /       \|   $$ \  ",
                                @"\$$\/  $$| $$      |  $$$$$$\| $$$$$$$\| $$$$$$$\|  $$$$$$\|  $$$$$$$ \$$$$$$   ",
                                @" >$$  $$ | $$   __ | $$  | $$| $$  | $$| $$  | $$| $$    $$| $$        | $$ __  ",
                                @" /  $$$$\ | $$__/  \| $$__/ $$| $$  | $$| $$  | $$| $$$$$$$$| $$_____   | $$|  \",
                                @"|  $$ \$$\ \$$    $$ \$$    $$| $$  | $$| $$  | $$ \$$     \ \$$     \   \$$  $$",
                                @" \$$   \$$  \$$$$$$   \$$$$$$  \$$   \$$ \$$   \$$  \$$$$$$$  \$$$$$$$    \$$$$ "
                            };
                    Console.WindowWidth = 160;
                    foreach (string line in arr)
                        Console.WriteLine(line);
    
                }
                catch (XdbModelConflictException ce)
                {
                    Console.WriteLine("ERROR:" + ce.Message);
                    return;
                }
    
                // Initialize a client using the validated configuration
                using (var client = new XConnectClient(cfg))
                {
                    try
                    {
                        var offlineGoal = Guid.Parse("ad8ab7fe-ab48-4ea9-a976-ae7a268ae2f0"); // "Watched demo" goal
                        var channelId = Guid.Parse("110cbf07-6b1a-4743-a398-6749acfcd7aa"); // "Other event" channel
    
                        // Identifier for a 'known' contact
                        var identifier = new ContactIdentifier[]
                        {
                                        new ContactIdentifier("twitter", "myrtlesitecore" + Guid.NewGuid().ToString("N"), ContactIdentifierType.Known)
                        };
    
                        // Print out the identifier that is going to be used
                        Console.WriteLine("Identifier:" + identifier[0].Identifier);
    
                        // Create a new contact with the identifier
                        Contact knownContact = new Contact(identifier);
    
                        PersonalInformation personalInfoFacet = new PersonalInformation();
    
                        personalInfoFacet.FirstName = "Myrtle";
                        personalInfoFacet.LastName = "McSitecore";
                        personalInfoFacet.JobTitle = "Programmer Writer";
    
                        client.SetFacet<PersonalInformation>(knownContact, PersonalInformation.DefaultFacetKey, personalInfoFacet);
    
                        client.AddContact(knownContact);
    
                        // Create a new interaction for that contact
                        Interaction interaction = new Interaction(knownContact, InteractionInitiator.Brand, channelId, "");
    
                        // Add events - all interactions must have at least one event
                        var xConnectEvent = new Goal(offlineGoal, DateTime.UtcNow);
                        interaction.Events.Add(xConnectEvent);
    
                        IpInfo ipInfo = new IpInfo("127.0.0.1");
    
                        ipInfo.BusinessName = "Home";
    
                        client.SetFacet<IpInfo>(interaction, IpInfo.DefaultFacetKey, ipInfo);
    
                        // Add the contact and interaction
                        client.AddInteraction(interaction);
    
                        // Submit contact and interaction - a total of two operations
                        await client.SubmitAsync();
    
                        // Get the last batch that was executed
                        var operations = client.LastBatch;
    
                        Console.WriteLine("RESULTS...");
    
                        // Loop through operations and check status
                        foreach (var operation in operations)
                        {
                            Console.WriteLine(operation.OperationType + operation.Target.GetType().ToString() + " Operation: " + operation.Status);
                        }
    
                        Console.ReadLine();
                    }
                    catch (XdbExecutionException ex)
                    {
                        // Deal with exception
                    }
                }
            }
        }
    }
    
  4. Press F5 to run the console - if the configuration initializes successfully, notice that four operations are now being executed - setting an interaction facet is a separate operation from creating an interaction.