Business Problem

My organizations has partnerships with different online education vendors such as Ukueoke, Fender Play, and MasterClass. These companies provide us with In Kind Donations of access codes. Our constituents can then request codes.

In the past, people had requested one code at a time.

However, a unique issue came up in 2019 when a vendor donated 8,000 codes, and constituents could apply for an unlimited number of codes. One person requested over 300!

We needed a way to send teachers codes in a way that would not mean sending, like, a billion emails.

My first attempt at solving this was to build a system in Flow that automatically assigns codes to Contact (more on that in at another time). Then, I created a Conga template that printed all of the Special Codes related to an application.

I needed to use Conga Conductor to send these out in mass (at one point we had about 400 to send out.) This got expensive at ~$1.00 per send.

Data schema spaghetti :-)~

How I Solved It

Using this blog post as a guide (like, amazing? THANK YOU), I went to play in my Sandbox. I created three components:

  1. An Apex Controller
  2. A Visualforce component
  3. A Visualforce email template

Da Controlla

A controller allows us to use code in email templates and Visualforce pages.

NSFW probably?
public class SpecialCodeController

## Gives the thing a name

{
    public Id teacherAppId {get;set;}

## Gives the Teacher Application record a place to live called TeacherAppId and sets permissions/says "welcome!"

    public List<Special_Codes__c> getCodeList()

## Creates a cradle for the baby codes

    {
        List<Special_Codes__c> codeList;
        codeList = [SELECT Name, Type_of_Code__c, Code_Expiration_Date__c, MasterClass_Code__c, FourChords_Code__c FROM Special_Codes__c WHERE Teacher_Application__c =: teacherAppId ORDER BY Name ASC];
        return codeList;
    }
}
##Adds the baby codes to the codeList. We know they're the right ones because of the WHERE clause which references the teacherAppId variable above! Cool!

Visualforce Component

A Visualforce Component takes the code from above and makes it usable! It’s like a widget according to this help article.

This Component is called specialCodeVis.

<apex:component controller="SpecialCodeController" access="global">
## References the controller above

<apex:attribute name="teacherAppIdVis" type="Id" description="Id of the Teacher App" assignTo="{!teacherAppId}"/>     
##Creates an attribute called teacherAppIdVis that references an ID to a Teacher Application that we will add later

<table border = "2" cellspacing = "5">
#This is a table created with in HTML. Brings me back to my Neopets days!
<tr>
<td>Name</td>
<td>Code</td>
</tr>
<apex:repeat value="{!codeList}" var="code">

##An apex:repeat iterates over a list. The variable for each Special Code in the query is "code". That's how we get this table to be dynamic.

<tr><td>{!code.Name}</td>
<td>{!code.MasterClass_Code__c}</td>
</tr>

</apex:repeat>
</table> </apex:component>                                      

Email Template

Finally, we can pipe the Visualforce Component into a Visualforce Email Template! Exciting!

    <c:specialCodeVis teacherAppIdVis="{!relatedTo.Id}" />
##OMG! This references the Visualforce Component and defines that the variable will be the {!relatedTo.Id}**

**Side note: I also learned that the “relatedTo.” tag in Visualforce email templates are a GREAT way to get merge fields many layers deep in an email template using dot notation :o) Good bonus from this project. However these templates can be pretty annoying to edit without admin privileges.

Final Product!

This is the Visualforce email template we built. The table is what we built with this code!
Thanks to our marketing team for providing 🔥 copy

Implementation Notes

  • I deployed the three items above from my Sandbox into production using a change set.
  • Make sure that the Security on the Controller is set so that anyone using the template (or is the running user on an automation that uses the template) is able to access it. After I deployed this, one of my users had a permissions issue and I had to add some profiles to the Controlla.

Conclusion

This will likely save us thousands of dollars in automations (For instance $1 per email x 5 partnerships x 500 emails per partnership = $2,500). It’s worth noting that I built the expensive solution to begin with, though. :’)