xConnect tutorial #1: Create a contact and an interaction

The following tutorial assumes that you have installed the complete Sitecore Experience Platform, including xConnect and the xDB.

In this tutorial you will:

  • Create a contact with a known identifier

  • Create an interaction with a single event

  1. Open Visual Studio 2015 (run as administrator).

  2. Create a new Console Application as shown:

    create-console1.png
  3. Add the following references:

    • Sitecore.XConnect.dll

    • Sitecore.XConnect.Client.dll

    • Sitecore.XConnect.Collection.Model.dll

    • Sitecore.Xdb.Common.Web.dll

    • Microsoft.Extensions.Configuration.Abstractions.dll

    • System.Interactive.Async.Providers.dll

    • Sitecore.Framework.Conditions.dll

    • Newtonsoft.Json.dll

    • Sitecore.XConnect.Search.dll

    • System.Net.Http.Formatting.dll

  4. Paste the following code sample into the Program.cs file:

    Note

    You can find the client certificate thumbprint in the C:\>PathToxConnect>\App_Config\AppSettings.config configuration file.

    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.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)
            {
                CertificateWebRequestHandlerModifierOptions options =
                CertificateWebRequestHandlerModifierOptions.Parse("StoreName=My;StoreLocation=LocalMachine;FindType=FindByThumbprint;FindValue=15E6693B0AECB63DE57D991EC363CA462DC52432");
    
                var certificateModifier = new CertificateWebRequestHandlerModifier(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
                {
                    await 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
                    {
    
                    }
                    catch (XdbExecutionException ex)
                    {
                        // Deal with exception
                    }
                }
            }
        }
    }
    
  5. Replace the following lines in the code snippet above with the host name of your xConnect instance and your client certificate thumbprint:

    • CertificateWebRequestHandlerModifierOptions.Parse("StoreName=My;StoreLocation=LocalMachine;FindType=FindByThumbprint;FindValue=15E6693B0AECB63DE57D991EC363CA462DC52432");

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

  6. Press F5 to run the console - if the configuration initializes successfully, the console application will print xConnect:

    console-works1.png
  7. Create and submit a contact with a known identifier as demonstrated in the try...catch block in the following sample:

    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(" ");
    
                CertificateWebRequestHandlerModifierOptions options =
                CertificateWebRequestHandlerModifierOptions.Parse("StoreName=My;StoreLocation=LocalMachine;FindType=FindByThumbprint;FindValue=15E6693B0AECB63DE57D991EC363CA462DC52432");
    
                var certificateModifier = new CertificateWebRequestHandlerModifier(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
                {
                    await cfg.InitializeAsync(); // 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
                    {
                        // 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);
    
                        client.AddContact(knownContact);
    
                        // 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
                    }
                }
            }
        }
    }
    
  8. Amend the code in the try...catch block as shown below, to create an interaction with a single event - in this example, a goal. Be aware of the following:

    • All events (including goals and outcomes) must be instantiated with a definition ID - definitions are created in Sitecore and deployed to the Reference Data Service. xConnect is not aware of these definitions and will let you pass in a random GUID that does not represent a definition. You are responsible for keeping your data clean.

    • All interactions require a channel GUID - again, these are defined in Sitecore and again, xConnect will allow you to pass in a random GUID.

      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(" ");
      
                  CertificateWebRequestHandlerModifierOptions options =
                  CertificateWebRequestHandlerModifierOptions.Parse("StoreName=My;StoreLocation=LocalMachine;FindType=FindByThumbprint;FindValue=15E6693B0AECB63DE57D991EC363CA462DC52432");
      
                  var certificateModifier = new CertificateWebRequestHandlerModifier(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
                  {
                      await cfg.InitializeAsync(); // 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);
      
                          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
                      }
      
                  }
              }
          }
      }
      
  9. Press F5 to run the console - if the configuration initializes successfully, notice that two operations are now being executed - one to add the contact and another to add the interaction:

    console-works-21.png