Saturday, March 11, 2017

Sitecore merging contacts with custom facets

This post is part 4 of a series, the introduction is available here and includes a table of contents, along with the full source code.

When there are two contact records in the xDB that are the same person, they can be merged. This will happen automatically when you identify a contact and can be called programatically when business logic dictates a merge. This also introduces the concept of the dying contact (the one being merged) and the surviving contact (the one being merged into).

Sitecore has a post which goes over the merge rules in detail, but custom contact facet data in particular will only copy over from the dying contact if the surviving contact has no data in that facet. It is however possible to create a custom pipeline that runs during a merge which can handle the custom contact facet merge to ensure data is brought across. Effectively you will have access in code to both contacts and can use custom logic to decide what to do with the data. It may be as simple as a full replacement, or you may need to decide on a field by field basis.

The pipeline

This is a simple example where we are effectively overwriting the customer data of the surviving contact and bringing in the product purchases. There would likely be a lot more rules around this copy in a real world example.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Sitecore.Analytics.Pipelines.MergeContacts;
using ContactFacet.Custom;

namespace ContactFacet.Pipeline
{
    public class MergeCustomData : MergeContactProcessor
    {
        public override void Process(MergeContactArgs args)
        {
            var dyingContactFacet = args.DyingContact.GetFacet<ICustomDataFacet>(CustomDataFacet.FacetName);
            var survivingContactFacet = args.SurvivingContact.GetFacet<ICustomDataFacet>(CustomDataFacet.FacetName);
            
            if (dyingContactFacet.IsEmpty)
            {
                return; // No data to merge
            }

            survivingContactFacet.CrmId = dyingContactFacet.CrmId; // Take over the CRM ID
            survivingContactFacet.ActiveCustomer = dyingContactFacet.ActiveCustomer; // Take over active customer flag

            //Copy over products
            if (dyingContactFacet.ProductPurchases != null && dyingContactFacet.ProductPurchases.Any())
            {
                foreach (var productPurcahse in dyingContactFacet.ProductPurchases)
                {
                    var newPurchase = survivingContactFacet.ProductPurchases.Create();
                    newPurchase.PurchaseDate = productPurcahse.PurchaseDate;
                    newPurchase.ProductId = productPurcahse.ProductId;
                }
            }
        }
    }
}

Configuration

<configuration>
  <sitecore>
    <pipelines>
      <mergeContacts>
        <processor type="ContactFacet.Pipeline.MergeCustomData" />
      </mergeContacts>
    </pipelines>
  </sitecore>
</configuration>

It's as simple is that. Part five: Personalization rules for contact facets, gives an example personalization rule that utilities the custom contact facet data.

No comments:

Post a Comment