Image of Sarah Pilzer next to text that says, "Automate This! — Use Loops in Record-Triggered Flows with Sarah Pilzer".

Automate This! — Use Loops in Record-Triggered Flows with Sarah Pilzer

By

Welcome to another “Automate This!” In this live-streamed video series, we cover all things automation, from use cases and best practices to showcasing solutions built by #AwesomeAdmin Trailblazers like you. With automation, you can remove manual tasks, drive efficiency, and eliminate friction and redundancy. In this episode, four community Flow experts showcase a Flow feature you can use in record-triggered flows. This blog post covers the Loops feature Sarah Pilzer showcased during the episode.

What is a Loop?

Sometimes when working with multiple records in Flow, it’s necessary to perform an action on an individual record at one time instead of acting on the collection as a whole. Let’s say you have a collection of records and you want to update the same field on each of them with the same new value. Unfortunately, you can’t just use a single Assignment element for all the records at once. You have to look at each record individually, assign the new field value, then move on to the next.

This brings us to the definition of a Loop according to the official Salesforce Help documentation:

A Loop is a Flow logic element that takes a collection of items (aka records) and uses a loop variable to store the values for the current item in the collection. When the Loop finishes examining an item, it copies the field values for the next item into the loop variable. To reference each collection item in elements along the loop path, use the loop variable. To keep changes made along the loop path, add the loop variable as an item in a new collection variable.

Example of a record-triggered flow with a Loop

If you’re anything like me, you might have been confused by that last paragraph about Loops, collections, and variables. It’s generally accepted that Loops are among the more challenging Flow features to master for both new and experienced admins alike. But don’t worry, I’m going to break down, step-by-step, how Loops can work in record-triggered flows using an example from my favorite fictitious nonprofit, the Otter Appreciation Society (OAS).

Let’s explore how OAS uses campaigns to track donations to its organization. In the Nonprofit Success Pack (NPSP) data model, every contact belongs to an account with a special Household record type. Multiple individuals from a single household can belong to the same campaign, each with their own campaign member junction record. The fundraising team at OAS has asked me, the Salesforce Admin, to set up automation so that when the campaign member status is changed on one individual in a household, the other household member statuses are also updated.

1. Configure entry criteria

Here’s a record-triggered flow I created to solve the requirements of the fundraising team. It’s pretty simple with only five elements total, three of which are specifically part of the loop.

The flow starts with entry criteria set so that the flow will run any time the Status field on a campaign member record is changed.

Configured record-triggered flow with a Loop.

Start element in the record-triggered flow.

The flow is optimized for actions and related records, meaning it will run after the triggering record is saved to the database.

Flow is optimized for Actions and Related Records.

2. Get the household campaign members record collection

The first step of the flow is to find all campaign member records that belong to the same household and campaign as the triggering record. This is achieved with a series of filter criteria using fields from the Campaign Member object and the special $Record global variable that’s available in record-triggered flows. It also will filter out the original triggering record so we don’t accidentally update it again. Notice that the Get element is set to store “All records” which means it will return a collection variable instead of a single record variable. In the next step, we’ll use a Loop to go through each record in the collection and separately change the status before moving on to the next item.

The Get Records element to get the campaign members.

3. Configure the Loop element to iterate through campaign member collection

The next part of the flow is where the magic begins! The Loop element is configured to take the collection of campaign members that were just retrieved using the Get element and to cycle through it, starting with the first item found and then proceeding until the last item is reached.

Configured Loop element.

The Loop element of the flow.

 

You might notice that the Flow element isn’t actually doing anything to change the items in the collection itself. It’s just a bit of logic to tell the flow which direction to move in. If you’re using Auto-layout mode when you add a Loop element to the flow, it will create two new paths: For Each and After Last. To update the items in the collection, we need to put additional elements along the For Each path, which will be executed on each record in turn as the Loop cycles through the collection. After all items in the collection have gone through the For Each path, the Loop is considered done and the flow continues down the After Last path to execute any additional actions.

 

4. Assign a new status to the current loop variable record

We are now along the For Each path created by the Loop element and are ready to add an Assignment element that will update the record that’s currently stored in the special loop variable. This helpful tool tip on the Loop element configuration screen explains how to access that record by typing the API name of the Loop into the left-hand side of the Assignment, and then using the value from the $Record variable to set the current record’s status equal to the value in the same field on the triggering record.

