Today’s the day: Write your first Visualforce email template!

I shied away from Visualforce email templates for much longer than I should have. Mostly because there was never a burning need for me to create anything. Then, two situations arose that called for some snazzier email templates than plain text could provide. Time to write some Visualforce!

Visualforce templates are good for when you want to render information conditionally and/or you want to show a list of related records. You can’t render information conditionally in a plain text email or HTML email. And you certainly can’t show a list of records.

Read on for two examples and code samples that you can copy + paste!

The Conditional Render

I do best with real world examples, so here’s an example of a plain text email that needs a serious refresh:

V.1: Lots of superfluous information.

This email gets the job done but is missing a few things:

  1. Clear formatting that explains what the user should be looking at. There is no bolding or anything so it’s easy for the eyes to glaze over.
  2. Usage of “1” instead of “Yes.” It’s not fair to assume that your users will understand a boolean value (notice how I wrote the little explainer at the bottom to be on the safe side).
  3. There are no notes about the lead’s marketing…yet that label is there. 😕

Okay, so all the important information is there just not presented in the best light. Don’t let the perfect be the enemy of the good. Notifying your users certainly beats the alternative! But, if you’re interested in cleaning up the template slightly — read on.

V.2: Cleaner, strategic bolding, and only rendering information that matters to the user.

Let’s dig into the nuts and bolts of the code that fuels this email.

Lines 1–7: Setting up our email with a series of opening tags (if you scroll down to lines 41–44 you’ll see the closing tags). The body of your email need to be in between these tags.

You can declare who the recipient will be and what object you’re referencing — in this instance a lead.

Lines 10–17: This is the main body of the email that provides all of the lead’s contact information. Something that is frustrating with Visualforce templates is the UI doesn’t provide the merge fields for you. I recommend opening up your field list for the object in question so that you can quickly reference what their API names are.

The <apex:XX> tags are specific standard components to Visualforce and each have individual behaviors. Salesforce lists all the components available in their documentation.

<apex:outputLink> is giving me my record link. Note that my instance is not hardcoded — this is a best practice. You can feel free to copy that exactly, since it’s what I did. 😇

Lines 21–24: I used the Visualforce component <apex:outputPanel> because I wanted to render all the information below depending on whether it was visible or not.

Another way to do this would be to make each line render conditionally, but it was creating a lot of weird whitespace so I went with this solution.

The rendered aspect has me checking 6 boolean fields and 1 text field to see if they are true/populated. If so, then continue to render the information below.

Lines 27–33: This is where I conditionally render the field labels and values of my boolean and text fields. I have the following fields: Restaurants, Food & bev manufacturers, Grocery, Higher-ed Admins, K-12 Admins, Agency, and Media Kit Comment.

If any of these fields are true, I want to render the label I’ve created and bold it. For example: Media Kit Comment: I’d like to purchase $100K of advertising ASAP!

I have to conditionally render this because just because Agency is true doesn’t mean I want to the field label for Media Kit Comment to show!

Lines 35–44: This is the rest of the email, and I’m closing out the tags. Notice I put a little more text after </apex:outputPanel>. If I had put it inside the tags, it would have also rendered conditionally.

The List of Related Items

Another good Visualforce email use case — what if you wanted to show a list of records related to an object, such as opportunity line items? Completely doable with the <apex:repeat> component.

Here’s an example of an email that we send internally to another department. The parent object is called a Project and the child records are Project Tasks:

This Project had 2 related Project Tasks that needed to appear in the email.

Lines 9–15: Some styling that I just left in there because I borrowed this template heavily from another template. You could remove it if you don’t care about the table headers/rows are rendered.

Lines 19–25: I am creating the labels for the columns my table will have.

Lines 27–36: This is where the magic happens. ✨ Using <apex: repeat> I’m able to set a variable name (pt) for my related object Project Tasks and iterate over them. I also utilized <apex:outputPanel> because I only wanted to render specific records. If you want to show everything, you wouldn’t need this part.

Note the pluralization! I initially wrote {!relatedto.AcctSeed_Project_Task__r} when it should have been plural. This absolutely killed me when I first started. Read this for more details on object relationships. I’m still not great with this.

Lines 37–50: This is closing out the email with all the tags, very similar to the first email.

Lines 55–71: This is actually the same email — just in plain text format! Given that this is going to an internal user and I know their email can handle it, I probably don’t need it. But leaving it in case you have a use case for it!

Line 73: Everything needs to stay inside the final </messaging:emailTemplate> component.

If you try to build a template, let me know in the comments!

Further reading:

Creating a Visualforce email template (Salesforce docs)

Not so scary VF templates for admins (Jan Vandevelde’s blog — and what inspired me to write this post)

apex:outputPanel render logic (StackExchange post)

Thanks to Jan Vandevelde and Peter Churchill for their help while I tackled these two email templates. ☁️

Leave a Comment

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s