Custom templates

Create custom HTML email templates for FeedOtter to gain precise control over the look and feel of your data-driven FeedOtter automated emails.


This guide will walk you through the creation of a basic, custom HTML email template that works with FeedOtter.  This guide will focus on creating the technical elements of the data-driven email.  You can apply the lessons learned here to your own HTML email creation to create custom, data-driven emails that are compatible with FeedOtter's automated and curated email features.

About FeedOtter's Token Language

Like many other email softwares FeedOtter has a token or merge variable language.  Using any of the following tokens in your FeedOtter HTML email will result in data being displayed in place of the token object.

There are several different kinds of tokens:

Campaign Tokens:
Used to display data related to the FeedOtter campaign object such as Send Date or Campaign Name.

Post Loop Tokens:
These are tokens that relate to your RSS content such as post title, description, url, and author.

UI Tokens:
These are special tokens that allow you to interact with the FeedOtter "edit" UI.  Examples include: primary color, button color, and heading text.  If you are coding an email from scratch we recommend using Custom Tokens rather than UI tokens as they offer more flexibility.

Custom Tokens:
These are tokens defined in the email template file.  You can create any number custom tokens to make parts of your email editing from the FeedOtter edit UI.  Customers use these to allow for custom image uploads, text and headline updates and more.  

Campaign Tokens

These tokens are used to display properties from the parent FeedOtter campaign object.
Merge Code
Description and Usage
The name of your campaign as provided during the wizard process
A text string containing the day of week, month, day, and year that your email campaign ran. Example: Tuesday, November 15 2016
A date object that can be used for advanced formatting such as [[feedotter.send_date_object | date("Hi m/d/Y", "Europe/Paris")]] Good resources for date building are: PHP date function and PHP date generator.
[[feedotter.scheduled_date | date("m/d/Y")]]

Available in Curated Newsletter Builder Only.

A date object which contains the date that a curated newsletter is scheduled. This may be useful if you create newsletters that are scheduled in the future. This token REQUIRES the use of a formatter such as [[feedotter.scheduled_date | date("m/d/Y")]] Date formatters are in PHP format. See: PHP date function and PHP date generator.

The FROM NAME value as provided during the campaign wizard process
The FROM EMAIL value as provided during the campaign wizard process
The REPLY EMAIL address as provided during the campaign wizard process
Special text block designed for an email preheader. This includes the title of the first post and the first 100 characters of the first post text.

Post Loop Tokens

These tokens MUST be inside a valid loop.  e.g. [% for post in feedotter.posts %] [[post.post_title]] [% endfor %]
Merge Code
Description and Usage
The title of a blog post. Use [[post.post_title | truncate(60,true,”…”)]] to truncate the title to 60 characters of length.
The full <content> content from the RSS feed (including HTML if present) as available in the node of an RSS feed
A text-only version of the node from the RSS feed. You can truncate this field to 200 characters like this: [[post.post_description_text | truncate(200,true,”…”)]]
An automatically created snippet based on the RSS fields. Our system looks for the best option and creates this. This field may include HTML if present
Same as post_excerpt with HTML stripped. [[post.post_excerpt_text | truncate(200,true,”…”)]]
The url of a blog post
The author name of a blog post.  If the RSS data contains multiple authors they will be displayed separated by a comma.  e.g "Author Name1, Author Name2".  You can gain more control over the display of multiple authors by using the asArray method. e.g [[ post.asArray.dc.creator[0].value ]], [[ post.asArray.dc.creator[1].value ]]
The publish date of a blog post. Automatic formatting.

The publish date of a blog post. This field can be formatted using [[post.post_date | date("F d")]] For details on how to format dates please visit:

The name of the source blog of a blog post
The best image to represent a blog post as chosen by our algorithm. We rely on the post's OG:IMAGE tag first and foremost. If not provided we scrape the page to find a suitably sized image.
[[post.image_url | resize(600,400)]]
Same as above but with an intelligent resize "filter" that will crop the source image to the provided dimensions to ensure your images all look consistent.
Displays an estimated article read time (integer) minutes. Based on field of the RSS data. Example usage: Read Time: [[post.post_timeToRead]] min.

UI Tokens

These merge codes correspond to properties that can be customized from the FeedOtter Customize interface.

Merge CodeDescription
[[feedotter.primary_color]]The color(hex) selected as primary color in the campaign wizard
[[feedotter.secondary_color]]The color(hex) selected as secondary color in the campaign wizard
[[feedotter.button_color]]The color(hex) for buttons and calls to action links
[[feedotter.footer_text_color]]The color(hex) of text in the default footer text. Only allowed inside "footer_html" content.
[[feedotter.footer_html]]WYSIWYG html block for footer content.
[[feedotter.social_html]]Display custom html to display social links and icons.
[[feedotter.header_image_url]]Certain templates support the upload of a header banner image
[[feedotter.company_logo_url]]Certain templates support the upload of logo image.
[[feedotter.post_body_char_limit]]Certain templates support the changing of the max body length via the UI
[[feedotter.unsubscribe_link]]Displays the proper unsubscribe link based on your sending software
[[feedotter.view_as_webpage_link]]Displays a link to view the email as a webpage based on your sending software.

