codeblog: programming html emails with sailthru’s zephyr code

So the past couple weeks at Sailthru, I’ve really settled into the day-to-day routine pretty nicely. We’ve had a steady amount of work, which has generally been a mix of building out raw html emails templates and programming those templates with Sailthru’s Zephyr scripting language.

I thought I’d try something new this week. Rather than doing a general overview of the work week and dropping in a few animated gifs for comedic value, I thought I’d dig into the code a bit and explain a little more about our process for adding programming snippets into html emails. Here goes…

Most of the coding work we do within emails consists of accessing JSON feeds to pull specific data points into email templates. For example, this past week, I needed to edit a few templates for an ecommerce client. The example I’ll feature here was a simple product template that accesses their JSON feed for two product types: “active collections” and “ending soon.”

The email template is a fairly clean and simple layout, which you can see here. Overall, looping through arrays of products and pulling in specific data points is actually quite easy using Sailthru’s own Zephyr scripting language. For example, a typical loop might look like this:

If you need to access a set number of items in the array, then you can use their “slice” function, which takes three arguments: the array you want to target, the index number of the array where you start, and the number of items you want to access ( like so: {foreach slice(content,0,5) as c} ).

This is all fine and dandy when you’re just working with pure JSON data sorting through objects and the like. Where it gets a bit more complex is when you have to repeat specific blocks of html email code in the template. These, of course, can be rather long blocks of html due to all the tables, rows, and inline styles needed for html emails.

For example, in the template linked above, you can see that each product collection includes a few items to display (including an image, link, description, and date), and that makes up a specific block of code we will need to repeat based on the collection of items coming through in our array. So, if we wanted to run a Zephyr “foreach” loop and “slice” our a set number of items, while also repeating that entire block of html for a single product item, we’d like to do something like this:

However, after each item there’s going to be some kind of dividing space in the email, which means we either add a simple “spacer” table data element (to take up a small space in the template), or we need to start an entirely new row. Luckily, because each row in the template consists of a pair of items, we’ve got an easy solution based on whether each item is odd or even. If it’s a single item, we just add a space in between the table data elements. If it’s the second item in a row, then we need to start a new row and add a different type of placeholder element.

So, we just need to add a conditional “if” statement to determine whether or not we need to start a new row and we need to have a way to check if the item is odd or even. Of course, we also don’t want to leave an empty space if there’s only, say, five items in our collection (since there’d be an empty space where the sixth item would need to go in that row). To do all of this, we add the following steps:

1) check the length of the array and see if it’s divisible by 2 (modulus).

2) if it’s an odd number, we subtract 1 so that it resets it back to an even number and we complete a pair of products for the row (this assumes an array of more than two items/products).

3) then we run the foreach loop and include the index of the array ( like this: {foreach slice(active,0,a) as i, c} — here “active” is our content array, “0” is the index number where we start, “a” is the total number of objects/items to loop through, and “i” is the index number of the array which we’ll need to check to determine whether or not we start a new row).

4) and finally, after all of our content items (name, date, etc..) have been displayed, we then add a conditional statement to either 1) insert a simple table data spacer between products (after one item is displayed in the row) or 2) start a new row (which requires a new table row).

So, here’s how that full block of code would work:

Lastly, you may have noticed that this handles only the top section of the email. Section two of our email for the “ending soon” items actually has three items per row. Luckily, we’ve done most of the work already, so we can basically just use the same code as above, but do our modulo with three instead of two. That way, we get three items per row instead of two.

~~

To recap….we had a very simple loop for accessing our product content that was made a bit more complex due to the format and setup of the html email. Overall, the task wasn’t bad, but it was made much more difficult by a lack of clear comments in the raw html email I started working with. The template I received did not include any comments as to where sections of the email started/stopped, so half of the battle was figuring out how it was set-up and, more importantly, where it would break if I repeated or failed to repeat any of the right html tags.

It took a few tries to find the right spot, and I eventually got it. But this was yet another lesson in the importance of including comments.

Although I am sure I am guilty of doing this at some point, I’m now of the firm belief that coding without good comments is basically “pure evil”…kind of like Newman:

http://youtu.be/Asv4IbNQ1Iw?t=2m20s