Helpful tool tip for working with Loops.

A configured Assignment element for storing a value in the Loop variable.

5. Assign the current record to a new collection

If you recall back to the Help definition of Loops, you know that in order to “keep changes made along the loop path, add the loop variable as an item in a new collection variable.” The new status value we just assigned to the record currently stored in the loop variable will be replaced in the next iteration by whatever value is in the next household campaign member record in the original collection. That means if we want to save our work, we need to store it somewhere first, like in a new collection that we can use to update records after the Loop is finished.

I created a record collection variable called “cobj_CampaignMember_Update” to hold the records with the new status values.

Record collection variable to hold records to be updated outside the loop.

Then, I added a second Assignment element on the loop path that takes the record in the current loop variable and adds it to the “cobj_CampaignMember_Update” collection variable. We’ll use the same variable in an Update element after the Loop is completed.

An Assignment element configured to Add the current loop variable to a record collection.

6. Update all records after the Loop finishes

I know what you’re thinking… Wouldn’t it be easier to just use an Update element in the Loop path instead of creating a new collection? Tempting as it may be, it’s against best practices to query, create, update, or delete records inside of a loop.

That’s because the Update element, like the Get, Create, and Delete elements, uses Database Markup Language (DML) to interact with your Salesforce data, which takes processing power and time. To ensure that resources are shared fairly among all Salesforce users, a single flow is limited to 150 DML statements and can process only up to 10,000 records at a time. While that may seem like a lot, when you put a DML statement inside a loop, it’s possible to hit the limits very quickly because you consume a DML statement each time the loop fires. Conversely, storing the loop variable in a new collection during each iteration does not require DML and can take advantage of using a single Update element to write all the changes to the database at once after the Loop has completed. This concept is called “bulkification” and is key to making efficient Loops in your flows.

Let’s apply bulkification to our example flow. The previous step mentioned using an Update element with the “cobj_CampaignMembers_Update” collection variable to tell Salesforce which campaign member records to update with the new status value.

Configured Update element that updates all the records in the record collection variable.Highlighting the Assignment elements.

This element is placed on the After Last path so that it will only execute after the loop is completed.

7. See the flow in action!

Now that we’ve completed our Loop and activated the flow, we can watch it in action by going to a campaign record and opening the Campaign Member related list. Let’s say that one of our favorite donors, Otto May Shawn, just sent in a check for the 2022 Summer Appeal. When we edit Otto’s campaign member status to “Donated”, the record-triggered flow kicks in and his partner Flo’s status is also automatically updated at the same time!

Animation showing that updating one campaign member status triggers an update on another campaign member from the same household.

What’s next?

Hopefully, this blog post has helped demystify the basic concept of looping in Flow and you can now adapt this example for other use cases. For example, consider adding a Decision element within a loop to decide whether to act on a record or not depending on its values, or use Assignments to set up tasks related to the loop collection records. Once you grasp the power of Loops, you’ll start to see many ways you can apply them in your automations to repeat actions more efficiently!

Resources

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

SUBSCRIBE TODAY
Copy Files from One Object Record to Another.

Copy Files from One Object Record to Another | Automate This!

Welcome to another “Automate This!” In this live-streamed video series, we cover all things automation, from use cases and best practices to showcasing solutions built by Awesome Admin Trailblazers like you. With automation, you can remove manual tasks, drive efficiency, and eliminate friction and redundancy. In this episode, see how Eric Smith created a subflow […]

READ MORE
Eliminate Manual Record Matching.

Eliminate Manual Record Matching | Automate This!

Welcome to another “Automate This!” In this live-streamed video series, we cover all things automation, from use cases and best practices to showcasing solutions built by Awesome Admin Trailblazers like you. With automation, you can remove manual tasks, drive efficiency, and eliminate friction and redundancy. In this episode, Christina Nava uses a screen flow to […]

READ MORE
Harness Custom Settings and Flow for Dynamic Round Robins.

Harness Custom Settings and Flow for Dynamic Round Robins | Automate This!

Welcome to another “Automate This!” In this live-streamed video series, we cover all things automation, from use cases and best practices to showcasing solutions built by Awesome Admin Trailblazers like you. With automation, you can remove manual tasks, drive efficiency, and eliminate friction and redundancy. In this episode, see how Warren Walters creates custom Auto […]

READ MORE