We recently completed a project with a set of nonprofit organizations who had won a grant award together to conduct a workforce training program. One organization - let’s call them Screening Pittsburgh (SP) - was primarily responsible for recruiting and screening candidates for the training program, and the other organization - let’s call them Training Pittsburgh (TP) - was primarily responsible for ensuring that all screened candidates were eligible, and for conducting the training itself. Understandably, SP and TP wanted us to help them share data between their systems, and so we decided to move forward with configuring Salesforce to Salesforce. We learned some interesting lessons along the way (after discovering some of the challenges with Salesforce to Salesforce), and wanted to share some of those lessons with you:
The primary objects which were shared were the standard Leads object (which tracked training program candidates) and Contacts (which tracked current and past students), as well as two related custom objects:
- The Careers object tracked a Lead’s job history, with one Career record for each previous position.
- The Screenings object tracked a Lead’s process of becoming a part of the training program. Each Lead had to pass a set of 5 assessments, including a drug test and an interview, in order to be eligible for training. Thus, the Screenings object had 5 record types, one for each type of assessment. A Lead would be ready for conversion (i.e., the candidate would be ready for the class) when they had all 5 screening records, with passes.
We quickly found that publishing and subscribing to our standard objects via Salesforce to Salesforce was fairly straightforward. We followed the introductory Salesforce to Salesforce documentation as a guideline to turn on the connection, to select our objects and fields to share, and used the auto-mapping tool as much as possible. These steps all worked as expected. The picture below displays the Salesforce to Salesforce field-mapping screen; whenever you subscribe to objects that were published from your connection instance, you’ll see this screen and can specify which incoming fields map to which of your fields. The auto-mapping tool automatically sets the mapping based upon matching field names.
However, we realized that our custom objects, which had lookup relationships to a Lead record, were being shared via the external connection, but their link to an associated Lead would not be maintained. For example, let’s say that SP was tracking the Career record “Mechanic” for the Lead record “Joe Candidate.” In the SP system, there would be a lookup relationship between “Mechanic” and “Joe Candidate.” SP shared the Lead and the Career record with TP. In TP’s system, both the Lead and Career record would exist - but the lookup field would be blank, so there would be no relationship. Further, we realized that our custom object record types weren’t being retained during external sharing; for example, SP would create a “Drug Test” Screening record, and it would be displayed in TP’s system as an “Initial Contact” Screening record (note: “Initial Contact” was their default record type for this object). Obviously, we needed to resolve both of these issues in order for Salesforce to Salesforce to be a truly viable option for our clients.
Here are the steps we took to ensure that the lookup relationships between our custom objects (i.e., Career, Screening) and standard objects were retained through the external sharing process. By the way, we did everything listed below in both instances of Salesforce - Screening Pittsburgh’s, and Training Pittsburgh’s - so that sharing could occur in either direction:
1. We created a Lead External ID field on the Lead object that was an autonumber. Since we were creating an autonumber Lead External ID field in both systems (SP and TP), we had to make the starting number for the autonumbering “0” in one system, and high enough in the other system to ensure that they would never experience a duplicate. In other words, an autonumber field mapped to an autonumber field in another instance via Salesforce to Salesforce cannot be guaranteed to be unique across the two instances, nor can we “set” an autonumber field value via a tool such as Salesforce to Salesforce mapping or a workflow field update, etc. Thus, each instance had its own unique Lead External ID autonumber field, with a significantly different starting number, so that every Lead in both systems had a unique external ID.
2. We created a Lead External ID Num field on the Lead object that was a read-only text field to capture the Lead External ID. We had to do that in order to retain the correct value of the auto-numbered external ID during sharing. Salesforce to Salesforce will not allow you to map an autonumber field outright. We were, however, able to map this text field in Salesforce to Salesforce.
3. We created a workflow rule to set the Lead External ID Num field only when the Lead was created in that instance of Salesforce. Thus, if SP created a Lead, their workflow rule set the Lead External ID Num field (from the Lead External ID field). We mapped that Lead External ID Num from SP to the Lead External ID Num field in the TP instance of Salesforce, which would previously have been blank because the workflow rule criteria stopped the field from being updated from within TP. The pictures below show our workflow rule criteria and field update.
4. We created a Lead External ID Copy text field on the Career and Screening objects, which was set by a workflow rule only when the Career or Screening record was not shared from another system (i.e., when “ConnectionReceivedID” was null). When the rule criteria was met, it would set the field to display the associated Lead’s Lead External ID. We then mapped the Lead External ID Copy field via Salesforce to Salesforce. Thus, when a Career or Screening record was received from the other system, its Lead External ID Copy field would be populated with an existing Lead’s External ID Num. The pictures below show our workflow rule criteria and field update.
5. We created two Process Builders and two flows - one each for Career and Screening - to set the correct Lead ID to the Career/Screening record based upon the Lead External ID Copy field. The Process Builder was set to trigger the flow, and it only triggered the flow when the Lead External ID Copy field was not null. The flow looked for a Lead record where the Lead External ID Num field matched the Lead External ID Copy field from the Career/Screening and updated the Career/Screening record appropriately.
This is what our Process Builder looked like, focused on the criteria which determined whether or not to launch the flow.
And our Flow looked like this:
There were three elements - to find the Career or Screening record that triggered the Flow, then to find the related Lead, then to update the original Career or Screening record with the Lead ID. The following image shows the detail of our 2nd element, the Lead Record Lookup, which found the Lead where the Lead External ID Num field matched the Lead External ID Copy field from the Career (specified in the first element). As you can see, we also assigned the Lead ID to an SObject, which we used in the third element to update the Career/Screening record.
Together, these steps ensured that when a Career or Screening record was shared via Salesforce to Salesforce, the receiving organization got a Career/Screening record that was still linked to the associated Lead record. Great! ... But, as I mentioned, we also found that our Career and Screening records were not retaining their record type when they were sent via Salesforce to Salesforce. Stay tuned for my next blog post, where I’ll share our resolution for the record type issue!