"How I Solved This" episode with Sarah Pilzer and Marc Baizman

How I Solved This: Display Available Campaigns on an Opportunity with Flow


Watch Sarah walk us through her innovative solution in the new, “How I Solved This” video series, and read all the details in the post below.

Key business problem

I want my users to know what campaigns are available when adding influence to an opportunity without referencing a separate contact record. Often, the primary contact record for an opportunity will belong to multiple campaigns, so it’s difficult to know which one(s) should be assigned to influence the opportunity. Finding a list of related campaigns requires the user to open the primary contact record, thereby navigating away from the opportunity, and then return to the opportunity record once they’ve decided which campaign to assign. Wouldn’t it be better if the user could see a list of potential campaigns right on the opportunity record?


The Country Dance & Song Society (CDSS) is a nonprofit arts organization with the mission to connect and support people in building and sustaining vibrant communities through participatory dance, music, and song traditions that have roots in English and North American culture. Like many nonprofits, CDSS relies on donor support to fund its programs. 

The Development department at CDSS runs several different fundraising campaigns each year to bring in money from target contacts. These campaigns may be running concurrently, and it can be difficult for staff to know which one is the best fit for any given donation. For example, a donor recently had lunch with the executive director, received a follow-up phone call after a concert, and is also on the monthly newsletter mailing list. Which one (or more) of those touches influenced their subsequent donation?

Example of a contact in a campaign history

Because it’s not always apparent which campaign has influenced an opportunity, we decided to not use the automatic campaign influence model at CDSS. Instead, when a donation check arrives, a team member from Development must decide which campaign(s) to manually relate to the opportunity via an influence record. The art of donor management relies on staff having a full picture of a donor’s interactions with the organization (that is, their related campaigns) when assigning influence to opportunities. And since nonprofit staff time is so precious, wouldn't it be great to display that full picture on the same opportunity record screen where the campaign influence is assigned?

How I solved it

I created a Screen Flow that displays a list of campaign names for the primary contact role, and then deployed that flow via a component on the Opportunity Lightning page.

1. Assign a group of contacts to campaigns using a report

When starting a new fundraising campaign, make sure that everyone you’re going to solicit is included as a contact in that campaign. Most of our campaigns start with a list that we generate using a contact report. For example, let’s say we’re creating a new campaign for major donor outreach. First, we generate a report that filters for contacts that gave more than $500 either last year or this year. This filter utilizes roll-up fields from the Nonprofit Success Pack (NPSP), which you may not have in your org but the same principles apply to any report you create. The basic idea is to get a list of contacts that we will then relate to a campaign.

Example image of assigning a group of contacts to campaigns using a report.

Example image of assigning a group of contacts to campaigns using a report.

Once we’ve built the report, we simply run it and use the dropdown menu next to the Edit button to add these contacts to a campaign. If you’ve set up custom campaign member status values for your campaign, you can select which status to give these contacts when adding them to the campaign. Who knew populating campaigns could be so easy?!

Example of adding a contact to a campaign. Example of adding contacts to a campaign.

2. Set up Opportunity Contact Roles

After we’ve established which contacts are in each campaign, we can utilize the relationships between contacts and opportunities to generate a list of campaigns to be displayed. Opportunity Contact Role is a junction object that creates a relationship between a contact and an opportunity. Opportunities can have multiple Contact Role records, and you can optionally mark one record as primary. NPSP automatically adds a donor Contact Role to household opportunities and marks it as primary. In the next step, we will build a flow that relies on the presence of a primary Contact Role. So, if you have not yet set up Contact Roles in your org, you’ll need to do so before this method can work. This help article walks through the setup process. 

3. Create a Screen Flow

Now that we’ve associated contacts with campaigns and with opportunities, we can use Flow to display campaigns on an opportunity.

Image of a special recordID variable.

The first step in the flow is a Get Records element with Filter Conditions to find the first Opportunity Contact Role record that is marked as primary and related to the opportunity.

Example of a screen flow.

Image showcasing how to Get Records for the Opportunity Contact Role.

We check if such a record was found with a Decision element because without a primary contact there’s no way to determine which campaigns are relevant. If no primary is found, then the flow will display a simple message to that effect on the screen.

Image showcasing user searching for a primary contact. Image that shows there is no Primary Contact assigned to an opportunity.

Otherwise, proceed to a second Get Records element to find the Campaign Member records where the ContactId is the same as the ContactId on the Contact Role. In this case we want to store all the records found.

Image of Campaign Member records.

Now we have a collection of Campaign Members that we can loop through to extract the associated campaign names and construct a list for display. 

Official Flow Tip:To use the current item in other elements in the loop, use the API name of the Loop element. Example: If your flow iterates over accounts with a Loop element named "My_Account_Loop", you can reference the current item from that Loop element. Just start typing "My_Account_Loop" and select Current Item from Loop My_Account_Loop.

For each campaign member in the collection, we store the name of the related campaign in a text variable named CampaignName.Image of a text variable named CampaignName.

The Development team has an additional request that they be able to see active campaigns separate from inactive campaigns. To achieve this, we create additional text variables to store the ActiveCampaignList and InactiveCampaignList, and then use a Decision element to determine which list the current campaign name belongs on.

Image of a text variable named Campaign Active Status.

Once we know which list we’re working with, we can add the CampaignName we stored earlier with an additional LineBreak constant to the list variable.

Image of the CampaignName variable we added earlier. Image showcasing how to add a line break to the list variable.

After we’ve added each campaign name to the list, the loop ends and we move on to the final screen element where we can display the list using a text display component. I added a set of radio buttons to allow the Development team member to choose which list they wanted to see displayed. The radio button choices are used to control conditional visibility on the text display components so only the specified list will show; but the default is to show both lists so that when a record opens, all the campaigns are displayed.

Image showcasing how to use a text display component.

4. Embed the flow on the Opportunity Lightning record page

Now that we have a working flow, it’s time to activate it and add it to the Opportunity page. We can do that using the standard Flow Lightning component in the Lightning App Builder. Simply drag and drop the component onto the page canvas, and then use the properties tab to specify which flow we want to run. 

Remember that special recordId variable? Because we specified it as an input variable, we can use the component to pass the opportunity’s record ID value into that variable for use in the flow.

Image showcasing how you can use the component to pass the opportunity’s record ID value into that variable for use in the flow.

After the Lightning record page is saved and activated, we can look at an example to see that now there’s a list of associated campaigns displayed right next to the related list where the Development team will assign campaign influence. So handy!

Image showcasing an example of the associated campaigns we just created.

Business results

We’ve achieved our goal of showing the relevant campaign data where Development staff need it most and helping them process donations more efficiently. Less time lost clicking between tabs means more effort spent on cultivating relationships and raising funds to support critical mission work.

Do try this at home

As a nonprofit Director of Operations, I’m always thinking of ways to improve upon existing processes, including the example in this post. Here are a few ideas I’ve had that could make this solution even better:

  • Create Campaign Influences within the flow - Flow has the power to do more than just display information on a page. We could use the information we’ve already collected to allow users to select a campaign from the list and then automatically create the Campaign Influence record for the opportunity. If you wanted to get really fancy, you could probably devise a way to allow multiple campaign influences split by percentage or amount.
  • Add the Contact to a new campaign - Let’s say there’s a campaign running that the primary opportunity contact does not yet belong to. Instead of needing to go through step one of this example, we could do a lookup of all campaigns and then use the embedded flow to allow the user to add the Contact to the campaign from the opportunity.

Let us know what you thought of this solution, and tell us how you want to use it with #AwesomeAdmins #HowISolvedThis.

Relevant Trailhead badges

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