DEV Community

Mike Sedzielewski
Mike Sedzielewski

Posted on

Coding-free iterating on email content

In this guide, we demonstrate a tool for automating the creation of email campaign content. This proved to be super useful for developers and content teams who have to maintain a growing number of daily ops email templates. The setup is based on Contentful and the small, open source, Node.js application we’ve released.

The problem

Daily ops emails are one of the topics that are easy to start with but hard to master. It all begins with one or two plain text templates, then you want to enhance them with the company logo and maybe some big buttons instead of links. The template quickly becomes a simple HTML file. Editing at the stage is still fairly easy; want to update the messaging? Just send a new copy over to your developers and they modify that particular template - smooth.

The business is doing fine. You scale the company and expand the customer service processes. It quickly turns out that the number of email notifications grows. You come up with new user acquisition tactics and some sweet deals for your loyal customers. Again, the email campaign collection gets bigger and bigger. New country launch maybe? Now your email campaigns just doubled.

So, the old content has to be constantly updated. There’s a continuous stream of copies coming from marketing, product team (A/B tests), and legal. Not to mention the inevitable typos! Especially when your developer doesn’t know a word in German :) Therefore, you quickly end up with a dozen people exchanging the content, all packed into several Excel files and screenshots, burning developers’ time along the way.

The imperfect solution

One of the solutions is to tap into MailChimp. By using their email designer, you could let the “content people” update the email messages on their own. This can be tricky though.

Once you’ve given them the opportunity to change the content, they can change (or should we say ‘break’) the design too. Such bugs are really hard to track down, especially if your templates are huge HTML monsters.

So, ideally, you’d like to structure the email job as follows:

Content people can change copies only
Developers make sure that emails are delivered and that they look as designed

The less imperfect solution

TL;DR:

  • Let’s introduce Contentful and the Contentful-emails library.
  • Copywriters create/edit email copies in Contentful. They do this in so called “draft mode”. They can’t modify the HTML template in any way.
  • Before they actually push the message out to production, they can preview the final version of the email. This is achieved by visiting Contentful-emails web app, which renders a copy from Contentful on top of your HTML template.
  • If accepted, the copy goes to production.
  • In case you want to update any copy, you just change the status to draft and you can experiment again, meanwhile the old version still works fine on production.
  • Let’s run through the whole process with a bit more explanation.

Go to your Contentful account and create a proper content model for all emails. It should consist of 3 fields: a name (short text), a subject (short text), and a body (long text). (Contentful is fairly easy to operate. Having said that, if you’re not familiar with it, I suggest watching this guide)

Alright, so we have a model. Now let’s create the first entity. Let’s start with a dead simple ‘Welcome’ email. Select the “Add Email” button from the Content view.

The editor enables you to create a copy. You can use the markdown standard because Contentful-emails can parse it too. Notice that you can use placeholders (sometimes also called merge tags). The list of available placeholders is totally up to you, but you need to agree this with the development team first.

The copy draft is ready. Now let’s verify how it looks like in a final, HTML version. Run Contentful-emails and visit the “Drafts” section. Click on the template and the popup with the final email message will appear. The image below shows an example of an extremely simple template with a logo at the top.

Note that placeholders have been filled with exemplary values. If everything looks OK, go back to Contentful and ‘Publish’ the template to make it live! You can modify it anytime by setting it back to draft mode.

The backend part

Before you can do what we just described, you must integrate Contentful-email into your system. The first step is to configure and deploy the application. It basically comes down to filling config/base.js with your Contentful API uide.

After you run it, the app does the following:

  • It connects to your Contentful account to get both Draft and Published email content.
  • It loads your HTML email template you put to front-end/views/emails. (As the app uses a templating engine, you extend the current setup to handle multiple parent-child structures to reflect your process. E.g. invoice-related messages will have a different base HTML than drip-related).
  • It caches the templates so you can save your API calls to Contentful. The cache can be invalidated with a webhook when an entry is published.
  • It offers a fallback to JSON-based copy of all content, you can manually rebuild with this gulp task.

Cache invalidator - webhook setup

The last part is to agree on the placeholders the marketers can use in the copies. In our case, apart from the text variables or links (like [[phone-support]] or [[user-unsubscribe]]), we added the possibility of injecting HTML snippets. So, e.g. when you put __[[invoice-download]]__ the parser replaced it with a predesigned button with a proper link. In this way, the product or marketing team achieved almost unlimited flexibility in content restructuring within a given template.

Summary

To recap, we’ll just say that in one of our client's project this solution has reduced the number of redundant commits and subsequent deploys related to emails to almost 0. Now they have more time to come up with new coupon-based email campaigns!

The application is open source; if you see any room for improvements, submit a pull request!

Top comments (0)