Table of Contents

Templates

Purpose

Flowmailer supports the use of templates, allowing you design and send beautiful e-mails without having to build them in your source systems. Users have full control over their templates by editing HTML or using our WYSIWYG Quick editor for basic editing. We also provide full design, HTML and template scripting services to provide working solutions.

Our templates are based on the Freemarker template engine, which allows for template logic ranging from simple to very complex. Personalization, conditional content, (nested-) loops and much more. Flowmailer adds it's own functions such as <@onlineLinkUrl/> to make working with e-mail easier. Are you a developer? Just convert your existing in-memory order to JSON and send it to Flowmailer, we'll send a nice order confirmation to the customer.

Flowmailer also has unique capabilities in re-using content from the message that the source sends. This enables our customers to send great looking e-mails without having to change how the source system sends e-mail. We can just wrap the entire message with a header and footer or select specific parts (or even specifiek fields) from the original message.

Quick editor

Apart from the complex logic that our templates can contain, many templates are mostly just text and images with some embedded variables. Flowmailer allows for editing those parts of templates without any code editing at all, using our visual Quick editor.

Template engine

Freemarker

Rather than reinventing the wheel, Flowmailer chose to integrate the well known and freely available Freemarker engine as a basis for our templates. This means most of the syntax and built-ins supported by Flowmailer templates can also be found in their documentation. Flowmailer adds specific functions that are designed to help Flowmailer usecases, such as including 'view online' links and marking regions as editable using our Quick Editor.

Applicability

Flowmailer supports templates in many situations. The most obvious one being HTML templates. But also, anywhere we want to make something more flexible, we use templates. For example, you can use all template functions described on this page for a Subject FlowStep, allowing you to use variables there or even add some conditional logic. Other places we have full template support include Text templates (also for SMS) and URLs settings in the External Content and External Data FlowSteps.

Please be aware that templates enable great flexibility, but you can also easily break things. Be careful when editing templates that are actively used. Flowmailer will verify the validity of templates when you save them, but some things can only be evaluated at runtime. If you do break something and cause an error, Flowmailer will send the affected messages to the "Held messages" list and raise a notification. You can then read the error message, fix the problem and choose to retry the held messages.

Basic usage

Variables

You can use variables to store information such as text and numbers, but also as a reference to other structures such as a list. Variables can be referenced in templates, for instance to print text in a certain place. All data available in the context of a Flow are made available as variables for use in templates. When the source sends text called 'firstName', this code would print the contents:

${firstName}

In some cases, you might want to access variables that are nested in a structure called a 'hash'. For instance when you have an order confirmation and you need its id. This is how you get it:

${order.id}
Alternate/default values

Usually, the next question is: "What if the variable is missing?". Good question! Basically, we want you to make explicit decisions on what needs to happen when certain data is missing when you're sending a message. That's why all used variables are mandatory and will result in an error when missing. You can change this behavior by adding an "!". You can also, optionally, provide an alternate value:

Dear ${firstName!"customer"},

If the firstName variable is missing, the alternate value will be printed:

Dear customer,
If

If conditions can be used to make parts of your template conditional. Content and template logic (for instance another if) can be mixed within the conditional block. For instance, if you only want to display shipping information if relevant:

<#if shippingMethod == "regular">
  Your order will ship as soon as possible!
</#if>

If statements can also contain multiple conditions and have "elseif" and "else" clauses. Please refer to the Freemarker documentation for more examples.

List

If you have a list of items, for instance an order containing order lines, you can use the list directive to handle them one by one. This is often used in conjunction with HTML lists or tables, where each item represents a new row:

<table>
  <#list order.lines as line>
    <tr>
      <td>${line.description}</td>
      <td>${line.amount}</td>
    </tr>
  </#list>
</table>

Special functions

View online

Creating a 'View online' link requires special code, because it's different for every message and not yet known when the template is applied. We dealt with that for you by creating a special macro for this:

<a href="<@onlineLinkUrl/>">View online</a>

Please note that an Archive FlowStep is required if you want to have a view online link, since that's what we will link to. If one is missing but a template requires it, messages will be held. The Archive FlowStep does not need to be set before the Template that refers to it, so you can still for instance insert it at the end of the Flow.

Editable regions

If you want to make regions of a template editable using the Quick editor (real templates only, not applicable to FlowStep settings), you can mark it like this:

