In this blog, I will discuss about synchronizing the data between Sitecore xDB and salesforce contacts using Sitecore Connect for Salesforce CRM 2.0. Sitecore uses data exchange framework to communicate with the CRMs such as salesforce and MS Dynamics. A contact created in xDB will be added as salesforce contact by running the pipeline batch in data exchange framework. Pipeline batch run series of pipelines in data exchange framework to send the contacts data onto the salesforce contacts.
- Read contacts from xConnect
- Process single contact from xConnect pipeline
- Read contact interactions from xConnect pipeline
- Process interactions from xConnect pipeline
- Process single event from xConnect pipeline
Note – This blog is written by using Sitecore 9.0 update 2, Sitecore Connect for Salesforce CRM 2.0.1. Other versions of Sitecore may have different approach of synchronization of data.
In the first step (Read contacts from xConnect), The default installation of Sitecore Connect for Salesforce CRM 2.0 will map the fields like Birthdate, Email Address, first name, Last Name, Salesforce Contact Id, Title and xConnect Contact Id which can be configured in Value mapping sets in Tenant branch settings.
So, the ask is to add a new field like address line 1, city, zip code along with the default contact xConnect fields provided by Sitecore connect. So, I have added a new mapping called City in the data mappings section of data exchange framework to see if the city field is being added from Sitecore xConnect contact to salesforce contact.Below is the screenshot of the field that needs to be migrated to salesforce.
To add a new field city to send to salesforce, we need to create a new value mapping using Data Access/Mapping/Value Mapping and populate the source accessors and Target Accessor. The source items for source accessors and Target accessors are located at /Sitecore/system/Data Exchange/Connect for Salesforce Tenant Branch/Data Access/Value Accessor Sets/Providers folder.
The source accessor where the city is stored in xConnect is in /sitecore/system/Data Exchange/Connect for Salesforce Tenant Branch/Data Access/Value Accessor Sets/Providers/xConnect/xConnect Contact Address/City on xConnect Address
The target accessor where the city data will be stored in salesforce is in /sitecore/system/Data Exchange/Connect for Salesforce Tenant Branch/Data Access/Value Accessor Sets/Providers/Salesforce/Salesforce Contact Fields/Mailing City on Salesforce Contact
After adding the above mappings, the field City should be exported to salesforce but it did not make to salesforce. So I tried to debug the source code by decompiling the sitecore.DataExchange.DataAccess dll, and the code in “dataexchange.dataaccess\mappings\sequentialmappingset.cs” is returning null at
ReadResult readResult1 = mapping.SourceAccessor.ValueReader.Read(source, dataAccessContext);
The above methods calls Read method of DataExchangeFramework.DataAccess\DataExchange.DataAccess\Readers\IndexerPropertyValueReader.cs where it tries to get the city property from GetIndexerProperty which is a reflection utility.
PropertyInfo indexerProperty = this.ReflectionUtil.GetIndexerProperty(source, this.Indexes);
So, for the above reason, the city field is not being added to the properties that are migrated to the salesforce contacts. This does not restrict us from migrating these fields such as city onto salesforce. Sitecore provides ability to extend the data readers by creating and extending the Data Readers.
To create a custom readers to read the data from sitecore or salesforce,Follow the process below
- Create a class library name “Demo.Salesforce.DataExchange.Readers”.
- Create a custom class AddressFieldConverter in namespace “Sitecore.Demo.Salesforce.DataExchange” and inherit IValueReader
- Add a method Read with output as ReadResult.
- Write the below custom code to read the xDB data from sitecore using xConnect API.
public ReadResult Read(object source, DataAccessContext context)
if (context == null)
throw new ArgumentNullException("context");
bool flag = false;
object value = null;
ContactModel contactModel = (ContactModel) source;
if(contactModel != null)
AddressList myFacetObject = (AddressList)contactModel.GetFacet(AddressList.DefaultFacetKey);
value = GetPropValue(myFacetObject.PreferredAddress, this.Indexes??.ToString());// myFacetObject.PreferredAddress?.GetType()?.GetProperty(this.Indexes??.ToString())?.GetValue(myFacetObject.PreferredAddress, null)?.ToString();
if(value != null)
flag = true;
return new ReadResult(DateTime.UtcNow)
ReadValue = value,
WasValueRead = flag
After creating custom reader in class library, we need to let the data exchange framework know about this classlibrary custom reader class we created.To do that,
- Navigate to /sitecore/system/Data Exchange/Connect for Salesforce Tenant Branch/Data Access/Value Readers/Providers/xConnect
- Create a new property value reader using template ‘/sitecore/templates/Data Exchange/Framework/Data Access/Value Readers/Property Value Reader’.
- Populate the Converter type field to ‘Demo.Salesforce.DataExchange.AddressFieldConverter, Demo.Salesforce.DataExchange.Readers’(Demo.Salesforce.DataExchange.Readers dll, AddressFieldConverter is the name of the class and Sitecore.Demo.Salesforce.DataExchange is namespace)
- Now, Navigate to Source Accessor of City Data mapping “/Sitecore/system/Data Exchange/Connect for Salesforce Tenant Branch/Data Access/Value Accessor Sets/Providers/xConnect/xConnect Contact Address/City on xConnect Address” and add the data reader created in previous step.
- Now the xConnect city will be read from the custom value reader created in the previous step and will be populated in salesforce contact when “xConnect Contacts to Salesforce Sync” pipeline batch is run. Below screenshot will show the field in salesforce.
The source code for the custom data reader to export data from xDB to salesforce or vice versa is available at https://github.com/ramakrishnaila/SitecoreSalesforceCustomReader
Happy coding and Sitecoring