Blog Details

SEO best practices

Recently, I was working in a business requirement where I had to capture customer interactions on product purchase and store it in XConnect. In this article I am going to explain step by step from creation,configuration and deployment of custom contact facade to save data in Xconnect.

Before starting I must thank Sitecore for the detailed documentation on XConnect (https://doc.sitecore.com/developers/90/sitecore-experience-platform/en/the-xconnect-model.html). Please refer the link for more in depth knowledge.

By default xConnect ships a number of built-in facets. These facets are located in the Sitecore.XConnect.Collection.Model namespace(e.g, PersonalInformation,EmailAddressList,PhoneNumberList etc). We can use these facade without any custom coding and save/retrieve data from it.However,as we need to customize it, let's  segregate the work into these sub modules -

1. Create a Facet class :

This is the actual model of the attributes we are going to store.As a recommended practice we should not store huge information in a contact facade.However,as for this article I am storing all related informations that I am going to use in future.

[FacetKey(DefaultFacetKey)]
public class PurchasedProducts : Facet
{
public const string DefaultFacetKey = "ProductInfo";
public List<PurchasedProduct> Products { get; set; }
}

public class PurchasedProduct
{
public string ProductID { get; set; }
public string ProductName { get; set; }
public string ProductCatagory { get; set; }
public string ProductCatagoryId { get; set; }
}

The [FacetKey] attribute is to define a default facet key. Default facet keys will be used in the xConnect Client API.

2. Create a custom model :

Let’s define the new facet in our collection model using the .DefineFacet() method.

public class PurchasedProductModel
{
public static XdbModel Model { get; } = PurchasedProductModel.BuildModel();
private static XdbModel BuildModel()
{
XdbModelBuilder modelBuilder = new XdbModelBuilder(“PurchasedProductModel”, new XdbModelVersion(0, 1));
modelBuilder.ReferenceModel(Sitecore.XConnect.Collection.Model.CollectionModel.Model);
modelBuilder.DefineFacet<Contact, PurchasedProducts>(PurchasedProducts.DefaultFacetKey);
return modelBuilder.BuildModel();
}
}

3. Serialize this model to JSON :

Model deployment is a manual process that involves copying a JSON representation of a model to all instances of xConnect. I have created a console application to serialize the xConnect model.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Sitecore.XConnect.Serialization;
namespace SerializeCustomModels
{
class Program {
static void Main(string[] args) {
var model = SC91.Foundation.MACustomPredicate.CustomFacets.PurchasedProductModel.Model;
var serializedModel = Sitecore.XConnect.Serialization.XdbModelWriter.Serialize(model);
string newFilePath = string.Concat(@"f:\serialization\", model.FullName , ".json");
File.WriteAllText(newFilePath, serializedModel);
Console.WriteLine(“Please find the model here: ” + newFilePath);
Console.ReadKey();
}}}

4. Deploy the custom model to the xConnect and Marketing Automation.

We need to copy the serialized json file to the below places –

> C:\inetpub\wwwroot\SC91.xconnect\App_data\Models

> C:\inetpub\wwwroot\SC91.xconnect\App_data\jobs\continuous\IndexWorker\ App_data\Models

5. Create a config patch and deploy the model in to Marketing Automation Engine.

> Copy our model DLL to the root of the Marketing Automation Engine (C:\inetpub\wwwroot\SC91.xconnect\App_data\jobs\continuous\AutomationEngine)

> Create a configuration file named sc.Sample.CustomModel.xml in C:\inetpub\wwwroot\SC91.xconnect\App_data\jobs\ continuous\AutomationEngine\App_Data\Config\sitecore.

The file name must start with sc and end with .xml.

<Settings>
<Sitecore>
<XConnect>
<Services>
<XConnect.Client.Configuration>
<Options>
<Models>
<PurchasedProductModel>
<TypeName>SC91.Foundation.MACustomPredicate.CustomFacets.PurchasedProductModel,SC91.Foundation.MACustomPredicate</TypeName>
</PurchasedProductModel>
</Models>
</Options>
</XConnect.Client.Configuration>
</Services>
</XConnect>
</Sitecore>
</Settings>

6. Create a config patch and deploy the model to our Sitecore instance.

> Copy the model DLL into the bin directory of your core Sitecore instance(C:\inetpub\wwwroot\SC91.sc\bin).

> Patch our model class into C:\inetpub\wwwroot\SC91.sc\App_Config\Sitecore\XConnect.Client.Configuration \Sitecore.XConnect.Client.config by creating an XML config named z.CustomPredicate.XConnect.Client.config :

<configuration xmlns:patch=”http://www.sitecore.net/xmlconfig/”>
<sitecore>
<xconnect>
<runtime type=”Sitecore.XConnect.Client.Configuration.RuntimeModelConfiguration,Sitecore.XConnect.Client.Configuration”>
<schemas hint=”list:AddModelConfiguration”>
<schema name=”PurchasedProductModel” type=”Sitecore.XConnect.Client.Configuration.StaticModelConfiguration,Sitecore.XConnect.Client.Configuration” patch:after=”schema[@name ='collectionmodel']”>
<param desc=”modeltype”>SC91.Foundation.MACustomPredicate.CustomFacets.PurchasedProductModel,SC91.Foundation.MACustomPredicate</param>
</schema>
</schemas>
</runtime>
</xconnect>
</sitecore>
</configuration>

7. Use the xConnect Client API to populate the contact facet

Now let’s quickly understand the following keywords :
A contact,it’s an individual who interacts with or may potentially interact with your organization. Contacts are represented by the Sitecore.XConnect.Contact class, and are uniquely identified by ID (of type Guid) within the xDB. In my case I am using unique EmailID to identify individual contacts.
An Identifier is required to uniquely identify a contact to systems outside the xDB. A single contact can have multiple identifiers,so it can be used as per the requirements.

var identifier = new Sitecore.XConnect.ContactIdentifier[]{ new Sitecore.XConnect.ContactIdentifier(“checkout”, order.User.EmailAddress, ContactIdentifierType.Known)};

Alternatively,a new contact can be created by using Tracker(Contacts that have interacted with your website have a tracker identifier, which is created the first time a contact visits your website)

Sitecore.Analytics.Tracker.Current.Session.IdentifyAs(“checkout”, order.User.EmailAddress);

The consolidated code for adding facet in contact –

using (Sitecore.XConnect.Client.XConnectClient client = Sitecore.XConnect.Client.Configuration.SitecoreXConnectClientConfiguration.GetClient())
{
{
try {
Sitecore.Analytics.Tracker.Current.Session.IdentifyAs(“checkout”, order.User.EmailAddress);
Sitecore.XConnect.Contact contact = client.Get(new IdentifiedContactReference(“checkout”, order.User.EmailAddress), new ContactExpandOptions(PurchasedProducts.DefaultFacetKey));
if (contact.GetFacet(PurchasedProducts.DefaultFacetKey) == null) {
if (order.Cartlines != null && order.Cartlines.Count > 0) {
List tempList = new List();
foreach(var info in order.Cartlines) {
PurchasedProduct productInfoFacet = new PurchasedProduct()
{
ProductID = info.Product.ItemId,
ProductName = info.Product.Name,
ProductCatagory = info.Product.ParentCategory,
ProductCatagoryId = info.Product.ParentCategoryItemId,
};
tempList.Add(productInfoFacet);
}
PurchasedProducts products = new PurchasedProducts();
products.Products = tempList;
client.SetFacet(contact, PurchasedProducts.DefaultFacetKey, products);
client.Submit();
Sitecore.Diagnostics.Log.Info(“Product deatils captured in PurchasedProducts facet”, “XConnect – UpdateTrackingContact”);
}
}
}
catch (XdbExecutionException ex)
{
Sitecore.Diagnostics.Log.Error(“UpdateTrackingContact failed: “, ex.ToString());
}
}
}


Once it start executing we can see the information getting stored in DB.

SELECT [ContactId]
,[FacetKey]
,[LastModified]
,[ConcurrencyToken]
,[FacetData]
FROM [sc91_Xdb.Collection.Shard1].[xdb_collection].[ContactFacets]
ORDER BY [LastModified] desc


ContactFacets Table

Stay tuned for part two of this series, where we’ll talk about Marketing Automation and how we can use this facet information to create custom predicates and activities.

Please let me know your suggestion about this article or contact me for any further information on this.

Comments (0)

Leave a Reply