Salesforce Obscura: Salesforce + Marketing Cloud = No Exit from the Journey

The Problem You Need To Solve
When a new Lead is created in Salesforce that is tied to a specific type of interest (e.g. from a specific landing page), it should immediately enter a Journey (in MC). This same Lead should exit prior to the journey’s end if it converts or is marked as not pursuing.

No Exit from an MC Journey when the entry point is Salesforce? Read on.

The Pain

This one should be in the category of “if you only do one thing in Marketing Cloud THIS is what you do.” Which should be in the category of “here is a handy step by step guide for people who don’t know Marketing Cloud because this task is super simple.”

If it is in this category, I couldn’t find that guide. Instead, I invented new swear words while watching my blood pressure rise. So I’m writing it here in case it prevents you from spending days shouting at cryptic and only partially helpful pieces of answers on the internet.

The good news is that the steps to make this work are mostly super easy once you know what to do.

Quick Look: The Steps To Accomplish This

If you already know how to do each of these steps, then the hard part is figuring out which steps and in what order. The steps are listed here.

The rest of this article identifies some Concepts and Lessons Learned (high level stuff that helped me understand what was going on) and then goes into the Step by Step Setup that contains exhaustive instructions and screenshots.

  1. Make sure the Salesforce Leads object is part of your MC Synchronized Data Extensions, and make sure you’re bringing in the fields you care about for your exit criteria.

  2. Create a new, empty Data Extension to hold a copy of the Lead data that will be used for evaluating your exit criteria.

  3. Create a new Attribute Group based off of the DE you created in step 2 above. Make sure you’re linking on Lead ID and it’s a one-to-one relationship.

  4. Use Automation Studio to copy data from the MC Salesforce Leads (synchronized) table into your new DE.

  5. Set up your Journey to have Salesforce Data as the Entry Source, to let the Lead come in immediately. Ensure you have Lead ID as the key.

  6. Create a Decision before each step in your journey to evaluate if the journey contact is found in your new DE, and if the criteria indicate that person should exit or not. You cannot use your new DE to set Exit Criteria, but you can compare the data in it with data in your entry event to ask if this specific person should continue or not.

A diagram representing how things are connected between MC and SF, linked to the steps above

Concepts and Lessons Learned

This is subject to change as Salesforce decides where it wants to go with Marketing Cloud data integration. As of early 2022, the following concepts are key to handling a journey exit when the entry point is a Salesforce record. Skip ahead to the next section if you’re just here for the step-by-step guide.

  1. Marketing Cloud only reads data in real time from Salesforce under very few, very specific circumstances. In a Journey, that circumstance is when you choose the Salesforce Data Entry Source. It does not re-evaluate the record after that record is on its Journey. So if you read about setting exit criteria and how a journey contact is automatically evaluated before every journey step if you have a goal or exit criteria set? Yeah, joke’s on you if you use a Salesforce Data entry source! That only works for custom Data Extensions.

The Salesforce Data Entry Source in Marketing Cloud operates in real time. You can think of it like a trigger in Salesforce that performs an after insert or after update action, but that action injects the contact into an MC journey.

2. In MC’s Contact Builder, the Synchronized Data Sources are going to make a copy of Salesforce data in MC. That alone is not unusual, but what is unusual is that you can’t work with the Synchronized Data Source like you can work with any other Data Extension. You have to copy parts of the copy into a local Data Extension to be able to work with it properly. You will need to automate this copying via the Automation Studio — details of these steps are outlined below.

If you’re not sure what I’m talking about, go to Audience Builder->Contact Builder->Data Sources->Synchronized as pictured in the image above. You should see your SF org with the number of sync’d objects and the number of fields across those objects. You can click on the box that says “Entities | Attributes” to get into your sync configuration.

3. The synchronized data sources can’t be removed (*). Once you’ve synchronized an object, unless you completely disconnect your Salesforce, you’re stuck with the object. Basically just sync only the objects you absolutely, 100% need, and of those only the fields you absolutely, 100% need. You can always add more later.

