In Automation, Blog, Flow, Process Builder, Tips & Tricks

Sometimes there are multiple ways to complete the same goal within Salesforce. Not every method is going to be very admin-friendly. For example, I want to send an email when the Opportunity is closed won out to everyone in my company. In that email, I want to give a list of the Opportunity Products. Opportunity Products is a related list so I cannot use straight up merge fields on an email template. I could create a visualforce email template but not every admin will find that very friendly.

So what are my options?

The Options

I gave this some thought and came up with a few ways I could achieve my goal. During this part of my process there are no bad ideas. My whole goal is to list as many options as possible and then go through the list and throw things based on their pros and cons. This way, if a chosen method doesn’t work out I already have a list of backup options.

  1. Visualforce Template
  2. Apex to send the message and define the body
  3. Put the product information in a field on the opportunity *somehow*
  4. Send separate emails for each opportunity product
  5. Convince people we don’t really need product information in this email

I wanted this to be as Admin friendly as possible. I don’t want to spam people so sending multiple emails was out of the question. That meant I need to think how can I get Product information in a field on the Opportunity.

The answer hit me. I could use Flow.

Flow It Up

My Flow would actually be pretty simple.

  • Get the Opportunity ID
  • Use a Fast Create to get all the Opportunity Products
  • Loop through the Opportunity Products
  • Build up my data
  • Use a Record Update and set my new product data to an Opportunity Field
Product Rollup Flow

The Flow Rolling up the data

We can take this one step further. We can plan on using an HTML email template we can put HTML in our Opportunity field and create a nice looking table. That’s where the multiple Assignment elements come into play. I have a text variable called “vrOutput.” The variable default value is simply “”

If I wanted I could also put the headers here, but I decided to not have headers on my table. Each time I reference this variable in the loop I’m adding, or appending to that value.

The first assignment element is assigning a new row, “<tr><td>”

The next element is where I insert the Product information into the table.  I technically don’t need two assignment elements, but it just feels cleaner to me.

For screen capture purposes, here’s what it looks like with just the Product Name and Product Total.

Adding Product Information and HTML tags

Adding Product Information and HTML tags

For the example, I’m putting the final output on the description field. It looks like this on the record.
Product Rollup on Opportunity

Now that we have our fields created, we can create our email template. I’ll need an HTML or Custom email template so the HTML in the field renders properly. But we still have 2 issues. How are we going to launch this Flow and how will we send our email template.

Process Builder

We could use a Workflow Rule to send the email template, we could even do it in a Flow (send an email alert). We could also add a custom button that people must use in order to change their Opportunity to Close Won.

We could do that and would make sense if I were doing other things with Flow when the Opportunity moves to Close Won (like custom validation across related objects). I wanted something more simple

Enter Process Builder. I can call both my Flow AND my email alert as actions in the Process Builder. I just need to make sure that my Flow is the FIRST action in the list followed by the email template. Actions fire in the order they are listed (based on my experience thus far). If I was really paranoid, I would have Process Fire the Flow and then re-evaluate the process to see if our Field on the Opportunity got filled in and use that as the cue to fire the email template.


We have a lot more power now with Flow and Process Builder. I no longer need to create a visualforce template. What’s very cool is I’m not limited to the number of related objects I want to include! Want to include Products and the last 5 Tasks? No Problem! As long as you have a way to query it you can include the data.

What other ways can you see using this method of rolling up children information to the parent?