Custom Tokens

You can also define custom field tokens in your HTML.  Custom tokens allow you to make certain parts of your email editable from the FeedOtter UI.  This is great for personalizing greetings, swapping out headlines, adding ad content or various other CTAs.  The idea is that you can easily change basic elements without the risk of breaking the email code.

In the example below we define 3 custom fields in a special <script> JSON block added to the bottom of our email's <head> section.  Currently, we support 3 types of custom fields; text, html, image.  
    <script type="application/ld+json" id="custom">
      {"prettyName": "Sample HTML","name": "samplehtml","type": "html","default": "<p>a block of html</p>"},
      {"prettyName": "Headline","name": "headline","type": "text","default": "Some plain text"},
      {"prettyName": "Ad Image","name": "adimage1","type": "image","default": ""}
    <h1>  [[custom.headline]]</h1>
    <p><img src="[[custom.adimage1]]"></p>
Each custom field will then appear in the FeedOtter UI when editing an email. You can edit text, upload images, or tweak basic html text to customize emails.
Custom HTML tokens in FeedOtter emails
Custom fields are also available for use when using the Send Now feature.
Custom fields are available for use with Send Now
Custom fields can be used in many creative ways.  You can even bind the default value of a custom field to data from your RSS feeds!

Looping Through RSS Feeds and Displaying Content

Here we cover the basic elements of a FeedOtter data-driven RSS email.

The Post Loop

The post loop is the most important component of any FeedOtter email design. The code shown here will loop through your RSS feed and display each the title, url, and description(with html stripped) for each post in your RSS feed.

    //A very basic post loop example
    [% for post in feedotter.posts %]    
    [% endfor %]    
Slicing the Post Loop

In many cases you may want to display a specific post or posts from an RSS feed.  We do this by applying a "slice" filter to the feedotter.posts element.

Example 1. Displays only the first post in the feed. 
"loop through the feed, starting at post 0, and stop after 1 post"

Example 2. Displays posts 2-5 in the feed.
"loop through the feed, starting at post 1, and stop after 4 posts"

Pay special attention to the | slice(0, 1) part of the loop definition. The first number in the slice() function is the starting point so 0=first post in a feed. The second number is the length or number of posts to display or loop through.

    //Example 1.
    [% for post in feedotter.posts | slice(0,1) %]
    	### Displaying Post 1 Only ###
    [% endfor %]
    //Example 2.
    [% for post in feedotter.posts | slice(1,4) %]
    	### Displaying Posts 2-5 ###
    [% endfor %]
Looping through Multiple Feeds

FeedOtter's advanced plans support combining multiple feeds into a single feed or displaying feeds in separate loops. This feature can help you consolidate data from multiple places and display content in different sections of a newsletter with ease.

Example 1.
There are two loops. The first loop displays the first post from RSS Feed 1. The second loop displays 3 posts from RSS Feed 2. The important part to note is the loop text "feedotter.posts".  Adding a number to this will allow you to access the data from multiple feeds. "feedotter.posts" is always feed1 -the topmost feed shown in the UI.

Example 2.
In this example we use a special filter to combine the data from feeds 1 and 2. This filter will remove duplicates and order all posts by their published date.

     //Example 1.
     ###Display 1 post from RSS Feed 1###
     [% for post in feedotter.posts | slice(0,1) %]
          [[post.post_title]] - [[post.post_url]]
     [% endfor %]

     ###Display 3 posts from RSS Feed 2###
     [% for post in feedotter.posts2 | slice(0,3) %]
          [[post.post_title]] - [[post.post_url]]
     [% endfor %]
     //Example 2.
     ###Combined Posts From All Feeds. De-duped and sorted by Published Date###
     [% for post in feedMerge([feedotter.posts, feedotter.posts2]) %]
          [[post.post_date | date("n/j/Y")]] == [[post.post_title]]
     [% endfor %]

Formatting Filters

//Truncate to 200 characters of text(200), preserve words(true), add ellipses("...")
[[post.post_excerpt_text | truncate(200,true,"...")]]

//Truncate to 450 characters of text but preserve sentences
[[post.post_excerpt_text | truncate_sentence(450)]]
Date Formatting In general FeedOtter can use any date formatting supported by PHP as seen here:
[[feedotter.send_date | date("F d")]] //the date FeedOtter sent your email formatted as: October 25
Image Cropping An issue that often plagues email newsletters is inconsistent image sizes. To fix this we offer a filter that resizes your images to the size you specify in your template code. This filter will CROP your image which means text and other effects in the image may become "cutoff". Use accordingly.
//Resize the original image to 400x400px.  This ensures your image will always appear square.
[[post.post_image_url | resize(400,400)]]

FeedOtter uses the TWIG template language.  As such ANY of the TWIG supported filters and formatters are available to use to manipulate data and display variations.  Here we will give examples of the some commonly used formatters.