<rant>There are so many things in MC where the official guidance is “well don’t screw it up on initial setup or you’ll hate everything forever ¯\_(ツ)_/¯” that it blows my mind, and I have dealt with some truly dreadful enterprise systems in my time. I wasted soooo much time thinking the can’t-remove-synchronized-data-sources issue couldn’t possibly be true and looking for the real truth. Friends, it is true, so just move on.</rant>

4. It is probably easiest to think of your Salesforce Data Entry Source as Table A, and the copy-of-a-copy Data Extension where you will get your exit data from as Table B. These tables will contain similar — if not identical — fields, and you can specify the foreign key between them (put another way, ID in Table A is the same as ID in Table B). To set up a Journey exit for our specific use case (**), you must compare data in these two tables, since you can’t compare Table A directly with synchronized Salesforce data. Also important to understand: table A never refreshes, so the data remains forever as it was when the person entered the journey, and table B only refreshes if you make it refresh with Automation Studio.

5. You know this one already but it’s worth mentioning — “Contact” in MC does NOT match the Contact object in Salesforce. In MC, Contact is a single, central database table containing one row per individual human being, and you can populate this with any information from any source. As an example: first name, last name, and email from the Salesforce Contact object will be stored in the MC Contact table, and also those same fields from the Salesforce Lead object will be stored in the same MC Contact table. For the purposes of this explainer, it’s fine to think of MC’s Contact and MC’s Subscribers as basically the same thing, just know that distinction probably matters somewhere I just haven’t found yet.

6. An Attribute Group in the Data Designer is a way to extend the definition of the MC Contact record. So whatever data storage you’ve got set up — and all of the Data Extensions are basically just database tables — you will link to the main Contact record. In Salesforce, you’d just go into the object manager and add fields on the object you want to extend; in MC, you create a supporting database table and link them.

(*) Synchronized data sources cannot be removed. But you can pause them, remove all the data from them, and change their fields. So you’re stuck with a messy screen but you do have some ways to at least mitigate data sync mistakes without blowing up your whole, entire Salesforce connection.

(**) The use case we need very specifically is to bridge the gap between the immediate nature of the Salesforce Data Entry Source and the data stored in traditional MC Data Extensions, which is what we outline below. If you start the journey from a standard MC Data Extension, exit criteria work just fine to re-evaluate before every step in the journey. But then you are dealing with lag from lead creation to first step on the journey, and most of the time that’s unacceptable. Put another way, if you use MC the way MC was designed, it does work more or less as documented. When you toss SF real-time stuff into the mix, things get kinda painful.

From Concept to Action — Step By Step Setup

These steps will allow you to: (1) Have data from Salesforce drop someone onto a journey immediately and (2) have that person exit the journey when their Salesforce data is updated.

I will be using Lead and Lead Source as the key data points throughout this example. You can do the same thing with Contact or any other object you need, as long as you can specify how your custom object links to your Salesforce Data Entry source.

Step 1: Set up your Salesforce Lead object as a Synchronized Data Source