<table>
  <tr>
    <td>
      <#-- REGION: intro -->
      This is a text.
      <#-- END REGION: intro -->
    </td>
  </tr>
</table>

Every region in a template needs to have a unique name (in this case "intro"). We advise keeping the regions as small as possible, containing only paragraphs of text or other single elements such as a table cell containing a logo image. Using a visual editor to edit more complex structures, although allowed, is tricky and might produce unexpected results.

Include

It's also possible to include other templates. This allows for reusing (parts of) templates. Examples of this include headers, footers, and banners. Having these in separate templates means you can edit them in one place and change them in all relevant messages at once.

Suppose 1040 is the ID of another template in the same account containing a shared footer. Code for including it would look like this:

<#include "1040">

Please note that Editable regions are disabled when using the Quick editor on the 'outer' template. This prevents accidental changes that affect other templates.

Special variables

There's a number of special variables available for use in Flowmailer message templates:

Variable Description Example
flowmailer.account.id ID of Account 0246
flowmailer.account.description Description of Account MyAccount Production
flowmailer.source.id ID of Source 1234
flowmailer.source.description Description of Source Webshop
flowmailer.flow.id ID of Flow 5678
flowmailer.flow.description Description of Flow Order confirmations
receivedMessage.id Flowmailer Message ID 201512161426489b63289c577efc89e2
receivedMessage.sender (SMTP) Sender address support@flowmailer.com
receivedMessage.from From header Flowmailer Support <support@flowmailer.com>
receivedMessage.recipient Recipient address support@flowmailer.com
receivedMessage.subject Message subject This is a test subject
receivedMessage.headers['Content-Transfer-Encoding'] Headers quoted-printable
currentMessage.sender (SMTP) Sender address support@flowmailer.com
currentMessage.from From header email address support@flowmailer.com
currentMessage.recipient Recipient address support@flowmailer.com
currentMessage.subject Message subject This is a test subject
currentMessage.headers['From'] Headers Flowmailer Support <support@flowmailer.com>
currentMessage.headers['header name'] Headers
inPreview If in editor preview true

Original content

Retrieving body

For basic 'wrapper'-style templates, you often just want the original message body, and place it somewhere in your template. You would need the following code to do so:

<html>
  <body>
    Insert original body here:
    <@extractFromOriginal />
  </body>
</html>

By default, Flowmailer will search for the <body> contents in the first HTML message part. If missing, the first Text part will be used, enclosed by <pre> tags.

Extracting elements

It's also possible to use CSS selectors to find specific elements from the original message. Most types of CSS3 selectors documented by the W3C should be supported. We will list some often-used examples here:

Selecting an element with ID 'someid':

<@extractFromOriginal selector="#someid" />


Selecting whatever is contained (text?) in the second table row, second cell, enclosed by a font tag:

<@extractFromOriginal selector="tr:nth-child(2) td:nth-child(2) font" />


Selecting the second cell from table rows containing specific text ('Field Name:'):

<@extractFromOriginal selector="tr:contains(Field Name:) > td:nth-of-type(2)" />

Element styling (advanced)

In addition to regular templates and original content extraction, Flowmailer also allows you to change content styling on the fly. This is often done in conjunction with other templates, to 'preprocess' elements to first make the content fit the style guide you want and apply a specific template as a second step.

We do this by traversing the DOM tree using Freemarkers built-ins for nodes. Each macro in the code below represents a change in styling, by setting the attributes we want.

<#macro h1>
  <h1 style="color: red;"><#recurse></h1>
</#macro>
<#macro a><a href="${.node.@href}" style="color: blue; ><#recurse></a></#macro>
<#macro img></#macro>

<#macro @text>${.node?html}</#macro>
<#macro @element><#t>
<${.node?node_name}<#t>
    <#list .node.@@ as attribute><#t>
        ${" "}${attribute?node_name?html}="${attribute?html}"<#t>
    </#list><#t>
><#t>
<#t>    <#recurse>
<#t></${.node?node_name}>
<#t></#macro>

<html>
  <body>
    <#assign doc=extractNodesFromOriginal()/>
    <#recurse doc>
  </body>
</html>

The code above effectively replaces the message HTML body with a reconstructed one. In doing so we make the following changes:

Please note that creating element styling templates are considered an advanced topic and should be avoided by most users.