Recommended Posts
Showing 25 comments
  • Virginia

    Brian: I’m trying to write a flow where I read in multiple email addresses and for each email address I send an email. We’re trying to do this with Flows. I can get one email to go out, but when I have two folks (working with sObject Collections) it seems I can never get to the second record/email. Any thoughts or suggestions? I’m plowing through the Google trying to find a similar pattern that may have been used and documented by others, but I’m coming up a bit empty handed!

    Thanks for all your great work!

    • Brian Kwong

      How are you getting the email addresses? From a record or something else? Is it the same email? Are you sending via the send email action?

      • Virginia Leandro

        I have multiple records linked to a parent record. Each linked record belongs to a different “user”. So I’m collecting those email addresses into an sObject Collection variable that has two fields, the record ID and the email address. The email addresses are different. I can get it to work for the first email address, but the Flow I’ve built seems to never get to the rest of the email addresses.

        • Brian Kwong

          Are you using a loop element to go through the collection?

      • Virginia Leandro

        Yes…but I think I may have “stumbled” upon my problem. Thank goodness for “Screens” and the ability to debug. I’m trying to pull data from a formula field and what I need to do is get the User ID and pull their email directly from the User object.

        I’ll keep you posted how this progresses! I’ll be happy if I can get this to work and this was my problem…!

  • jtitus008Josh

    I’ve been trying to do something similar, but I can’t figure out how to get the HTML markup from my field to work in the Custom Email template I’m using. Right now when it fires everything works great except the HTML renders as plain text within my email template from the merge fields. How did you escape Salesforce wanting to set your merge field to plain text?

  • Matt

    Hi Brian,

    Apologies if this is a dumb question but html isn’t something I have much experience with and I’m struggling to see how this can work.

    When the value of the opportunity description field is passed into the html mark up via a merge field in the custom template builder I would have thought anything in that field would be rendered between text area tags, as the field is of type ‘Long Text Area’ in Salesforce?

    I don’t see how you managed to get the field value from the opportunity description field to render as html and not as a separate text area that will just show the text value of the field, ie “TheWizardNews”, did you use something I’m not aware of in the html mark up in the template?

    I tried this quickly and I got the results I expected (everything in the text field displaying as text including the tags), If you could explain how you got this to work I’d really appreciate it as I’m keen to see this solution working.


    • Brian Kwong

      Matt, There are no dumb questions.

      Interesting. This USED to work. I would use an HTML or Custom email template and it simply took the HTML from the long text area and displayed the rendered results. It may have gotten changed in a release.

      • John Norman

        I think perhaps it did change. I’m getting the same results. Bummer.
        I have a need to create an email that the user can edit before sending, but I also have the requirement to include related list items in a table as part of that email. I can do this with Conga Composer, but would love to do this with existing functionality in SF. I’ve been able to create the email in a VF Email template, but of course that can’t be edited before sending. 🙂

  • Tam Wong

    Thanks for this blog, Brian. I have a similar use case, but not sure if it’s possible with a process builder launching a flow.
    The process builder is on the Account object. When criteria are met, I want to send an email alert to all the contacts related to the Account. Only related contacts with a specific checkbox enabled will receive the email alert.
    The process builder action would be to launch a flow. The flow will lookup all the contacts with that checkbox enabled and then store them in a Collection Variable. Then email alert will be within the same flow and will go out to all the contact records in the Collection Variable.
    Is this possible with process builder + flow?


    • Brian Kwong


      I haven’t tried this out yet, but you could forseeably use a collection variable to collect the emails and then send it out. My concerns will be the number of contacts that could be on the account. You could also send them one at a time but again that might hit limits.

      Another options, and this is a bit on the evil lazy side. Is when the criteria is met it checks a box on all contacts that should get an email.

      Then you have a contact process which will send the email and uncheck the box.

      Cascading processes work, but it is a cascade. So you’ll want to check to make sure you don’t hit any limits with any apex you may have written on those two objects. You could get around that by making the contact update a scheduled action if you needed to.

      Let me know what you decide to do and how it works out

      • Tam Wong

        Hi Brian,
        I created a flow with a Fast Lookup element on the Contact object. I filtered this element to only lookup contacts that have an Account ID that equals the AccountIDVar variable and checkbox1__c equals TRUE. I stored the contacts as an SObject Collection Variable called {!PortalUserContacts}. I am saving the ID and Email fields in this collection variable (not sure if I need the ID).
        Then, I used a loop element to loop through my collection variable and my loop variable is {!PUContact}.
        Finally, the third and last element on my flow is the Send Email element, where the Body is a text template I created, the Subject is just text, and for my recipients, I used Email Addresses (comma-separated).
        I made sure to have a start element in my flow. I activated it.
        This flow is launched from my process builder that operates on the Account object (when created or edited). When the criteria are met, my Immediate Action is to launch the above flow. The confusing part is when I’m trying to Set Flow Variables. There are 3 of them. I know the AccountIDVar should reference the [Account].Id, but I’m not sure what to do with the other two flow variables (PortalUserContacts and PUContact). One of them is the SObject Collection variable and the other is the loop variable. I don’t see what to reference them as on the Account. Do they need to be set at all?
        I tested my work and so far, I’ve only been able to see one email sent out, even though I have multiple related contacts with the checkbox enabled.
        Do you know what I’m doing wrong? I spent hours getting to this point, but at a loss with this approach now. I think something might be wrong with how I’m using the collection variable or the setting the flow variables.
        I prefer to get this approach working before I attempt the option 2 you suggested with the cascading processes. I did give that a quick try, but not sure if the second process should start when it’s invoked by another process or when a record is updated.

        • Brian Kwong

          You could probably invoke the process. You wouldn’t need the extra checkbox to say send the message then, just go by your original criteria.

          As for your flow, I would add a email action before your send email and have the body include your variables so you know what the value is. It may be that the values are set properly and that’s why you only get 1 email. Also make sure it’s different email addresses you’re sending on the contacts.

          Finally, as for your process builder calling the flow, any variable you marked as Input or Input and Output will be visible in Process Builder. You only need to select the ones your flow needs. In your situation it’s likely just the AccountID. All other variables should stay as private. It’s more secure that way

          • Tam Wong

            I ended up adding an Assignment element to the flow. The loop element goes to this Assignment element as a Next Element and the Assignment element goes back to the loop element. The Assignment element has a variable {!contactemail} and is assigned the loop variable, {!PUContact.Email}. The loop element has an End of Loop that goes to the Send Email element and the Recipient is assigned the variable in the Assignment element. I think it seems to be working so far.
            The only issue is that the process builder that launches this flow will only fire when an account is created or edited to meet the criteria. There are many dormant accounts in the system that will never meet this criteria without intervention. That’s something I’ll have to think about and decide on. For now, I’m good.
            Thanks for your help, Brian. I really appreciate it.

  • Justin Dover

    Brian KwongOctober,

    I hope this is a easy question for you.

    I have set up a button, that sends a custom email temple to a customer, “home owner invoice”. Using /_ui/core/email/author/EmailAuthor?rtype=003&p2_lkid={!Opportunity.JobContactId__c}&p3_lkid={!Opportunity.Id}&retURL=%2F{!Opportunity.Id}&p5={!$User.Email}&template_id=00X41000000WDOF

    I have set up a process builder that also does this when moving to “final invoice sent to customer” stage with a balance. Then wait counters to reactivate every 15 days till balance is 0.

    Now my problem:

    Both work, but when the button is clicked. It logs it in the opportunity under Activity History as EMAIL: Final HO Invoice. However when the process builder sends it, it will not log it under the activity history. Do you know why this is or how to fix it. I have read 100’s of google search results and i can not find a answer to this.

    We need this to be able to prove how man times the customer has received and been notified of their balance.

    • Brian Kwong

      yeah, this has to do with Process Builder sending emails. Same thing happened with workflow rules. Unfortunately, there’s not a setting to change or even a future update that I”m aware of that will let you do this.

      The closest you can do is add an action to the process to add a task in addition to sending the email. This is a royal PIA to deal with but that’s the only way I know of – to date – to send email through PB and have it log the email got sent

  • Andy Bazouk

    Hey Brian and co, thanks for this excellent and insightful post. Piggybacking on the most recent comments, I am evaluating a use-case where I want to send an HTML Email (that sobject) to Contacts when the record they are associated to is updated to meet criteria to send an email

    HTML Email allows us to track all the user interactions against that email– a lot of suggested solutions indicate I would need to reference Salesforce’s Email Apex classes, but could I solve this with Visual Flow?

    • Brian Kwong


      I’m not sure of a way to use the HTML email method so it gives you that tracking capability. The only ways I know to send email out with Flow is either using a Email Alert or the Send Email action (which doesn’t really support HTML). The only other method I found is using an APEX Plugin,

      But that doesn’t give you that HTML email record so you can see if it was opened or not. Personally,if the tracking is the primary goal, I wouldn’t use Salesforce. I would get an email platform that gives you the tracking and use a MailTo: hyperlink ( to open up the email program of the user.

      There are plugins out there for Outlook and Google that would even let the user select an email template (I like Cirrus Insight. For transparency purposes my employer Better Partners is a referral partner of that company) from Salesforce to send. I don’t think you can automatically pick the email template using the hyperlink method.

      So no good ways that I know of to automatically send email in automation using the HTML email method that gives you that tracking

  • Alex Waddell


    I have created a flow that creates an HTML table, the unfortunate news is that when i send the email using a HTML Template, i do not see a table.. I am just given the string of code that my flow created

    The email looks like this:


    Outreach Health is reimbursing Vendor A for the following Invoices

    Invoice NameInvoice NumberInvoice AmountI-00132,925.16I-05800

    Was there a change in this functionality that no longer allows this workaround to be used?

    • Alex Waddell

      I just noticed that the comment section removed all of my HTML like my table’s tr’s and td’s

      Still i think you know what i am getting at 🙂

    • Brian Kwong


      This is a 3 year old pre-lightning solution. It is entirely possible Salesforce made some changes that prevent this from working. I won’t get a chance to test this setup again for a few days, but in the meantime some questions:
      1. Are you using Lightning or Classic?
      2. Are you sure your HTML is valid? If you copy/paste it INTO the template and do a test send, does it render appropriately?

  • Adriana

    Hello, is this option available in Lightning? or what’d be the best and easiest way?

    • Brian Kwong

      This really want’s a classic or lightning function. It was taking advantage of how email templates were reading the HTML in the text fields. Whether this works with a Lightning email template I can’t speak to since I haven’t tried it.

pingbacks / trackbacks

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.