This is the only step where I’ll point you to the documentation — if you haven’t already connected your Salesforce and Marketing Cloud instances via the Salesforce Connector, then this article won’t help you and you need to go do that first.

  1. In your top navigation in MC, hover over Audience Builder and choose Contact Builder.

  2. Once you’re in Contact Builder, click on Data Sources, then click “Synchronized”

  3. Click anywhere in the box that appears that shows your SF Org’s name and looks like the screenshot below (except probably with fewer “Entities” (objects) and “Attributes” (fields).

Click anywhere in your version of the box that says “Entities | Attributes” to go to the sync setup.

4. If you don’t see Leads in the screen that appears next, then you’ll need to set it up. If you do, then you may want to check and confirm that all of the fields you need for your Journey exit decision (Lead Source and Lead Status, in this example) are mapped.

An example of Synchronized Data objects. The Set Up Object button is highlighted in this image. You can see that I already have Lead synchronized in this org — if you don’t, click the button.

4a. Set up Leads: Only if you don’t see Lead under Synchronized Entities. Click on “+ Set Up Object” then search for Lead. Click the “Synchronize” button inside the box that is labeled “Lead.” On the next screen, select the fields to synchronize — note that it’s best to just select only the fields you know for sure you need. So you may only sync a few. In this example we would be sure that Converted, Lead Source and Status were selected, along with First Name, Last Name, and Email and anything that is the sync pulls in automatically. When you’re done with this, you do NOT need to do step 4b.

4b. Confirm Lead Data if Already Sync’d: If you already have Lead sync’d (and skipped step 4a) you may just want to double check that the necessary fields are already configured. Click on Lead (where the image above has a rectangle around it) to go into the object configuration screen. Review your synchronized fields (in this example, make sure you see IsConverted, LeadSource and Status in the mapped fields, and add them if you don’t see them).

5. Note the poll schedule — whether you just set up Leads to sync, or whether you already have it sync’d, it’s important to know how long the gap is between refreshes. Remember that the synchronization is copying data from Salesforce into MC on the schedule defined by the poll sync. So if your poll schedule is 15 minutes, you’ll have up to a 15 minute lag between a record getting created or updated in SF and having its info refreshed in MC.

Step 2: Create a new, empty Data Extension to hold a copy of the data you just sync’d in step 1

Yep, you read that right. You’re going to copy the copy, or at least parts of the copy. First we have to set up the container for that copy.

  1. In your top navigation in MC, hover over Audience Builder and choose Contact Builder.

  2. Once you’re in Contact Builder, click on Data Extensions then click “Create”

The Data Extensions menu in MC

3. Give your new Data Extension a name that lets you find it, and a description. The example below is a little generic, in real life I have it specific to the journeys and business units it supports. Check “Is Sendable?” and (if appropriate) “Is Testable?” then click Next.

Screen one of Create New Data Extension. This screen just gives it a name and some basic settings.

4. It is a very good idea to set retention settings, so that data doesn’t stick around forever. If you’re not sure right now, you can always adjust this part later.

For my real use cases, I need the information for a bit longer than the journey duration. So I set the retention accordingly. But this part I’m not 100% sure about yet, so if it turns out to be a Poor Life Choice, I’ll update this article.

5. Finally we get to the important step — setting up the fields for this Data Extension. This is exactly like setting up a new database table (or new object in Salesforce, except that in MC you must also specify which field contains the ID).

For this example, you will absolutely want to have an ID field that can hold the Lead ID (or the ID from whatever object causes you to enter the Journey). You will probably also want the Email address. Lead Status, Lead Source, and Converted are all important for our exit criteria so we create fields for those. Be careful to match your data types and field lengths to accommodate your actual Salesforce data. For example, Lead Status and Lead Source are picklists in Salesforce, but MC doesn’t have picklists. So we set up the Data Extension field as Text and make sure to increase its size from the default of 50 characters to the 255 max that would be the limit of a Salesforce picklist value.

The full specification of the Data Extension for this example. It contains only the fields we absolutely need, and the data types and lengths have been adjusted to match whatever we expect to come from Salesforce.

6. Notice the “Send Relationship” — this is the field that will link the data in this Data Extension back to MC’s single, central record for a person (see the explainer in the Concepts section if this makes no sense). Your system will differ from mine — some organizations use email, and some use the subscriber key (lead or contact ID, roughly). Choose the right one for you and then click “Complete.” (note: if you’re not sure, choose Lead Id as the most likely starting place).

Step 3: Connect your (empty) Data Extension to the MC Contact via an Attribute Group

  1. Still in Contact Builder, click on “Data Designer”. You will see a big circle that says “Contacts” in the middle, with other circles sticking out from it. The other circles are basically extending the Contact record.

The Data Designer screen, image taken from Salesforce Trailhead

2. Click +Create Attribute Group. Give this new attribute group a name and choose an icon (doesn’t really matter which one, it will show up in the blue part of the circle on the Data Designer screen). Click “Create”

The screen that appears when you create a new Attribute Group in Marketing Cloud.

3. Click “Link Data Extensions” from the next screen. We are going to link this attribute group directly to the Data Extension we created in step 2.

4. Ignore what’s on the left-hand side of the screen for a minute. Navigate to the Data Extension you just created in step 2. It is probably in the “Data Extensions” folder, so click that on the right-hand side to see all of your DEs. Click on the one you created to select it.

Navigate to your new DE. Ignore the left hand side for a minute.

The next step is how you tell MC how your custom Data Extension relates to the core Contact record. Remember that, thanks to step 1 in this explainer, Salesforce is syncing all of your Leads already. The Salesforce Connector will put the Lead ID and other data into the MC Contact table automatically, and it links Lead ID to Contact Key. We want to do the same thing with our Data Extension — we are linking our custom data table to all these other things with the Lead ID. It’s not that different than setting a lookup in Salesforce or specifying a foreign key in another database.

5. Click on “Contact Key” in the left-hand side. This selects it as the way you will connect your custom data to the core data set. Then click “Lead ID” in the right hand side, to make the link. You also want to make sure that the drop-down in the upper right that says “One” in the image says “One” on your screen. This drop-down specifies that this data extension exists in a one-to-one relationship with the master data list. Basically when we do a lookup in this table with an ID, we will only ever get one single record, and that’s exactly what we want. Click “Save.”

This screen shows a correctly configured one-to-one link between our new data extension and the core Contact list, linked on Lead ID as the unique identifier.

7. After you save, you will land on a screen that looks like the one below. You can come back here to edit the relationship or name of the attribute group if you need to later.

Step 4: Copy your synchronized Salesforce data into your customized Extension

You have just sync’d data from Salesforce, created an empty storage container, and defined how you want to use that container in your MC data architecture. Now you need to use Automation Studio to copy the data from your synchronized data set (which we can’t use the way we need to) to your data extension, which is the last step before we can use it in Journey Builder.

  1. Create a new SQL Query activity in Automation Studio.

  • Go to Automation Studio (I get to mine via Journey Builder but apparently you can access it other ways).

  • Choose “Activities” in the top nav.

  • If you want, navigate to your SQL Query folder on the left-hand side.

  • Click “Create Activity”

Your screen should look more or less like the above if you’re in the right place for this step.

2. Click on “SQL Query” to choose it then click “Next”

When you click to choose the type of activity, it will turn a pale blue with a faint checkmark.

3. Give your query a name and a description, then click “Next”

The description says: This query will copy data from the Salesforce Synchronized Lead DE into the Leads for Exit DE for use in journey builder.

4. Compose your query. Read this next bit carefully, as there are a lot of caveats and this is where a bunch of pieces link together.

  • This is the step where you map the fields from the synchronized data into your custom DE. There is no other place to do this, you do it directly in the SQL using the syntax “select source_fieldname as destination_fieldname”.

  • You will not find your Salesforce DEs available in the left-hand menu where you would normally look for help on what you are selecting from. You can reference your custom DE from this menu.

  • MC always names the synchronized objects with the pattern [objectname]_Salesforce. So in our case we will select from Lead_Salesforce. If you’re not sure, you can check on your Synchronized Data screen, under Entities — the SF name will show up, then the table name to select from.

  • MC also always synchronizes the Salesforce field’s API name as the field name, which again you can check in your Synchronized Data screen once you click into the sync’d object.

  • In step 2.5 you set up your custom DE. You must use exactly what you typed in as the field name in your custom DE to specify the destination in this step — spacing matters (Field Name and FieldName are different. Not entirely sure if capitalization matters). Use the left-hand menu to find your custom DE, which will list all of the field names when you click on it. You can drag these into the query builder to ensure you get the right field name.

  • Use the Validate Syntax button before moving on to the next step.

So your query will look more or less like the following:

Select Id as “Lead Id”,
FirstName as “First Name”,
LastName as “Last Name”,
Email,
Status as “Lead Status”,
LeadSource as “Lead Source”,
IsConverted as “Is Converted”
from Lead_Salesforce

Your completed query, mapping from the source table (Lead_Salesforce) to the destination DE.

5. Select the destination DE (the one you created in step 2) and choose whether you want to append, update, or overwrite. For this example, you want to update. Click Next.

In the middle box, scroll until you find your custom DE and click on it to select. Below, choose Update.

6. Review and click “Finish”. You have just stored a query, now we have to set up the timer so it runs without manual intervention.

7. Still in Automation Builder, click “Overview” then “New Automation”

8. In the left hand side, click on the green calendar icon that says “Schedule” and drag it into the circle that says “Start with a Starting Source”. Then click “Configure”

9. Configure the schedule.

  • Provide a starting date and time that is after the current moment.

  • For your Repeat, make sure to select some frequency other than “None (run once).” I typically set these on every 1 hour because my journey will run on its own timeline and frequently refreshed data is imperative.

  • For your End, choose the appropriate time to end this automation. Ideally you would end it to coincide with when you shut off the Journey it is supporting, but that’s up to you.

  • Click “Done”

This schedule will run our actions every hour from the start date till the end of time.

10. From the left-hand side, grab the SQL Query icon and drag it into the empty space to the right of the schedule.

11. Once it’s on the canvas, click “Choose”. From the screen that opens, find your SQL Query that you just created and click on it to select it. Once you’ve clicked on it, a review screen will open — just click “Done” in the bottom right corner.

Find the SQL Query you created and click on it to select.

12. In the upper right corner, click the blue “Save” button. Give your automation a meaningful name and description. Do not Save and Close — you have one more thing to do.

13. Click “Active” to turn on your automation.

You can also click the “Run Once” button in the upper right of your screen to force a single run and ensure that your data is populating correctly. To do this:

  • Click “Run Once” and follow the prompts to select which activities (your SQL query is the only option) to run this one time. Then navigate out of Automation Studio.

  • Go back to Contact Builder->Data Extensions.

  • On the main DE screen, you’ll see all of your DEs in a big grid with headers Name, External Key, Description, Field Count, and Record Count. Record Count tells you how many records are in your DE — it started out as 0 in step 2, and stayed 0 until now. You should see it increase to whatever you’re expecting from your Salesforce data set after the run once.

The list of DEs, with a successful population showing in the nonzero record count.

  • You can also click on the DE itself and see the records it has stored just to triple check everything is as you expect.

Step 5: Set up your Journey with a SF Data Entry Event

FINALLY!

  1. From your main nav, go into Journey Builder. Click “Create New Journey” in your upper right hand corner. Choose “Multi-Step” journey from the next screen.

2. Drag the “Salesforce Data” icon into the “Start with an Entry Source” area on the canvas. It goes into the canvas greyed out — click on it to open up the configuration screen.

Drag the Salesforce Data icon into the circle, then click on the greyed out version that appears.

3. Choose how data will enter your journey from Salesforce. For this example, we are pulling directly from a newly created Lead, regardless of their Campaign, and we are not dealing with Communities/Experience Cloud users, so we’ll choose Salesforce Data. When you click on it, it will turn pale blue with a checkmark. Click “Next”

(Important aside: if you have gotten this far with the example and are NOT using Leads, make sure every step above aligns with whatever object you ARE using!!! We built every step up to this point with this specific entry point already in mind.)

Salesforce Data as our entry source allows us to select from any object in Salesforce, and respond immediately to the create or update of a record. This will create “Table A” from the explainer earlier in the article. We have already created “Table B” in our custom DE from steps 2–4.

4. Set up Lead as the starting point.

  • In the box that says “Select who to inject into the journey” type “Lead” then hit enter. This will just filter the full list of SF objects.

  • In the results, click on the “Lead” object to select it. It will expand to show some fields in the Lead object from your Salesforce — these are our potential primary keys for this data set.

  • Click “Lead ID” to select it as the primary key. This is how we will join up data in this data set to data in our custom DE — the Lead IDs will match in both tables.

  • Click “Next”

When you’ve completed the above steps, your screen should look like mine. I searched for lead, then clicked on it to expose the fields, then clicked on Lead ID (Lead) to select it as the primary key.

5. Select which records from Salesforce should enter onto this journey. What fields on this record make it eligible for this journey? And only on create, or also when the record is changed to make it eligible?

In my example, I want journey entry only on create, only for people from an unknown lead source, and people who are in a specific lead status.

  • Check Is Created and/or Is Updated, based on your actual journey entry needs

  • Check Meets Specific Event Criteria to add conditions beyond “created or updated”

  • All fields on your Lead object will show up. Find the fields you want to use for your additional entry criteria and drag them one at a time into the right-hand filter builder.

  • When you’re done, click “Next”

An example of how I built my entry criteria to select only certain leads, when created in SF, to enter immediately into my MC Journey.

6. Don’t do anything on the “Filter Criteria” or “Entry Data” screens, just “Next” through them.

Unless you actually need to. And if you do, please put in the comments what on earth these screens are actually for? I am baffled and can’t get a good answer anywhere.

7. Review your Summary screen and click Done.

You’ve now got someone automatically entering the journey, immediately, whenever a Lead is created with the right criteria.

Step 6: Set up a Decision Split to see if the Lead is still on the journey

Important note: this article is already way too long so I’m not going to go into how to set up the journey overall. I’m assuming you have a basic command of the journey builder itself and can add the things you need to add. For this example, I’m just doing a simple time-delayed email just to set it up to illustrate the decision split.

Our simplistic starting journey, just to illustrate the key Decision Split that joins the custom DE with the Entry Event data to evaluate exits.

  1. Drag a Decision Split element into your journey prior to the point you need to evaluate. For example, in the journey above it is the requirement that everybody immediately gets the first email, and then we wait a day. I will add my decision split after the day’s delay and before the next email, to ensure that the person hasn’t converted between entry and next send.

Our simple journey, with a new Decision Split placeholder that isn’t configured yet.

2. Click the Decision Split in your journey to configure it.

  • The default split will be “Path 1” and “Remainder” — just click the pencil icons to rename these. Since this decision asks “Still a valid lead?” I just name them “Yes” and “No”

  • Click “Edit” next to Path 1 / “Yes”. This is where we finally connect all of the prep work.

  • Click Contact Data

Contact Data is the list of all available Data Extensions, including your custom one that is being refreshed automatically.

  • Click on the name of your custom DE (“Leads to Evaluate for Exit” is what the example is called)

  • A list of fields available in your custom DE will appear. This holds the current information from Salesforce about your leads.

  • Drag Lead ID and any other fields you want to evaluate into the right-hand canvas. Do not configure the Lead ID filter yet. In our example, you are still a viable lead (and still on the journey) if you have not converted and if your lead status is still Inquiry, so you can see this represented in the screenshot below.

We have set up our filter criteria by dragging fields from our custom DE into the Filter Criteria canvas. For anything that we want to evaluate about the lead, we’ve already configured it by clicking on each filter criterion and and entering the relevant data. We have left Lead Id un-configured for now.

  • Click on Lead Id in the Filter Criteria canvas to configure it. Check the “Add an attribute to compare” box.

When you check “Add an attribute to compare” a new field type comes up. This is where you link to the journey’s DE using the steps below.

  • In the left-hand side (under “Attributes”) click the home icon to go all the way back out to the top level of attributes available to you.

  • Click Journey Data to access the information about journey participants on this specific journey.

  • When you click on Journey Data, you should see only one option, which would be your Data Entry element. Click on it to see the available fields.

  • Drag Lead ID into the right-hand side to link it to the Lead ID from your custom Data Extension.

Drag the Lead ID from the data in “Table A” (this journey’s entry data) to match to the Lead ID from “Table B” (your custom DE that contains updated SF data).

  • Click “Summary” to to back to the Decision Split config screen and review your logic.

When you’re done with the setup, you will see a confirmation of the filter logic that matches the path you’ve set.

Based on the image above, we can see that for anyone who started this journey and is also found in the custom DE (Lead Id equal Lead:Id) AND who also still has a lead status of “Inquiry” (from the custom DE) AND who is not yet converted (from the custom DE) will proceed with the journey on the “Yes” path. Anybody else is kicked to the “No” path which simply exits them.

Once you have your decision split set up, you can simply clone it and paste it anywhere else on your journey that it’s needed. So it’s tedious, but fast.

Step 7: Celebrate

You did it. And hopefully you learned a lot, or at least got your marketing team off your back.

Previous
Previous

How I Solved It: Copy a File to a Rich Text Field with Flows

Next
Next

Salesforce Obscura: This quarter vs the same quarter last year, but ALIVE