Helpful Marketing Automation-Related Merge Codes

FeedOtter supports the usage of your email platform’s merge codes as well.  This is useful to insert personalization (first name etc…) or other data fields from your email platform.  Here are several common and useful examples.


{{system.viewAsWebpageLink:default=edit me}}
{{lead.First Name:default=edit me}}

Full list of Marketo merge tokens



Full list of Pardot Classic Variables

PARDOT 2020+:


Full list of Pardot HML Variables


Subject Line Merge Codes

Certain merge codes are available for use in your subject line they are listed below.

Best Practice: Subject lines should not exceed 100 characters so we always recommend using a truncated post title.

//Insert the title of the most recent post in the subject line
[[feedotter.latest_post_title|truncate(40,true,"...")]] //truncated example

//Date examples
[[feedotter.send_date | date("F d")]] //formatted October, 25

Social Share Icons / Links

While some FeedOtter templates come with built in social sharing icons. You may want to add your own. You can do this by adding the below code into the loop.
<a target="_blank" href="[[post.post_title]]&url=[[post.post_url]]" style="border:none !important;margin-right:5px;">
	<img src="" title="Twitter" alt="Twitter" width="20" border="0" />

<a target="_blank"  href="[[post.post_url]]" style="border:none !important;margin-right:5px;">
<img src=""  title="LinkedIn" alt="LinkedIn" width="20" border="0"  />

<a target="_blank"  href="[[post.post_url]]" style="border:none !important;margin-right:10px;">
<img src=""  title="Facebook" alt="Facebook" width="20" border="0" />

Here’s an example of how we implemented social sharing icons on our Almeria template.

Conditional IF/ELSE, Ternary statements

Often it is desirable to show/hide content based on whether Tag values are present.  This can be done using conditional tags.  Here are some examples:

//Basic IF Statement
[% if post.image_url == true %]
<img src="[[post.image_url]]">
[% endif %]

[% if post.image_url %]
<img src="[[post.image_url]]">
[% else %]
<img src="">
[% endif %]

//Ternary IF / ELSE
[[post.image_url ? post.image_url : '']]

//Loop Based IF / ELSE
[% if feedotter.posts|length >0 %]
//display something
[% endif %]

Non-RSS XML Values

While FeedOtter requires a valid RSS feed to supply data.  We can also read additional, custom xml values.  Client’s have used this to supply custom images and descriptions along with the standard RSS data fields.

This can be especially useful when building data-driven emails from job boards, news sites, and eCommerce applications.

A helpful starting point is to use the token [[ post.asArray | json_encode ]] in your loop.  This will display the raw object that you can then use to access various elements using standard object / array notation as shown below.

Below is a partial RSS entry.  Note the node:

<title>Beautiful Painting of saharanpur</title>
<price cost="$179,000" age="2,000 years" condition="perfect"></price>

Here is how to access the custom_image property in the FeedOtter post loop:

[% for post in feedotter.posts %] //standard post loop

//the post.asArray provides direct access to any xml fields in the <item> node of the RSS feed

[% endfor %]

You can also access attributes of custom elements such as the cost=”$179,000″.  The post.asArray.price.attr contains all of the attributes on that node.

[% for post in feedotter.posts %] //standard post loop

//the post.asArray provides direct access to any xml fields in the <item> node of the RSS feed
[[post.asArray.price.attr.cost]]  // displays $179,000
[[post.AsArray.price.attr.age]] // 2,000 years
[[post.asArray.price.attr.condition]] // perfect

[% endfor %]

Working with Multiple RSS Feeds

Applies to: Automated Emails

One of FeedOtter's most powerful features is the ability to incorporate multiple RSS feeds into a single email. Customers have used this features to automate complex multi-section emails, displaying categories of content, or content from multiple blogs or news sites in a single email.

While using multiple feeds is a more advanced use-case and requires a Plus plan or higher it can be a great way to automate more elaborate emails.

This first code sample shows how to display content from multiple feeds in an html email.  Each additional feed you add to your campaign enables a new loop  feedotter.posts, feedotter.posts2 and so on.

You can loop through content using and use the familiar slice() filter to access specific sections of the feed content.

Display 1 post from RSS Feed 1
[% for post in feedotter.posts | slice(0,1) %]

[[post.post_title]] - [[post.post_url]]

[% endfor %] Display 3 posts from RSS Feed 2 [% for post in feedotter.posts2 | slice(0,3) %]

[[post.post_title]] - [[post.post_url]]

[% endfor %]
The second example shows how to "braid" or combine multiple RSS feeds into a single FeedOtter loop object.
 Combined Posts From All Feeds. De-duped and sorted by Published Date
 [% for post in feedMerge([feedotter.posts, feedotter.posts2]) %]

[[post.post_date | date("n/j/Y")]] == [[post.post_title]]

### [% endfor %]

Automate Your Newsletter Today

Improve your brand awareness and blog engagement with automated newsletters by FeedOtter.
start a free trial
Sign up for a free 7-day trial. No credit card required.
Grow Better with FeedOtter