Process Automation, Data Model Flashcards
Mitigate SOQL Injection
Salesforce Object Query Language Versus Structured Query Language
SOQL
As a Salesforce developer, you know that on the Lightning Platform we use SOQL not SQL. While the languages are similar in many respects, SOQL is essentially a customized version of SQL developed specifically for the Salesforce platform.
Let’s dig into the ways that SOQL differs from SQL. For starters, SOQL is a language exclusively for querying the database rather than modifying data like in traditional SQL. Here is a list of what SOQL does not have.
INSERT, UPDATE, or DELETE statements. It only has SELECT statements.
Command execution.
JOIN statement; however, you can include information from parent objects like Select Name, Phone, and Account.Name from Contact.
UNION operator.
Ability to chain queries together.
Mitigate SOQL Injection
SOQL Injection Prevention
SOQL
You can use several techniques to prevent SOQL injection:
Static queries with bind variables
String.escapeSingleQuotes()
Type casting
Replacing characters
Allowlisting
SOQL Injection Prevention
Static Query and Bind Variables
SOQL
The first and most recommended method to prevent SOQL injection is to use static queries with bind variables. Consider the following query.
String query = ‘select id from contact where firstname =\’’+var+’\’’;
queryResult = Database.execute(query);
As you’ve learned, using user input (the var variable) directly in a SOQL query opens the application up to SOQL injection. To mitigate the risk, translate the query into a static query like this:
queryResult = [select id from contact where firstname =:var]
This step ensures that the user input is treated as a variable, not as an executable element of the query. If a user types a value like test’ LIMIT 1 when the database performs the query, it looks for any first names that are “test’ LIMIT 1” in the database. With a bind variable, the attacker can’t break out and control the SOQL query.
While using bind variables is recommended, there are some limitations. They can only be used in the following types of clauses.
The search string in FIND clauses.
The filter literals in WHERE clauses.
The value of the IN or NOT IN operator in WHERE clauses, enabling filtering on a dynamic set of values. (Note that this is of particular use with a list of IDs or strings, though it works with lists of any type.)
The division names in WITH DIVISION clauses.
The numeric value in LIMIT clauses.
The numeric value in OFFSET clauses.
SOQL Injection Prevention
Typecasting
SOQL
Another strategy to prevent SOQL injection is to use typecasting. By casting all variables as strings, user input can drift outside of expectation. By typecasting variables as integers or Booleans, when applicable, erroneous user input is not permitted. The variable can then be transformed back to a string for insertion into the query using string.valueOf() (remember with dynamic queries, the database.query() method accepts only a string).
If we enter a simple SOQL injection payload “1 limit 1” and search, the query returns only one result, because our input is treated as code.
The Apex code would look like this:
public String textualAge {get; set;}
[…]
whereClause+=’Agec >’+textualAge+’’;
whereclauserecords = database.query(query+’ where ‘+whereClause);
You can see that variable textualAge is placed directly into the query, allowing our input to be treated as code. You can also see no single quotes aroundtextualAge in the query.
If you apply the same SOQL injection payload of “1 limit 1” to your search, you see that the SOQL injection still functions.
You need another solution to prevent SOQL injection.
You would want to edit the controller again and remove string.escapeSingleQuotes(). Then you’d want to find the variable declaration for textualAge and change it from String to Integer (age is an integer, so this typecasting is appropriate). Because the query is expecting a string but textualAge is now an integer, you need to wrap textualAge in string.valueOf() as follows:
whereClause+=’Agec >’+string.valueOf(textualAge)+’’;
If you submitted your SOQL injection payload “1 limit 1” in the search area again, you would see an error rather than a SOQL injection. “1 limit 1” is not considered an integer, so the SOQL injection is prevented.
Typecasting can be used to prevent many kinds of SOQL injection where the user is not entering text.
SOQL Injection Prevention
Escaping Single Quotes
SOQL
Another cross-site scripting (XSS) mitigation option that is commonly used by developers who include user-controlled strings in their queries is the platform-provided escape function string.escapeSingleQuotes().
This function escapes any instance that it finds of a single quote mark (‘) in the string using the backslash () escape character. This prevents an attacker’s input from being treated as code by constraining them to the boundary of the string.
The Apex code for this would look like the following:
String query = ‘SELECT Id, Name, Title_c FROM Books’;
String whereClause = ‘Title_c like '%’+textualTitle+’%' ‘;
List<Bookswhereclauserecords = database.query(query+’ where ‘+whereClause);**
The search string “textualTitle” is placed directly into the query string, allowing user input to be treated as code and enabling this SOQL injection. Because the variable is wrapped in single quotes in the final query, we can fix this SOQL injection through string.escapeSingleQuotes().
In the example above, replacing the where clause with the following code wrapping textualTitle with String.escapeSingleQuotes() will prevent an attacker from using SOQL injection to modify the query behavior.
String whereClause = ‘Title_c like '%’+String.escapeSingleQuotes(textualTitle)+’%' ‘;
This time we’re using string.escapesinglequotes() to make sure the user-provided single quote is escaped to appear as data rather than as a query control character. Thus, the application is no longer vulnerable.
However, it is important to point out that this solution applies only to strings. Not all variables are strings, and not all SOQL injection attacks require using a single quote character. Other solutions are required to prevent SOQL injections in these types of code.
SOQL Injection Prevention
Replacing Characters
SOQL
A final tool in your tool belt is character replacement, also known as blocklisting. This approach removes “bad characters” from user input.
In security, blocklisting will never be as strong as allowlisting, because it is far easier to predict a few good inputs than to predict all possible bad inputs. That said, blocklisting through character replacement can often effectively mitigate simple problems. Take the following code:
String query = ‘select id from user where isActive=’+var;
While typecasting or allowlisting would be effective here, removing all spaces from the supplied input would be an equally effective approach. In that way, a SOQL injection payload of:
true AND ReceivesAdminInfoEmails=true
becomes
trueANDRecievesAdminInfoEmails=true
The code to remove all spaces from a string can be written as follows:
String query = ‘select id from user where isActive=’+var.replaceAll(‘[^\w]’,’’);
While it should not be considered the first line of defense, development is about flexible solutions to varied problems, and this solution is a valid one to keep in mind.
SOQL Injection Prevention
Allowlisting
SOQL
The previous solution of typecasting was effective only against non-string input. What if user-controlled values need to be text but don’t have any single quotes? This often occurs when other query portions are put under a user’s control, like the Select fields or the From object.
Another way to prevent SOQL injection without string.escapeSingleQuotes() is allowlisting. Create a list of all “known good” values that the user is allowed to supply. If the user enters anything else, you reject the response.
Mitigate Cross-Site Request Forgery
What Is CSRF?
This example is precisely what a CSRF attack can look like. The attacker got the user’s client (the browser) to perform an unwanted action (the advancement of a student to the honor roll) on a trusted site (School District Management app) for which the user is currently authenticated.
Let’s start with the idea that we have built an application that lists all of the current students in our network of schools. In this application, there are two important things to note.
Only the admin or the superintendent can access the page allowing users to promote students to the honor roll.
The page automatically refreshes if you click the Honor Roll link. If you’ve added a student, an alert will be noted that your student has been added to the honor roll.
What is happening behind the scenes is that the Honor Roll button makes a GET request to /promote?UserId=<userid>. As the page loads, it reads the URL parameter value and automatically changes the role of that student to the honor roll.</userid>
Seems pretty straightforward. You may be wondering, where’s the vulnerability?
Let’s take a look at this scenario again and change it slightly.
This time, imagine that after logging in to your School District Management org, you decided to browse another website. While on this website, you click a hyperlink. This hyperlink redirects to a link to www.beststudents.com/promote?user_id=123. This malicious link is executed on behalf of the admin (your signed-in account), thereby promoting a student to the honor roll without you realizing it.
Mitigate Cross-Site Request Forgery
Prevent CSRF Attacks
Consider a slightly different version of the page that has two required URL parameters: userId and token. What if you made the token parameter value a random, unique value that changed on every request? This would make it next to impossible for an attacker to guess the current value, preventing the attack. This example is the most common prevention technique for CSRF.
For this prevention technique to be successful, four things must happen.
All sensitive state-changing requests (anything performing database operations) must include a token.
A token must be unique to the request or user’s session.
A token must be difficult to predict (long with advanced encryption).
The server must validate a token to ensure the request originated from the intended user.
Suppose all four steps are properly implemented by the server. In that case, the attacker can’t guess the current value of the token parameter and can’t manipulate the user’s browser into making the correct honor roll request to the app. The attacker sees an error and is unsuccessful.
Mitigate Cross-Site Request Forgery
Use the Salesforce Platform to Protect Against CSRF
Luckily, Salesforce includes out-of-the-box protections against CSRF for developers.
By default, requests made against Salesforce resources have CSRF tokens attached. These pseudo-random tokens prevent the reuse and distribution of hyperlinks to protect privileged accounts from accidentally making state-changing requests that were not intended.
Beyond this, developers of Lightning applications need to pay attention to how their code is structured to prevent CSRF attacks from occurring. The most simple forms of CSRF attacks use HTTP GET requests with state-changing parameters, like GET mywebsite.com?change_username=”joe”.
By simply avoiding the use of state-changing HTTP GET requests, you can eliminate a large number of CSRF vulnerabilities in your code. When you reach out to a web API, use POST or PUT instead when state changes are needed.
Several other mitigations can be put in place in your application to prevent CSRF attacks.
When an endpoint is hit in your API, you can validate the origin header. The origin header is set on HTTP GET requests and specifies the URL from which a request originated. Suppose the request is on the forbidden headers list, meaning all major browsers will not allow it to be spoofed via JavaScript. In that case, it will always return the correct value unless the request initiates from a nonstandard browser or tool.
When you integrate your Salesforce Lightning application with a third-party application via API, you may desire your own anti-CSRF tokens. These can easily be added to XMLHttpRequest within Lightning by using setRequestHeader() in an HTTP request that looks like this:
var o = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(){
var res = o.apply(this, arguments);
var err = new Error();
this.setRequestHeader(‘anti-csrf-token’, csrftoken);
return res;
};
Mitigate Cross-Site Request Forgery
CSRF on Lightning Page Load Events
Another place for CSRF vulnerabilities is when server-side DML operations are executed automatically as part of a page-loading event such as onInit or afterRender. To mitigate the risk of a page load CSRF, ensure that DML operations are only performed as a result of an interaction with a page (clicking a button, selecting an option, or other actions).
({
doInit: function(cmp) {
var action = cmp.get(“c.updateField”); //vulnerable to CSRF
[…]
$A.enqueueAction(action);
},
handleClick: function(cmp, event) {
var action = cmp.get(“c.updateField”); //not vulnerable to CSRF
[…]
$A.enqueueAction(action);
}
})
Mitigate Server Side Request Forgery
What Is Server Side Request Forgery?
Server-side request forgery (SSRF) is a security vulnerability in web applications where an attacker can make unauthorized requests, both internal and external, on behalf of the server. In an SSRF attack, the malicious application tricks the server into making requests to internal and external services or systems, potentially leading to unauthorized access or data exposure.
To illustrate this vulnerability, let’s consider our School District Management developer org. Imagine we have an application that fetches information about students from an internal service that is hosted on a non-routable address. The application is designed to make a GET request to the server whose address is contained in the API request to retrieve the student’s details, for example studentApi=https://192.168.0.1/student.
Now, suppose an attacker observes that the requests sent from the client contain a path value that may be exploitable. Cloud services often expose a REST interface on a metadata endpoint (such as http://169.254.169.254). In addition, some NoSQL databases may be configured to expose unauthenticated REST interfaces on internal interfaces. An attacker would intercept the API call from the client, replace the endpoint value of the student service with a call to the metadata service and exfiltrate sensitive service configuration data from the internal metadata endpoint.
Mitigate Server Side Request Forgery
Preventing SSRF Attacks
Preventing SSRF attacks involves implementing measures to validate and restrict the scope of requests. Effective prevention techniques include a combination of the following.
Validate and Sanitize Inputs
Ensure that input values, such as the studentApi value in our example, are properly validated and sanitized to prevent the injection of malicious URLs.
Implement Allowlisting
Restrict the allowed destinations for outgoing requests by enforcing the URL schema, port, and destination allowlist, disabling HTTP redirections. Only allow requests to specified, trusted endpoints.
Use URL Parsing Libraries
Utilize URL parsing libraries to parse and validate URLs before making requests. This helps ensure that the requested URLs conform to expected patterns.
Network Segmentation
Implement network segmentation to restrict the server’s ability to make requests to internal resources, limiting the impact of any potential SSRF attacks.
Salesforce Platform Protections Against SSRF
Salesforce provides built-in protections against SSRF for developers. Requests made against Salesforce resources include safeguards to prevent the exploitation of SSRF vulnerabilities. Additionally, Lightning application developers can use the following best practices to minimize the risk of SSRF.
Avoid GET Requests
Similar to CSRF prevention, developers should avoid using HTTP GET requests. Instead, prefer using POST or PUT requests to minimize risk of SSRF data exfiltration.
Validate Origin Headers
When integrating Salesforce Lightning applications with third-party APIs, validate the origin header in HTTP requests. Ensure that the request originates from a trusted source to prevent potential SSRF exploits.
Implement Anti-SSRF Tokens
Developers can add custom anti-SSRF tokens to XMLHttpRequests within Lightning by using setRequestHeader(). This adds an additional layer of protection against SSRF attacks.
SSRF on Lightning Page Load Events
Another area prone to SSRF vulnerabilities is during server-side Data Manipulation Language (DML) operations triggered by page-loading events like onInit or afterRender. To mitigate the risk, ensure that DML operations are only initiated in response to user interactions, such as clicking a button or selecting an option.
Triggers and Order of Execution
When you save a record with an insert, update, or upsert statement, Salesforce performs a sequence of events in a certain order.
Before Salesforce executes these events on the server, the browser runs JavaScript validation if the record contains any dependent picklist fields. The validation limits each dependent picklist field to its available values. No other validation occurs on the client side.
Executes validation checks
Record-triggered flows that are configured to run before the record is saved
Executes all before triggers
system validation steps again
Executes duplicate rules
Saves the record to the database, but doesn’t commit yet
Executes all after triggers.
Executes assignment rules.
Executes auto-response rules.
Executes workflow rules.
Executes escalation rules.
Executes these Salesforce Flow automations - Processes built with Process Builder,
Flows launched by workflow rules (flow trigger workflow actions pilot)
Executes record-triggered flows that are configured to run after the record is saved
Executes entitlement rules.
If the record contains a roll-up summary field or is part of a cross-object workflow, performs calculations and updates the roll-up summary field in the parent record. Parent record goes through save procedure.
If the parent record is updated, and a grandparent record contains a roll-up summary field or is part of a cross-object workflow, performs calculations and updates the roll-up summary field in the grandparent record. Grandparent record goes through save procedure.
Executes Criteria Based Sharing evaluation.
Commits all DML operations to the database.
After the changes are committed to the database, executes post-commit logic. Examples of post-commit logic (in no particular order) include:
Sending email
Enqueued asynchronous Apex jobs, including queueable jobs and future methods
Asynchronous paths in record-triggered flows
Triggers and Order of Execution
When you save a record with an insert, update, or upsert statement, Salesforce performs a sequence of events in a certain order.
Before Salesforce executes these events on the server, the browser runs JavaScript validation if the record contains any dependent picklist fields. The validation limits each dependent picklist field to its available values. No other validation occurs on the client side.
- Loads the original record from the database or initializes the record for an upsert statement.
- Loads the new record field values from the request and overwrites the old values.
Salesforce performs different validation checks depending on the type of request.
For requests from a standard UI edit page, Salesforce runs these system validation checks on the record:
Compliance with layout-specific rules
Required values at the layout level and field-definition level
Valid field formats
Maximum field length
Additionally, if the request is from a User object on a standard UI edit page, Salesforce runs custom validation rules.
For requests from multiline item creation such as quote line items and opportunity line items, Salesforce runs custom validation rules.
For requests from other sources such as an Apex application or a SOAP API call, Salesforce validates only the foreign keys and restricted picklists. Before executing a trigger, Salesforce verifies that any custom foreign keys don’t refer to the object itself.
3. Executes record-triggered flows that are configured to run before the record is saved.
4. Executes all before triggers.
5. Runs most system validation steps again, such as verifying that all required fields have a non-null value, and runs any custom validation rules. The only system validation that Salesforce doesn’t run a second time (when the request comes from a standard UI edit page) is the enforcement of layout-specific rules.
6. Executes duplicate rules. If the duplicate rule identifies the record as a duplicate and uses the block action, the record isn’t saved and no further steps, such as after triggers and workflow rules, are taken.
7. Saves the record to the database, but doesn’t commit yet.
8. Executes all after triggers.
9. Executes assignment rules.
10. Executes auto-response rules.
11. Executes workflow rules. If there are workflow field updates:
Updates the record again.
Runs system validations again. Custom validation rules, flows, duplicate rules, processes built with Process Builder, and escalation rules aren’t run again.
Executes before update triggers and after update triggers, regardless of the record operation (insert or update), one more time (and only one more time)
12. Executes escalation rules.
13. Executes these Salesforce Flow automations, but not in a guaranteed order.
Processes built with Process Builder
Flows launched by workflow rules (flow trigger workflow actions pilot)
When a process or flow executes a DML operation, the affected record goes through the save procedure.
14. Executes record-triggered flows that are configured to run after the record is saved
15. Executes entitlement rules.
16. If the record contains a roll-up summary field or is part of a cross-object workflow, performs calculations and updates the roll-up summary field in the parent record. Parent record goes through save procedure.
17. If the parent record is updated, and a grandparent record contains a roll-up summary field or is part of a cross-object workflow, performs calculations and updates the roll-up summary field in the grandparent record. Grandparent record goes through save procedure.
18. Executes Criteria Based Sharing evaluation.
19. Commits all DML operations to the database.
20. After the changes are committed to the database, executes post-commit logic. Examples of post-commit logic (in no particular order) include:
Sending email
Enqueued asynchronous Apex jobs, including queueable jobs and future methods
Asynchronous paths in record-triggered flows
Order of execution: Additional Considerations
Note these considerations when working with triggers.
- If a workflow rule field update is triggered by a record update, Trigger.old doesn’t hold the newly updated field by the workflow after the update. Instead, Trigger.old holds the object before the initial record update was made. For example, an existing record has a number field with an initial value of 1. A user updates this field to 10, and a workflow rule field update fires and increments it to 11. In the update trigger that fires after the workflow field update, the field value of the object obtained from Trigger.old is the original value of 1, and not 10.
- If a DML call is made with partial success allowed, triggers are fired during the first attempt and are fired again during subsequent attempts. Because these trigger invocations are part of the same transaction, static class variables that are accessed by the trigger aren’t reset.
- If more than one trigger is defined on an object for the same event, the order of trigger execution isn’t guaranteed. For example, if you have two before insert triggers for Case and a new Case record is inserted. The firing order of these two triggers isn’t guaranteed.
- In API version 53.0 and earlier, after-save record-triggered flows run after entitlements are executed.
Workflow Rules
Starting in Winter ’23, you can’t create new workflow rules. You can still activate, deactivate, and edit any existing workflow rules. To migrate existing workflow rules, use the Migrate to Flow tool. For new automations, create flows in Flow Builder.
Move Processes and Workflows to Flow Builder with the Migrate to Flow Tool
Use the Migrate to Flow tool to convert your Process Builder processes and workflow rules into Flow Builder, including scheduled actions. The tool also supports partial migration of processes for most actions.
Before moving your new flows to production, start with migrating and testing in a sandbox environment.
From Setup, in the Quick Find box, enter Migrate to Flow, and then select Migrate to Flow.
1. Select the process that you want to convert to a flow.
2. Click Migrate to Flow.
3. Select the criteria that you want to migrate.
If it’s a process, the Migratable column indicates whether you can fully or partially migrate the process.
4. Click Migrate to Flow.
If this is a partial migration of a process, click Needs Review when the migration is complete to see the list of actions that require additional configuration.
After you migrate a process or workflow rule, test the flow in Flow Builder.
If everything works as expected, activate the flow.
Deactivate the process or workflow rule you migrated to Flow Builder.
Planning Your Switch to Flow Builder
Migrate to Flow Tool Considerations
Workflow Rules and Process Builder are no longer the preferred tools for automating your business processes. With their pending retirement, now is the time to go with Flow Builder as the future of automated processes. Flow Builder is a foundation for the future and offers built-in extensibility, application lifecycle management, and faster performance.
Replace Time-Dependent Workflow Rules with Scheduled Paths
Add a Scheduled Path to a record-triggered flow. Scheduled Paths occur in the future, after the trigger has fired, based on dates and times. You can schedule such actions as reminders or follow-ups based on dates in the record that triggered the automation, such as Close Date. This feature also rechecks the entry conditions.
Example: Set your entry condition to Status = Escalated and then have an automation that sends a reminder two days before close. The reminder only sends if the status remains escalated.
Considerations
1. Processes with recursion aren’t fully supported. When a process with recursion is migrated, the record is evaluated only one time. Test and make sure that any processes with recursion work as intended after migration.
- Processes are migrated as Actions and Related Record-optimized (after-save) flows. If necessary, you can edit and optimize the flow for Fast Field Updates (before-save) after the flow is migrated.
- The invoke flow action is migrated as a subflow element instead of an invocable flow action. Subflows run in the same transaction as the parent flow. Any processes with invoke flow actions involving external callouts, external actions, or pauses must be redesigned using an asynchronous path.
- You can migrate scheduled actions only if you select the single criteria associated with the scheduled action. If multiple criteria are selected, no scheduled actions are migrated. After migration, scheduled actions become scheduled paths in a flow. In the flow, migrated scheduled actions follow the naming convention ScheduledPath_#. At run time, the new flow checks for pending actions from the original migrated process and then deletes them.
- You can’t migrate a cross-object reference in a formula.
You can migrate a process that uses a custom metadata reference in a formula. After the migration, the custom metadata reference is used in flow formulas, but you can’t configure it by using the resource picker.
- When migrating a time-based process, you must migrate each outcome to its own scheduled action flow. Then activate the new flows and deactivate the process.
- Supported Processes
The Migrate to Flow tool supports only record-triggered processes. Custom event and custom invocable type processes aren’t supported. The tool also doesn’t support processes that contain custom metadata types or criteria that contain a field that’s from a related object (field traversals). For supported processes, you can migrate these action types without additional configuration.
Record update
Record create
Invoke flow
Invoke Apex
Email alert
After migration, these action types retain their original positions in the flow, but they require additional configuration to function as expected.
Post to Chatter
Quick Action
Submit for Approval
Send Custom Notification
Live Message Notification
Send Surveys
Quip-related action types
Considerations for Migrating a Workflow to a Flow
If a workflow rule contains only field updates, the tool converts it into a fast field update (before-save) flow.
Due to their position in the order of execution, record-triggered flows can behave differently from similar workflow rules.
An at-rest pending time-based action is migrated to a scheduled path when the associated record is changed.
Supported Workflow Rules
The Migrate to Flow tool supports workflow rules that contain these items.
Field-based criteria
Field updates
Email alerts
Outbound messages
Time-dependent workflow actions
Rule criteria formulas that are set to true (unless the evaluation criteria are also set to created, and anytime it’s edited to subsequently meet the criteria)
Equal to null
Not equal to null
Rule criteria formulas
Workflow rules that contain the following can’t migrate with the Migrate to Flow tool.
Criteria with no defined workflow actions
Global variable fields
Fields on related records
Record types
The does not contain, includes, excludes, or within operators
The greater than, greater or equal, less than, less or equal operators on picklist fields
Formulas that use Hour, Minute, Second, TimeNow, TimeValue, IsClone, or $RecordType
Tasks
Relative date values in date fields
Multiple currencies
Choose Which Salesforce Flow Feature to Use
Use Flow Builder to automate most of your organization’s repetitive business processes. More features can provide further automation functionality, including approval processes, Flow Orchestration, Einstein Next Best Action, and Apex.
To determine your automation needs and which feature to use, ask these questions.
When do you want the automation to start running?
What do you want to happen after the automation starts?
For example, when you add a contact, you want the contact to receive a welcome email.
Start: When a contact is created.
Automation: Send an email to the contact.
What Can Start or Trigger a Flow?
FLOW STARTS OR TRIGGERS FLOW TYPE TO USE FOR EXAMPLE, YOU WANT SOMETHING TO HAPPEN…
When a record is created Record-Triggered When a new case is created.
When a record is updated Record-Triggered When a lead’s status field is changed.
When a record is created or updated **Record-Triggered When an account is created or the account priority field is changed.
When a record is deleted Record-Triggered When a contact is deleted.
After a certain amount of time Record-Triggered A week after a quote is created. Add a scheduled path to the record-triggered flow.
At a specified time and frequency Schedule-Triggered Every Saturday at midnight.
When a user clicks a button on a form Screen - When a customer enters contact information into a flow screen and clicks the Next button.
When a user clicks a quick action button Screen When an employee clicks Request PTO on their employee record. Opens a form to complete.
When a user clicks a custom button or link Autolaunched When a user clicks a Complete Sale button after closing an opportunity. Starts background automations, such as updating records and emailing stakeholders.
When called by another flow Autolaunched or Screen When a flow executes another flow within the same running instance to reduce repetition within the main flow.
When called by Apex code Autolaunched When an Apex class is triggered by a change to an opportunity’s stage, which triggers an autolaunched flow.
When a platform event message is received Platform Event–Triggered When an integrated printer is out of ink, it publishes a platform event message.
What Can a Flow Automate?
AUTOMATION Example
Create records Create an account.
Update records Change a contact’s address.
Delete records Delete a user’s permission.
Send an email Send an introductory email to a lead.
Collect input from external users with an online form Let new customers add themselves to your contacts using an online form.
Collect input from internal users with a form placed on a Lightning page or launched by a button Create an account, a contact, and a case quickly with one simple form placed directly on support reps’ Home pages.
Send a custom notification Notify managers when significant opportunities are won.
Send a survey Send a customer satisfaction survey after an opportunity is closed.
Submit a record for approval Require that managers approve discounts.
Run another flow in the context of the current flow Run another flow that creates a contact within your account-creation flow.
Access external systems Call actions registered by External Services to insert details from an external banking system into a Salesforce record.
Call a custom invocable action Execute a custom Apex method that uses the InvocableMethod annotation. You decide what the action does.
Send outbound messages Initiate the reimbursement process for an approved expense report by sending a message to an external HR system.
When Do I Use Another than Flow Tool or Feature?
WHEN YOU WANT TO… USE… FOR EXAMPLE, YOU WANT…
1. Approve records through multiple levels in your organization. Approval Processes Two levels of management to review and approve employee PTO request records.
2. Suggest offers and actions to users that are tailored to meet your unique business criteria. Einstein Next Best Action To prompt agents to offer service contracts to customers who don’t have them.
3. Coordinate multiple flows, and assign them to multiple teams or individuals. Flow Orchestration An automated hiring process that involves HR, Finance, and the hiring team.
4. Perform an operation for more records than scheduled-triggered flows allow. Batch Apex To update all your 600,000 contacts at once.
5. Perform CPU-intensive operations. Apex To calculate a highly complex discount rate.
Einstein Next Best Action
Display the right recommendations to the right people at the right time with Einstein Next Best Action. Create and display offers and actions for your users that are tailored to meet your unique criteria. Develop a strategy that applies your business logic to refine those recommendations. Your strategy distills your recommendations into a few key suggestions, like a repair, a discount, or an add-on service. Display the final recommendations in your Lightning app or Experience Builder site.
Einstein Next Best Action is a solution that uses flows, strategies, and the Recommendation object to recommend actions to users. You can display these recommendations on many different types of pages, including Lightning pages in your Salesforce org, Experience Cloud sites, or external sites.
Recommendations are displayed to users with the option to accept or reject the recommended action. Each recommendation contains an image, important text values such as button text and a description, and an assigned flow that runs when a user responds. They can be stored and referenced in the Recommendation standard object, or they can be manually assembled when building a strategy.
Strategies determine which recommendations to display to users, based on your data and business processes. When you set up Einstein Next Best Action on a page, you assign a strategy to that location, which then defines the recommendations that appear there.
You can control which recommendations are displayed in any situation, even if your org has a large number of recommendation records. Strategies can filter recommendations based on any available value, including recommendation fields, fields related to the running user, and fields related to the record that’s currently displayed.
Important In Flow Builder, you define which recommendations are displayed by making sure that they’re in the outputRecommendations collection variable at the end of the flow. In Strategy Builder, you define which recommendations are displayed by making sure that they’re not filtered out when they reach the Output element.
Einstein Next Best Action Example: Offer a Gift Basket to Each Account
To configure this Einstein Next Best Action recommendation:
- Create an action flow that executes when the gift basket recommendation is accepted.
- Create a recommendation that specifies how to present the gift basket offer.
- Create a recommendation strategy flow that determines when and how the recommendation is presented.
- Add a Next Best Action component that displays the recommendation on the Account record page and executes the strategy.
Create an Action Flow
Create a flow that collects the recipient’s name and address and sends an email to the shipping department.
From Setup, in the Quick Find box, enter Flows, select Flows, and then click 1. New Flow.
2. Select Start From Scratch and then click Next.
3. Select the Screen flow type and then click Create.
To collect the recipient’s name and address, add a Screen element to the flow.
Enter a label and API name.
Drag the Name and Address components to the canvas and assign an API name to each. Click Done.
4. To create the text of the email message to send to the shipping department, click New Resource in the Flow Builder Toolbox. If the toolbox isn’t visible, toggle the toolbox icon in the upper left corner of the Flow Builder canvas.
Add a Text Template resource type.
Enter EmailBody as the API name.
In the Body area, enter the email text, inserting the name and address resources.
Click Done.
5. To create a task for the shipping department, click + below the Screen element and add an Action element to the flow.
In the Action dropdown list, enter Send Email and select the Send Email action.
Enter a label and API name.
For Body, select the EmailBody text element.
Enter a subject line.
For Recipient Email Addresses (comma-separated), select Include and add the email address of the shipping department.
To allow rich text formatting for the message, select Include and select the True global constant.
Set any other values as needed.
Click Done.
6. Save the flow and name it Gift Basket Offer.
7. Activate the flow.
8. To return to the Flows page, click Back.
Create a Recommendation Record
Create a recommendation that specifies how to present the gift basket offer.
From the App Launcher (App Launcher icon), in the Quick Find box, enter Recommendations, and select Recommendations.
1. Click New.
2. Enter a name and description for the recommendation.
The description appears in the Next Best Action component on the Lightning record page.
3. For Action, select the action flow that you created.
To add an image (optional), click Upload Image and follow the instructions.
For best results, use a 1000 px x 380 px image at 72 dpi or one with a similar ratio.
Enter text for the acceptance and rejection buttons.
Select the target audiences for the recommendation.
Click Save.
4. The Is Action Active checkbox is automatically selected, which makes the recommendation available to Einstein Next Best Action.
Create a Recommendation Strategy Flow
The recommendation strategy flow determines when and how the recommendation is presented.
From Setup, in the Quick Find box, enter Flows, select Flows, and then click 1. New Flow.
2. Select Use a Template and then click Next.
3. Select the Recommendation Strategy flow type and then click Create.
4. To specify which records to use for the recommendation, add a Get Records element to the flow.
Enter a label and API name.
Select the Account object.
In the Filter section, add the condition Id equals recordId.
Select the options to store all records and all fields.
Click Done.
5. To load possible recommendations into the strategy, add a Get Records element.
Enter the label Get Gift Recommendation and the API name. Get_Gift_Recommendation.
Select the Recommendation object.
In the Filter section, add the condition Name contains Gift Basket.
Select the options to store all records and all fields.
Click Done.
6. In Flow Builder, you define which recommendations are displayed by making sure that they’re in the outputRecommendations collection variable at the end of the strategy flow. The next step uses the Assignment element to add the recommendations to outputRecommendations. To learn how to use the Limit Repetition element to assign the outputRecommendation variable while also limiting the number of times that the user sees the recommendation, see Create Recommendations Based on Customer Satisfaction Scores.
7. To move the recommendation output out of this flow so it becomes available to Einstein Next Best Action, click + below the Recommendation Assignment element and add an Assignment element.
Enter a label and API name.
For Variable, select outputRecommendations.
For Operator, select Equals.
For Value, select Recommendations from Get Gift Recommendation.
Click Done.
8. Save the flow and name it Gift Strategy. Activate the flow.
Display the Next Best Action Recommendation
Display the Next Best Action recommendation on the Account record page.
- Open an Account record page.
- Click the Setup icon (Setup gear icon), and select Edit Page.
Drag the Einstein Next Best Action component to the desired location on the page layout. - Add Gift Basket Offer as the component title.
- For Strategy Source, select Flow Builder and then select the name of the recommendation strategy
- Save your changes.
Return to the Account record and refresh the page.
The recommendation is displayed. If the account rep clicks Yes, a form opens with entries for name and address. Completing the form generates an email request for the shipping department to fulfill the order.
Einstein Next Best Actions Considerations
Einstein Next Best Action relies on flows, recommendations, strategies, and components, and has standard objects for reporting.
Flows
1. All Recommendation objects reference a flow. If you don’t have any flows, you can’t surface a recommendation.
2. Strategies only load recommendations with active flows.
3. When a flow is executed via REST API, the flow runs in the context of the user who is authenticated via REST API. The running user’s profile and permission sets determine the object permissions and field-level access of the flow. We recommend that you create a profile and permission sets for users who run the flow.
Recommendations
1. Consider adding a custom category field to the recommendation object and layout. A category field gives you more control when loading, sorting, and filtering recommendations and more options when creating flows.
2. Create names, descriptions, acceptance labels, and rejection labels that are appropriate for your intended audience.
3. Reusing a recommendation name creates a recommendation. It doesn’t overwrite an existing recommendation. Duplicated names can cause strategies to display duplicate recommendations to customers.
4. All flows, both inactive and active, display in the Action dropdown list. After you save your recommendation, you can see if the flow is active.
You can create a recommendation based on a flow that isn’t active, but no strategy loads it until the flow is activated.
Strategies
1. All strategies require at least one recommendation.
2. In Strategy Builder, you can load and filter the records of a Recommendation object. Or load and filter the records of any object, and convert them into recommendations at the end of the strategy using the Map element.
3. Load elements require at least one criteria.
4. Strategies only load recommendations that are based on active flows.
5. The Limit Reoffer element in Strategy Builder lets you hide a recommendation from all users based on its responses. A recommendation is hidden if users respond more than a defined number of times within a defined number of days. For limit reoffers to work, recommendations must have a unique record ID. If you want to continue to test a recommendation as a flow-entry point, delete individual records from the Recommendations Reaction table with Rest API calls:
~~~
GET /connect/recommendation-strategies/reactions
{ onBehalfOf: “005B00000018jK4IAI” }
//Returns a list of reactions
//For each result, if the reaction matches the strategyId of the strategy you’re testing:
DELETE /connect/recommendation-strategies/reactions/${reactionId}
~~~
6. Strategy Builder is available only in Lightning Experience.
Tracking and Reporting Reactions
1. For strategies created in Flow Builder, create custom report types using the Recommendation Strategy Metrics and Recommendation Responses primary objects. For strategies created in Strategy Builder, create custom report types using the Recommendation Strategy Metrics and Recommendation Reactions primary objects.
3. For reports created from the Recommendation Reactions primary object to correctly display the recommendation source name and ID for limit reoffers, recommendations must have a unique record ID.
Einstein Next Best Action Entitlements
Einstein Next Best Action has usage-based entitlements. All orgs receive a free monthly allowance of Next Best Action requests. If your usage exceeds your allowance of free monthly requests or any entitlements that you purchase, Salesforce contacts you to discuss additions to your contract. To track your usage, from Setup, navigate to Company Information.
Next Best Action entitlement usage is based on a rolling 30-day period, beginning when the org is created. Entitlement usage listed on the Company Information page in Setup is based on the calendar month’s usage, not the rolling 30-day usage.
Einstein Next Best Action: Next Best Action Request
A request is a call to the Next Best Action engine that causes a strategy to run and return recommendations.
Each time a page with an Einstein Next Best Action component is loaded or refreshed in a browser, Salesforce generates a new request. For example, when a case status changes from New to In Progress, the data change on the page triggers a refresh. This action also applies to the Actions & Recommendations and Suggested Actions components.
Requests are also made when:
A field is updated on a record detail page that includes the Next Best Action component.
A user enters data in the Subject or Description field of a site contact support page that includes the Next Best Action component.
Another way to make a request is to call a Next Best Action REST API resource from your own web app. You can also call Next Best Action REST API resources from an iOS or an Android app. The app can make requests in response to a custom UI and return recommendations.
Paying customers can see the number of requests their org has made by navigating from Setup to Company Information, Usage-based Entitlements, Maximum Next Best Action Requests available.
Einstein Next Best Action:Recommendations
Recommendations are standard Salesforce records, similar to accounts and contacts, that are processed by strategies and associated with flows. Strategies determine which recommendation records are surfaced using business rules, predictive models, and other data sources. The result of this process is context-specific recommendations that you present to your users.
Optionally add a custom Category field to the Recommendation object and the Recommendation Layout. Adding a custom Category field can simplify loading, filtering, and sorting recommendations in Strategy Builder.
Note:
Salesforce has both a Recommendation object for Einstein Next Best Action (that’s this page) and a Recommendation component for Experience Builder sites. The Recommendation component isn’t related to Next Best Action.
If you don’t see Recommendations in the App Launcher, in Setup, select Default On in the Recommendations tab settings for your user profile or permission set.
You can load and filter the records of a Recommendation object. Or load and filter the records of any object, and convert them into recommendations at the end of a strategy using the Map element.
Einstein Next Best Action:Launch a Flow When a Recommendation Is Accepted or Rejected
Each recommendation is associated with a single flow. By default, Next Best Action launches a flow when a user accepts a recommendation. The flow then performs an action, such as updating a case or sending an email. But you can also launch a flow when a user rejects a recommendation, which gives you more flexibility. For example, a flow could run an automated process, write to another system, or create a reminder email when a recommendation is rejected.
For example, at a telecommunications company, the admin configures the Next Best Action component to display recommendations to its customer service representatives (CSRs). When a CSR accepts a recommendation for a customer who wants to purchase a discounted service, a flow is launched to calculate the discount. The admin analyzes the reactions to the recommendation, and is confused about why the CSRs are rejecting it. To help get answers, the admin uses Next Best Action to launch a questionnaire flow every time the recommendation is rejected.
This feature is available for:
The Einstein Next Best Action component used with Lightning record pages
The Suggested Actions component used in Experience Builder
The Actions and Recommendations component used with Lightning console apps
To assign a flow that runs when a customer accepts or rejects the recommendation, create an input variable in the flow to accept the isRecommendationAccepted value. Then add a Decision element to the flow that’s based on that value.
In Flow Builder, configure a flow that’s associated with a recommendation. Be sure to activate the flow because Next Best Action can’t call an inactive flow from a recommendation.
Create the Boolean isRecommendationAccepted input variable.
Create a Decision element and use the isRecommendationAccepted variable in your outcome conditions.
Create a decision outcome for what the flow does when the recommendation is accepted.
Create a decision outcome for what the flow does when the recommendation is rejected.
When you add the Next Best Action component to a Lightning record page, select Launch Flow on Rejection.
Einstein Next Best Action:Add a Limit Repetitions Element to a Next Best Action Flow
You can add a Limit Repetitions element to your Recommendation Strategy flow to limit the number of times that the same recommendation or offer appears on the same record or for the same user during a time period.
You must have a collection of recommendations that has a valid value in the ID or RecommendationKey fields. The RecommendationKey value must be a database ID or have the syntax DYNAMIC_<custom>.
If you include an Assignment element, from Actions, choose Output from limit. Or you can skip this step and add the output from the Limit Repetitions element.
1. From **Setup**, in the Quick Find box, enter **Flows**, and then select Flows.
2 .Open or create a Recommendation Strategy.
3. After the collection of recommendations, add a** Limit Repetitions element**.
Enter a label and an API Name.
Add a description.
Search for and select the Recommendation Collection that you want to filter.
Select the responses that you want, and then enter the number of responses and days as whole numbers.
Look Within This Many Days is based on days, not hours. If the number of days is set to 1 for an accepted response, and the user accepts the recommendation at any time on Monday, the recommendation doesn’t display again until the start of Wednesday. So a one-day time period could be as few as 25 hours in duration or as many as 48 hours.
If you didn’t include an Assignment element, you can search for and select the collection that includes the limit repetition output.
In Advanced, select Manually assign variables.
From the Store Output Variables field, search for and select the output variable.
Click Done.
Save your work.</custom>
If you add an Assignment element after the Limit Repetitions element and change the label for accept or reject, you must update the limit repetitions output.
Einstein Next Best Action: Building a Strategy
A strategy determines when and how to present an Einstein Next Best Action recommendation on a Salesforce Lightning record page. For example, if you want to offer a discount to a subset of customers, create a strategy that collects the appropriate customer records and identifies the discount option to present. To create a strategy, you can use Flow Builder (recommended) or Strategy Builder.
A Flow Builder strategy specifies business logic and generates output for an Einstein Next Best Action component on a Salesforce Lightning record page.
In a Flow Builder strategy, you generate recommendations in either of the following ways:
Use predefined recommendations created in the Recommendations object. With this method, you create recommendations individually in the Recommendation object and then use them in one or more Next Best Action components. This method is best if you’re creating a small number of recommendations.
Create recommendations on the fly without using separate recommendation records. With this method, you create multiple recommendations dynamically in the strategy flow. This method is best if you’re creating a large number of recommendations. For example, if you have an extensive product list, you can create a different upsell recommendation for each product in the list.
Build a Strategy Flow Using Predefined Recommendations
Build a strategy flow based on predefined recommendations. This method works best if you have a small number of recommendations and want to make them available to multiple Einstein Next Best Action components. For example, you can create a recommendation that offers a discount to a customer. You can then use the same recommendation when creating a strategy for birthday discounts and for new customer discounts.
- From Setup, in the Quick Find box, enter Flows, select Flows, and then click New Flow. On the Alt + Templates tab, select the Recommendation Strategy flow type, and click Create.
- Load the records you want to use for your recommendation by adding a Get Records element to the flow.
Enter a label and API name.
Select the object to use for the recommendations, such as the Accounts, Cases, or Contacts object.
In the Filter section, add conditions to limit which records from the object are used in your strategy. - Bring a predefined recommendation into the strategy by adding a Get Records element.
Enter a label and API name.
Select the Recommendations object.
In the Filter section, use conditions to specify the recommendation that you want to use. - Add other flow elements as needed to define the strategy.
Make your recommendation available for use in an Einstein Next Best Action component. - Add an Assignment element.
For Variable, select outputRecommendations.
For operator, select Equals.
For Value, select the predefined recommendation. - Save your flow.
Activate your flow.
Build Strategy Using On-the-Fly Recommendations
Build a strategy flow with multiple recommendations that you create dynamically in bulk. For example, you can create a strategy that offers a different upsell recommendation for each product in your product list. With this method, you create recommendations directly in the strategy flow without using separate Recommendation records.
- From Setup, in the Quick Find box, enter Flows, select Flows, and then click New Flow.
On the Alt + Templates tab, select the Recommendation Strategy flow type, and click Create. - Load the records you want to use for your recommendations by adding a Get Records element to the flow.
Enter a label and API name.
Select the object to use for the recommendations, such as the Product object.
In the Filter section, add conditions to limit which records from the object are used in your strategy. - Add a Recommendation Assignment element.
Enter a label and API name.
For Record Collection Variable, select the variable that you generated with Get Records.
When you select the variable, the target fields are populated automatically.
Set values for the target fields:
AcceptanceLabel—Button label to accept the offer.
RejectionLabel—Button label to reject the offer.
ActionFlow—API name of the flow that performs an action when the offer is accepted or rejected.
Description—Text that appears above the buttons in the Next Best Action component.
Make your recommendation available for use in an Einstein Next Best Action component. - Add an Assignment element.
For Variable, select outputRecommendations.
For operator, select Equals.
For Value, select the recommendation from the Recommendation Assignment step. - Save your flow.
Activate your flow.
Einstein Next Best Action: Display Recommendations
After creating a strategy, choose a page to run your strategy and display your recommendations. You can use a Lightning record page, an app’s home page, an Experience Cloud site page, a Visualforce page, or an external site, depending on where you want recommendations to appear.
Lightning Page (Lightning App Builder):
In Lightning App Builder, create, edit, or clone a record page.
Drag Einstein Next Best Action from the component list to the location on the page where you want to display it.
Choose an action strategy and the number of recommendations that you want the component to display.
An App’s Home Page:
Create a strategy for the Next Best Action component. Use global variables such as $User.Id when you create the strategy. Use global variables because the home page isn’t a record page and isn’t associated with objects, like Case, Account, or Product.
Navigate to your org’s Home page.
Click Gear icon, and select Edit Page.
From the list of Lightning components on the left (1), drag the Einstein Next Best Action component to the home page (2).
Experience Builder Site Page (Experience Builder):
In Experience Builder, create or edit a site page.
Drag Suggested Actions from the component list to the location on the page where you want to display it.
Visualforce Page: Use Lightning Out to add the lightning:nextBestAction component.
Automated Actions
An automated action is a reusable component that performs some sort of action behind the scenes—like updating a field or sending an email. After you create an automated action, add it to a process, milestone, or other automated process.
Action Type:
Workflow Rule Process Flow Approval Process Entitlement Process
Email Alert x x x x x
Field Update x x x
Flow Trigger (Pilot) x
Outbound Message x x x
Task x x x
Email Alert Actions
An email alert is an email generated by an automated process and sent to the designated recipients. The action consists of the standard text and the list of recipients. You can use an email alert in an automation, such as a flow, approval process, or entitlement process. Legacy workflow rules and processes built in Process Builder or through the Invocable Actions REST API endpoint also use email alerts.
The daily allocation for emails sent through email alerts is 1,000 per standard Salesforce license per org—except for free Developer Edition and trial orgs, where the daily email allocation is 15. The overall org allocation is 2,000,000. This allocation applies to emails sent through email alerts in automations or REST API. Single emails sent to external email addresses are also limited, and how those limits are enforced depends on when your org was created.