I’ve seen quite a number of people asking how to drive automations using Salesforce Surveys and Flow and thought I would share a solution I’ve used in a recent project that utilizes Custom Metadata records to intelligently drive automation based on specific responses.
First, I will say that for basic automations the Surveys add-on called Feedback Management will handle most scenarios for you – simply create a data map for each survey and perform a series of automations in your org. For more advanced automation, or if you can’t purchase Feedback Management, you may want more control and flexibility with the help of Flow.
Secondly, I will also say this is not the most basic solution. This takes some time to digest and if you want to sacrifice scalability for speed, you don’t need Custom Metadata records… however you will need to be careful of any changes made to the survey and the logic used in your flow that may look at the question text. Understanding this model will serve you well in the long run – both in knowing how to use Custom Metadata and in understanding the Survey data model.
The Survey Data Model
It’s critical to understand the Survey Data model in order to understand the Flow automation I built to handle survey responses. When a survey taker responds, a Survey Response record is made, with a series of Survey Question Responses for each responded question.
Please excuse this extremely un-architechty diagram.
Survey: This is the actual survey you create and has multiple versions. Everything eventually rolls up to this.
Survey Version: This is where we track the various versions of the related survey. Think of this as a similar version of ContentDocument / ContentVersion.
Survey Question: The questions that you create on your survey each have their own Question record that all relate to the Survey and Survey Version.
Survey Question Choice: If your question has multiple options (picklist, for example), you will have multiple Survey Question Choice records that all relate to a single Survey Question.
Invitations & Responses
Now we get into when a survey taker responds to the survey.
Survey Invitation: This is where the unique URL is made for the survey. This is also where you specify other details like if the user needs to be logged in to respond, and whether You can add custom fields to this.
Survey Subject: A junction object that connects the survey response to another object. You can add custom fields here. This typically grants visibility to the survey.
Survey Response: Represents information about a participant’s response to a survey, such as the status of the response, the participant’s location, and when the survey was completed.
Survey Question Response: This is the actual response to a question. You can choose to drive your automations on this object, or Survey Response.
Take this SOQL query for example that looks at the out of the box Customer Satisfaction Survey choices. SurveyQuestionChoice looks up to SurveyVersion and SurveyQuestion. We use the relationship fields just to demonstrate how they all relate.
Where SurveyVersion.Name = ‘Customer Satisfaction’
Which object do you select as your starting point?
The first thing you need to consider is whether you want your automation to run when a Survey Response is created vs. when a Question Response (a response to an individual question) is created. Both have valid use cases.
Trigger on Survey Response
Trigger your flow here when you only want your Flow to fire once.
- If you have a ton of questions with potentially complex logic and lots of looping, I would suggest starting here.
- If you really only care that somebody has submitted a survey and you want to track its status elsewhere (like on a Case), go this route. Otherwise, you will needlessly fire off a Flow for every single question.
Trigger on Survey Question Response
Trigger your flow when you want your Flow to fire for every question.
This works well when you don’t have a ton of questions and you don’t necessarily care about doing something with the status of the overall survey.
If you don’t necessarily care what happens on submission and you’re okay with multiple instances of your automation firing, choose this object as your starting point.
Be wary of going this route if you have something like 50+ questions though, you could run into limit issues if your flow is complex and has lots of loops / processing.
Custom Metadata: Survey Automation Mappings
The main thing that drives this Flow is the Survey Automation Mapping custom metadata object. In it, we store the developernames of specific Choice and Survey records. This allows us to avoid hard-coding responses in decision nodes in our Flow to drive automation on specific responses to questions. This means that we can change the answers to questions in surveys without worrying about also updating the Flow.
Here are the fields:
Active: Keeps the mapping activate. Generally always a good idea to have an Active flag in any CMT record.
Department: Not needed for generic use, but could provide for department-specific automations for the same survey responses.
Mapping Help Text: Provides the admin the ability to provide context / help for the mapping record like where and why it’s used
Question Choice DeveloperName: Stores the developer name of the Question Choice – we do this so we dont have to reference static text in the automation.
Question Choice Text: Stores the answer response text – used in the decision node in the Survey Response Flow
Question Label: Optional. Used more as a handy reference when viewing mappings to know which question is being referenced in this CMT record.
Question Query Text: Used by Flow to retrieve the right CMT record and get the developer name of the question being queried. For example ‘Was_Request_Met’ AND Survey DeveloperName = ‘Surveyname’
Survey Developer Name: Stores the developer name of the survey containing the mapping
Each response to a ‘Choice’ type question has a related Choice record for each option for that question that has a flexible label, what the customer sees, but a static DeveloperName. We use that DeveloperName in the custom metadata record. See below for an example of how the data model looks with Questions, Choices, and Responses.
Let’s take a scenario where there is a question on a survey that asks ‘Was your request met with us’ with 3 possible choices (see below).
Getting the DeveloperName of Questions & Surveys
You will need to use SOQL (Dev Console, Workbench) or Salesforce Inspector’s (a Chrome Extension) ‘View Data’ feature to see a survey/question/choice record’s DeveloperName. VS Code also has some SOQL functionality.
Here is how you’d query for everything you need to create your Metadata Mappings:
SELECT id,Name, DeveloperName,Question.Name, Question.DeveloperName, SurveyVersion.Survey.DeveloperName
WHERE SurveyVersion.VersionNumber = (use the version # you want here)
AND SurveyVersion.Name = ‘Survey Name Here’
ORDER BY Name
Using this, we can create some mapping records:
|Active||Label||Survey Automation Mapping Name||Mapping Help Text||Question DeveloperName||Question Label||Question Query Text||Question Choice Text||Survey Developer Name||Question Choice DeveloperName|
|TRUE||Member Feedback – Request Not Met||Member_Feedback_Request_Not_Met||Used to automate Case field ‘Request Status’ to drive if the case has to be re-opened or can be closed||q_963113e4_d736_4a0d_b992_7f42bdb540e1||Was your request met with us?||Was_Request_Met||Not_Met_Close_Case||customer_satisfaction_survey||c_315e2827_6ffc_49d4_93b9_54b55cd356|
|TRUE||Member Feedback – Request Not Met||Member_Feedback_Request_Met||Used to automate Case field ‘Request Status’ to drive if the case has to be re-opened or can be closed||q_963113e4_d736_4a0d_b992_7f42bdb540e1||Was your request met with us?||Was_Request_Met||Request_Met||customer_satisfaction_survey||c_69a6ba6f_0aec_4f1d_8283_feff74543339|
Next up – we’ll look at using these custom metadata records to drive specific responses in our Flow