How I Solved It featuring Erick Mahle.

Use a Screen Flow to Avoid Duplicates in a Private Sharing Model | How I Solved It


Welcome to another “How I Solved It.” In this series, we do a deep dive into a specific business problem and share how one Awesome Admin chose to solve it. Once you learn how they solved their specific problem, you’ll be inspired to try their solution yourself! Watch how Erick Mahle improved user navigation within a private organization by creating a screen flow. This flow ensured data consistency by helping users find existing accounts to avoid duplicates and associate subsidiary accounts with their parent accounts, even if access was restricted.

Key business problem

“This doesn’t work for me. Can you just give me full access to Salesforce?” If you oversee a Salesforce instance at a company that uses Private organization-wide defaults, chances are you may have heard this one before. And while there’s no shortage of valid arguments for why you’d want to limit visibility to your organization’s database, the reality is that implementing it usually comes with some form of compromise.

One example is how to manage data. If you implement duplicate rules, setting them to ‘alert only’ can lead to backlogs of duplicate data (and a lot of manual labor to maintain/manage it). And if you flat out reject the creation of the record, you risk user adoption of the system as frustration among users builds.

Surely there’s a way to leverage out-of-the-box functionality to deliver a great user experience (UX) to keep both sides happy. Enter screen flows!

How I solved it

The solution is a screen flow packed with functionality to consolidate as many steps as possible in a way that helps users find what they need quickly and minimize the room for errors. The screen flow will run on Access All Data, meaning it will provide any user that initiates the flow with a controlled View All window into the company’s account database. Explaining it to an end user, the solution is very simple with just two screens.

  1. A screen to search the account you’re looking for by name or account number
  2. A screen that returns your results and helps you take any action that you need directly from there; this would include:
    1. Seeing a limited view of account details
    2. Requesting access to the account
    3. Creating a subsidiary account
    4. Creating a brand new account (if you really don’t find the account you’re looking for)

If you match this screen flow with removing their permissions to create accounts, you can ensure users will now depend on this flow to be able to create a new account (since the flow essentially runs as a System Administrator). You can also ensure the parent account is established, in case you’d like to notify teams from different divisions or territories that there’s activity within the accounts they own/service.

How I created the solution

Note: Account Teams must be enabled in Setup for this flow to work.

The screen flow is designed to look simple to the end user, but like many great UX solutions, some lifting may be required behind the scenes. Fortunately, we get to break down a lot of the great out-of-the-box screen flow functionalities we’ve used to deliver on this solution. So, let’s break this flow down in a few different sections.

  • Start screen
  • Query
  • Search results
  • Decision paths


An overview of the entire screen flow that allows you to get an admin view to search all accounts in the Salesforce environment.

The Start screen

As the saying goes, “You never get a second chance to make a first impression.” We start with an initial screen element that has a few tricks up its sleeve, thanks to reactivity and component visibility.

  • If you start searching by either field (Name or Account Number), we automatically hide the subsequent field to avoid limiting the results and not knowing why. That said...
  • If you search by account number, we reactively populate the account type to search for as “Customer”, as Prospects or other types of accounts typically are not assigned an account number until they purchase from our organizations. Every click counts!

If you haven’t worked with reactivity before, it’s all in the formulas. We create a formula aptly named “formulaCustomer”. We’ll set the radio button’s default value with that formula. The formula simply states that if the Account Number field is not blank, then return the value of “Customer”, which pre-populates the field with the right value.

A view into how a reactive radio button is set up.

A breakdown of the formula that powers the reactivity at the first screen element.

The query

Keeping up with best practices, we try to limit the amount of elements using Data Manipulation Language (DML), so we get all of the accounts we can that meet the initial criteria, and filter accordingly from there to return the records to display to our users.

A key note here: If your organization uses large data volumes, this logic may need to be reconsidered to ensure the performance of the screen flow. At some point, a developer who knows Apex can be a good colleague to call on.

