1

I'm trying to make a custom contact facet and I followed the documentation of Sitecore 9.1 as shown in the code block below, which comes from https://doc.sitecore.com/users/91/sitecore-experience-platform/en/configure-the-import-contacts-wizard-to-include-custom-contact-facets.html.

There are some points I don't understand:

  1. The first parameter of mapping.GetValue("Emails_Others_Personal") what does it refer to? Is it the facet field in Sitecore or the field in the excel sheet?
  2. Others["Personal"] what does this refer to?

    public class ExtendedEmailFacetMapperSample : IFacetMapper
    {
        private readonly PreferredEmailFacetMapper mapper;
        // Decorate the existing PreferredEmailMapper
        public ExtendedEmailFacetMapperSample(
            PreferredEmailFacetMapper mapper)
        {
            this.mapper = mapper;
        }
    
        public MappingResult Map(
            string facetKey,
            Facet facet,
            ContactMappingInfo mappings,
            string[] data)
        {
            // Call the existing email mapper to map all the basic email fields
            var result = this.mapper.Map(facetKey, facet, mappings, data);
            var facetMappedResult = result as FacetMapped;
            if (facetMappedResult == null)
            {
                return result;
            }
            var partiallyMappedFacet = facetMappedResult.Facet as EmailAddressList;
            if (partiallyMappedFacet == null)
            {
                return result;
            }
            // Set Personal email
            var personalEmail = mappings.GetValue("Emails_Others_Personal", data);
            if (!string.IsNullOrWhiteSpace(personalEmail))
            {
                partiallyMappedFacet.Others["Personal"] = new EmailAddress(personalEmail, false);
            }
            // Set Work email
            var workEmail = mappings.GetValue("Emails_Others_Work", data);
            if (!string.IsNullOrWhiteSpace(workEmail))
            {
                partiallyMappedFacet.Others["Work"] = new EmailAddress(workEmail, false);
            }
            return result;
        }
    }
    
  • Can you paste your code instead of a screenshot of it? It's easier to help when you do. Read more meta.stackexchange.com/questions/22186/… – Marek Musielak Mar 4 at 13:52
  • I have attached the link of the code to the question. – Mariam Nasr Mar 4 at 14:37
  • 1
    For future reference, please make sure you only add 1 question per post, if you have multiple questions, just open multiple posts :) – Richard Seal Mar 5 at 14:13
6

The code you are referencing is part of the process that details how List Manager, or the Marketing Operations of Sitecore, handles mapping imported CSV data to facets on a contact. At least that's the documentation link that you provided. The documentation link describes a generic scenario where the purpose of this mapping facet is to map the Personal and Work Email Address elements of the CollectionModel.FacetKeys.AddressList facet with the data coming from the CSV column name Emails_Other_Personal and Emails_Other_Work.

The CollectionModel.FacetKeys.AddressList is a Facet of the EmailAddressList type. On this class, there is a Property exposed that is a dictionary based on a key and the value of the type EmailAddress.

In this example, we are adding to entries to the Others dictionary. Personal and Work email addresses.

The way the mapping feature works is actually via a little bit of brute force. In this example, the first thing we are doing is calling the overridden class object (in this case PreferredEmailFacetMapper the Out of the Box mapper. As the contact object is created and mapped, it attempts to map each facet against it's type. In this case, the mapper uses the Map() method to compare the Facetkey against the object record. If the key matches, it instantiates the object. If it doesn't, it returns null.

So, by calling the PreferredEmailFacetMapper, if this is the correct facet, we should get an object back, hence the first null check.

// Call the existing email mapper to map all the basic email fields
var result = this.mapper.Map(facetKey, facet, mappings, data);
var facetMappedResult = result as FacetMapped;
if (facetMappedResult == null)
{
  return result;
}

Next up, we try to instantiate the facetMappedResult as a facet of the EmailAddressList type, which is the out of the box type for the Email Address List portion of the contact facet. If by some strange reason, this isn't an Email Address List facet, we'll get a null so that we can return out of the process. Otherwise, we move along.

var partiallyMappedFacet = facetMappedResult.Facet as EmailAddressList;
if (partiallyMappedFacet == null)
{
  return result;
}

Now we have the correct objects, of the correct types, for our correct facet. We can now do the work we need to. In this case, the next piece of the puzzle is to get the Personal and Work email addresses from the CSV file for the current contact that we are importing. That's where mappings comes into play. GetValue takes the CSV column header of Email_Others_Personal and fetches the value from the data collection passed in.

If it's not null or empty, we then add the EmailAddress object to the Others Element Dictionary, using the key value of Personal (or Work respectively).

// Set Personal email
var personalEmail = mappings.GetValue("Emails_Others_Personal", data);
if (!string.IsNullOrWhiteSpace(personalEmail))
{
  partiallyMappedFacet.Others["Personal"] = new EmailAddress(personalEmail, false);
}
// Set Work email
var workEmail = mappings.GetValue("Emails_Others_Work", data);
if (!string.IsNullOrWhiteSpace(workEmail))
{
  partiallyMappedFacet.Others["Work"] = new EmailAddress(workEmail, false);
}

And viola! We're done.


BUT WAIT...

That's if you were trying to achieve this very specific task.

None of this has anything to do with creating a custom contact facet. In fact, this documentation page makes the assumption that you already have facets that you've created and are simply trying to add a mapping for a custom CSV import. No custom contact facets are being added here.

If you are trying to create a custom facet, and this documentation page confuses you, you may be looking for the documentation page that discusses creating the actual custom contact facet.

xConnect and Contact Facets

Sitecore provides a 5 Part Tutorial on xConnect which explains how to create custom facets, not just for contacts, but also interactions.

  1. Tutorial #1: Create a contact and an interaction
  2. Tutorial #2: Set contact and interaction facets
  3. Tutorial #3: Get contacts
  4. Tutorial #4: Search contacts and interactions
  5. Tutorial #5: Create custom facets and events

This looks like it's about xConnect. Did you say above that the code above references List Manager? This doesn't look like List Manager.

In Sitecore 9 and later, the introduction of xConnect has brought on some clarity (or confusion depending on your lens) on how xDB information is collected. xConnect has been developed to clearly define the role of Sitecore in creating and consuming xDB data. That means Sitecore is now just a client of xConnect. This also means that Contacts are a construct of xConnect (or really xDB and xConnect is just the service layer) which means if we need to make modifications to the model of a Contact, we have to tell xConnect about it. That's why this tutorial exists, in order to explain how to modify xConnect.

In the example stated in the question, Sitecore, or more specifically List Manager, is just a consumer of the contact and we are just mapping data to already established contact facets.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.