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.
- > searchList = [FIND 'map*' IN ALL FIELDS RETURNING Account (Id, Name), Contact, Opportunity, Lead];
Account [] accounts = ((List