A breakdown of the Get Records element to query all accounts, and how filters are applied as necessary to return the selected accounts.

We accomplish this by running our account query to get all of the matching accounts based on the information entered on the Start screen element. Based on what we can review what was selected on our radio button at the Start Screen, we take the necessary path to filter out any accounts based on their type, if needed. The crucial part is that we create an account record collection (which we named “collectionAccountResults”), which we use to set the results of our query through each path in the Account Query Check Decision element.

Demonstrates the use of an account record collection in a screen flow.

This allows us to use that new collection in the Data Table component that will follow. It also avoids the mess of creating multiple data tables depending on which option you’ve selected.

The search results

Once we have our query completed and have successfully found records, we return our search results in a neat data table. Since this is a Private organization-wide default scenario in our sharing settings, we limit a lot of the sensitive information that can be viewed in the data table.

Demonstrates a debug preview of a data table within the screen flow.

At the search results, we also introduce the “enableAccountCreate” boolean input variable. If you haven’t used input variables before, it allows you to dictate what kind of information gets fed into the flow before it runs. In this case, this boolean value allows us to turn on extra functionality. That way, this flow can be run one of two ways.

  • If set to False, it runs as a lookup-only (with no ability to create accounts).
  • If set to True, it runs pretty much unrestricted, with both lookup and create abilities.

Demonstrates different radio buttons depending on whether all functionality is enabled within a flow.

The component visibility set up to display elements based on whether a checkbox is selected to enable the necessary account creation functionality.

You’ll find several components in the screen elements and Decision paths (to follow) that reference this functionality. It’s a great use case for keeping screen flows incredibly flexible and serving multiple use purposes! Based on the input variable, you’ll be prompted with one of two radio buttons — one with the additional account creation options.

Finally, while on the topic of component visibility, we try to add an additional reminder (only if they select to Create a New Account or Create a New Subsidiary), where we ask them to consider very carefully before moving forward to avoid creating any duplicates.

The Decision paths

Once the solutions are neatly returned in a data table, we’ve mentioned that there are several options for users to select. Here are a few key technical highlights of each Decision outcome that can follow after the second screen element.

Back to Beginning

If a user chooses to go back to the beginning, we simply reset the variables to make sure there’s nothing preselected.

The Back to Beginning values being set in the Assignment element.

When it comes to the collectionAccountResults, we use the Remove All operator, as you cannot use the Empty String when working with variables that include multiple values.

No Selection

If you install the flow in a developer environment, you’ll find that the data table in the Account Search Results screen element does not require a selection — that is intentional, as no selection would be needed if they wanted to actually create a brand new account.

The No Selection value being set to highlight an error message for users.

In this scenario, we set a boolean variable to True to send them back to the last screen element and display a message that a selection is needed.

The Display Text component contains an error message and the conditional visibility rules to display it.

There are other ways to handle this scenario where this Decision path element might not be necessary: one way being with the clever use of Component Visibility to hide the data table when selecting Create New Account in the Account Search Results screen element. In this case, you can choose to make a single selection required on the data table, therefore using its removal from the screen to avoid its requirement. Doing so can avoid the No Selection Decision element entirely.

Request Account Access

This one builds on a feature that I’ve personally come to adore: Chatter. Effectively, it allows the user to select the access they would like, and it creates a Chatter post to the account owner specifying the request, which they’ll subsequently get as an email.

Chatter displaying the message that results when access to an account is requested via the screen flow.

If the account owner uses mobile, then they even get a push notification. Talk about delivering a great UX! To be able to tag the account owner, you have to simply add @[{your_variable_here}]. In this case, you’ll find the txttemplateChatterMessage text template and see the reference to the account owner from the account selected in the data table: @[{!datatableAccountResults.firstSelectedRow.Owner.Id}].

Create New Account/Subsidiary

