Or, How To Put Templates In Your Templates

Removing code duplication is one of the most satisfying parts of refactoring and programming in general. The past few decades are littered with a variety of ways to detect and reduce duplication for many different types of code. Solutions range from IDE-assisted refactoring on the more complex side of things to various strategies for pulling in content fragments like header and/or footer, so common content can be centrally managed.

By now it’s perhaps obvious what we’re going to talk about in this article: how to support includes in SparkPost Templates. A quick disclaimer, this support will be provided as part of a client library, instead of directly in our service.

I’ll be modifying our Go client library (which I maintain) with this new functionality. While we’re in there, it’s only slightly more work to allow writing your own macros, with the function signature func(string) string – so let’s make some Macros!

SparkPost Templates: How do they work?

The short answer is they’re basically like Handlebars templates (docs here on our variant). The longer answer is that under the hood, while they technically support more stuff (like user-defined macros), it would be, let’s say, “unwise” to allow our users to write their own macro code that would execute on our system.

 

As our company has evolved over the past few years from traditional software to become a cloud-based service provider, parts of our mindset have shifted too. Before our cloud shift, a feature like Template includes would have been implemented “inside the box”, meaning as a customization inside the email server itself.

While this approach is certainly still possible, the system stays simpler and more flexible when functionality can be pushed outwards. Instead of building one specific “in the box” feature, when we can empower customers to build the features they want most, that lets us innovate elsewhere.

The Search For Template Includes

My first thought when starting to build this feature was: “Ok, what library am I going to use?” – however, it turned out to not be quite that simple. What we’re going for here is to allow users of our client library to pre-process templates before calling our API. This means only Handlebars blocks with locally-registered macros should be interpreted and replaced, not every block in the template. None of the templating libraries I found supported this kind of partial template execution.

Thankfully, the code to detect Handlebars blocks (see Tokenize) isn’t too out there, which makes partially executing templates quite a bit easier. Here’s an example of a made-up template you might want to partially execute before sending an email:

An advantage of this kind of approach is ease of integration between existing systems and SparkPost, letting users continue to use the same tools they’ve always used to build content. As long as the system can export over HTTP, content can be pulled into an email template. This is a somewhat contrived example, and I’m sure you’ll come up with some clever ideas for macros that we haven’t even considered. Let us know what you build!

The Template For Templating Templates

That’s all well and good, but how do you use the thing? The client library’s default behavior doesn’t change, so you’ll need to explicitly add calls to pre-process strings with your shiny new Macros. Here’s a list of the types and functions added for this feature:

Usage is simpler than the four (4) exported functions would imply. Check out the tests for examples. You’ll need to register some Macros with the appropriately-named  Client.RegisterMacro , and then call  Client.ApplyMacros to perform pre-processing on whichever strings might contain your Macros. The other two functions are there in case you’d prefer to do things differently than  ApplyMacros does – like having Metadata take precedence over  SubstitutionData , for example.

What’s Next For Template-y Templates?

You’ll notice the triple-curlies in the example template above. That’s a bit of a head fake. As of this writing, client-side macros treat double- and triple-curlies identically, with no escaping. For consistency with how SparkPost (and Handlebars) templates work, doubles should escape HTML in the substitution value, and triples should turn off the safety.

The careful reader will also notice that the feature, as written, is suitable only for single-Recipient Transmissions, or for multi-Recipient Transmissions using Templates that don’t have per-Recipient placeholders nested inside custom Macros. Supporting this use case would likely require modifying the Transmission payload to contain dynamic_html for the per-Recipient pieces, or unrolling the Transmission API call so the client library makes one call per Recipient.

Did you enjoy this post? Got a clever Macro to share? Let us know by commenting, or start a conversation on Github or send us a tweet.

-Dave

Sending Gopher Emails

So you want to send some email. And you’re using Go. Do I have some great news for you! I have done this, and you can too. We’re going to build a tool that I’ve appropriately named send-a-gopher which, unsurprisingly, sends you (well, somebody) a gopher.

This tutorial assumes you already have a SparkPost account and have created an API key. And that you’ve got Go installed on your system.

First! Pick a gopher to send

This is undoubtedly the hardest part. After careful consideration, and a quick right click, copy image address, there’s your gopher. Oh, right. We need some code too.

Et voila! An extremely limited in-memory version of curl/wget/etc! We can now get gophers.

Second! Set up the SparkPost package

Installing the package is arguably the easiest part:

And that’s it. Next we’ll import and configure the SparkPost package:

Third! Encase the gopher in code

We’ll get it from the HTTP response, wrap it up in an InlineImage and some Content, then send that off in a Transmission:

 

 

Last! Send, and admire your handiwork

This is the second easiest part:

Er, you get the idea.

Look at you now. With a free account and just a little bit of code, you’re sending yourself gophers. That was pretty easy, and there are more sending examples in our GitHub repository, specifically in the sparks tool, along with the complete version of the code we’ve dissected here. It even handles errors.

-Dave Gray