Now we’re getting into account creation. To make the UX as positive as possible, when creating a new account, we request only the fields that are absolutely necessary. You can play around and add whatever fields are necessary. Both of these outcomes allow the user to create a brand new account.

If someone selected to create a subsidiary (effectively a child account), we take one step to set a few default values into our record variable called “varAccount”. We set the parent account as the account they have selected in the data table, set the account type as the same as the parent (which they can change if needed), and add a clever suffix to the account name, which says “, a subsidiary of” (parent account selected).

Displays the default value assignment for accounts that are to be created as subsidiaries.]

Formula expression to suggest a name to the subsidiary account to be created.

Using formula fields and hyperlinks, once the account is created, users can click the link and be redirected to their brand new account.

Display the use of hyperlinks within Display Text element with formulas.

Note that the formula used for the hyperlink (formulaNewAccountURL) does not require any hard coding, which means it should work regardless of whether you’re in a sandbox or production environment. If you attended FlowFest V2, you may remember that some of our competitors were challenged on that one!

View Account Team

Last but certainly not least, we display the full account team and a basic view into the account. This includes the account team (users and their roles) as well as all opportunities, without revealing any sensitive financial information. We’ll include two data tables: one for all account team members (and their roles) and one for the opportunities associated with this account.

For those that have tried to work with data tables, you may be aware that you cannot reference parent-level information. For example, when we display the opportunities, you can choose the owner ID field but you cannot display the owner name. Hopefully, that will be resolved at some point in the future, but for now, there’s a clever workaround.

Displaying the assigned values into a temporary Opportunity record variable.

Renaming a column in a data table to suit the temporary need to display parent-level data.

In the screenshots above, you’ll see how we loop the related opportunities to set the values for our opportunity data table. We borrow the opportunity Next Step field to house the opportunity owner full name. We include any other fields we would like to include as a column in the data table and add it to a Temporary Collection for a view-only purpose. In the account team members, you’ll find a similar step where we use Title to display the account team member’s full name instead of their user ID.

For FlowFest V6 watchers, you’ll see some of the top competitors in the world use this same trick to display leads and contacts within one data table!

With UX always top of mind, the final portion of this screen flow is a series of subflows to display a catered error message to users if they go beyond the intended path in a way that says “we see what you did here,” avoiding the common red-font fault message that can even confuse more experienced users.

Business results

Working with a focus group of sales users, we’ve demoed this solution several times and iterated based on their feedback to make this as useful as possible. This helped us tremendously to begin to improve the quality of our data. But there’s more to it than that — with improved data quality, here are some very tangible gains that executives appreciated.

  • Account hierarchies allowed us to start notifying associated users in parent accounts when activities occurred with child accounts, increasing visibility in cross-region sales efforts.
  • The creation of duplicate data with accounts was significantly reduced. Leveraging some In-App Guidance features on the existence of the tool, the Sales Enablement portion to get users using the screen flow was basically done for us.
  • Collaboration increased as Chatter started becoming more valuable for users with these notifications, demonstrating the value of the feed itself.

Do try this at home

Try it right now, actually! Sign up for a personal dev org or spin up a sandbox and use this very screen flow in your org environment. Find the link to the Unmanaged Package which contains this exact flow (and associated subflow) in the Resources section below. There are explanations within each Description element to guide you on why.

Bonus points: With Spring '24 upon us, you could even add Repeaters in the flow, allowing you to request access to multiple users within your org, all in one shot!


Want to see more good stuff? Subscribe to our channel!

Jennifer Lee and Stacy O'Leary in a new episode of "How I Solved It"

How I Solved It: Manage Contacts Who Have Changed Jobs

Welcome to another post in the “How I Solved It” series. In this series, we do a deep dive into a specific business problem and share how one #AwesomeAdmin chose to solve it. Once you learn how they solved their specific problem, you’ll be inspired to try their solution yourself! Watch how Stacy O’Leary gives […]