Autopilot: Personalize emails with Liquid, RSS and JSON fetch
Autopilot supports the Liquid templating language in both the Basic and Advanced Editors. This provides a powerful and flexible way to personalize your emails. Liquid allows you to include dynamic content in your emails. It also allows you to personalize your emails using dynamic logic. This means that in addition to including contact fields* in emails, you can use logic such as "if" statements, "for loops", and the many filters that Liquid supports.
Autopilot supports all of the Liquid syntax documented at the link above, as well as three additional tags: {% rss %}, {% json %} and{% json-get %}. These tags allow you to retrieve data from your RSS feed or custom endpoint, respectively. Examples of how to use them can be found below.
* You might also know these as "personalization variables" or "merge tags". In this article we refer to them simply as "contact fields" to avoid ambiguity, as there are other tags also being discussed.
How to use Autopilot contact fields with Liquid
Normally in Autopilot you include contact fields in emails using the following syntax:
—First Name—
In Liquid the syntax is as follows:
{{ contact.firstname }}
There are a few key differences to note here. You need to use:
- double curly braces on each side instead of the dashes;
- no spaces in the name; and
- a contact. prefix. This is so no values are overwritten if you use the RSS and JSON tags and have variables named the same thing coming from them.
Note that capitalization doesn't matter.
The same applies for custom fields. Normally you include them using the following syntax:
--My Custom Variable--
In Liquid the syntax is as follows:
{{ contact.mycustomvariable }}
Fallback values (i.e. defaults)
In the Basic and Advanced Editors we allow you to specify a fallback value (i.e. default) in case the given contact does not have that field available, for example:
Hi --First Name=there--
,
So in the case where we have a first name we might see:
Hi George,
And the case where this contact does not have a first name set, we would see:
Hi there,
This is convenient, and it is available in Liquid with a different syntax. Here is how to do it in Liquid:
Hi {{ contact.firstname | default: 'there' }}
For more please see Liquid’s documentation here.
Filters
Filters are simple methods that modify the output of numbers, strings, variables and objects. The above example with "default" is an example of one of Liquid’s filters.
For more please see Liquid's documentation here (go to the left hand side menu under "Filters").
Control flow tags
One of the most useful features of Liquid is the ability to selectively display content based on logic, this is done primarily through the use of the "if" statement.
Here are some examples of this:
{% if contact.numberofemployees > 50 %}
With a large organization like yours, communication is key.
{% elsif contact.numberofemployees > 5 %}
In SMBs, the key is balance.
{% else %}
In a micro-org like yours, you need to save every dollar.
{% endif %}
Of course you don’t need all the "else" statements you could just do this:
{% if contact.specialoffer %}
Bonus: for being a loyal customer we'd like to offer you half off your next purchase. Use the coupon code LOVE to redeem this offer.
{% endif %}
For more please see Liquid’s documentation here.
Iteration tags
If you have collections of things, you can use iteration to loop over it. For example:
- items in an RSS feed;
- items in an abandoned shopping cart;
- items which are on special; or
- events which are coming up.
Since Autopilot’s built-in fields and custom fields do not currently support arrays or groups of items, this will not immediately be useful without using the RSS or JSON tags (referred to below) and we give examples of iteration there.
For more please see Liquid’s documentation here.
Variable tags
Liquid also supports assigning things to variables. You may need to do this for more sophisticated templating and Autopilot fully supports this and indeed the entire syntax.
RSS tags
RSS tags allow you to read from an RSS feed and put information coming from the RSS feed into an email.
{% rss http://www.myblog.com/test.xml %}
{% for item in rss.items %}
{{ item.title }}
{{ item.link }}
{{ item.content }}
{% endfor %}
The RSS tag will read in your RSS feed and populate it into a variable called "rss" which can then be iterated upon as outlined above. You then have access to each item’s title, link, description.
Please note that your endpoint must return in less than 5 seconds and be less then 2MB in size. If this fails when sending an email you will see Activity Feed items saying that the email failed to send and why.
So be careful: if your RSS endpoint is unreliable, you will have emails which will fail to send.
Also note, the only properties in your RSS feed that are currently supported are title, description and link. See the following:
<item>
<title></title>
<description></description> **Use {{item.content}} to display description.
<link></link>
</item>
JSON tags
JSON tags allow you to read arbitrary data from your own endpoint. This is something that your development team can set up so you can include data far beyond the scope of what Autopilot stores about your customers, more up-to-date info, or just anything you like.
The syntax looks like this:
{% json https://www.autopilothq.com/test.json %}
I have {{json.chocolates}}
chocolates.
Note that we POST to this endpoint, see below for discussion of the GET version. We provide you with two important values in the body of the request for POST requests:
json
{"contactId": "contacts_person_3C86FF1C-9E87-40B1-8D13-1AA064B0BF7A","email": "george@autopilothq.com"}
These values allow you to customize the response value based on the contact whom is being emailed. For example, you might look up George’s most recent shopping cart and return a list of the items specific to her.
Here is an example to show you what that looks like:
{% json https://www.autopilothq.com/shoppingcart %}
Hi
{{ contact.firstname }},
{% if json.cart %}
Thanks for visiting our website. We noticed that you had some items in your cart but didn’t buy them. We would really like for you to buy them.
The items in your cart are:
{% for item in json.cart.items %}
{{ item.name }} - ${{item.price | round }}
{% if item.tags contains 'special' %}
THIS ITEM IS ON SPECIAL!{% endif %}
{% endfor %}
{% else %}
Thanks for visiting our website. We noticed you didn’t put anything in your cart. We hope you'll check back soon.
{% endif %}
So on the server side you would read the incoming values, look up the cart information for that contact and output something like the following:
json
{ "cart": { "Items": [ { "name": "Toothbrush", price: 0.8, tags: "special, blue" }, { "name": "Soccer Ball", price: 6, tags: "deflated" } ] } }
Autopilot supports nesting of JSON values so you can do things like this:
{{ json.some.very.deep.value }}
We also support arrays as seen with the cart items.
This should allow you to display almost any level of custom content in an email and get as creative or detailed as you like.
Please note that your endpoint must return in less than 5 seconds and be less then 2MB in size. If this fails when sending an email you will see Activity Feed items saying that the email failed to send and why. If you would like the timeout to be increased beyond 5 seconds, please email us at support@autopilothq.com.
So be careful: if your JSON endpoint is unreliable, returns errors or is ever down, you will have emails which will fail to send.
JSON-GET tags
JSON-get tags allows you to read arbitrary data from your own endpoint via a GET method. This is something that your development team can set up so you can include data far beyond the scope of what Autopilot stores about your customers, more up-to-date info, or just anything you like.
The syntax looks like this:
{% json-get https://www.autopilothq.com/test.json %}
I have
{{json.chocolates}}
chocolates.Note that we send a GET to this endpoint. We provide you with two important values in the query string of the URL:
https://www.autopilothq.com/test.json?contactId=contacts_person_3C86FF1C-9E87-40B1-8D13-1AA064B0BF7A&email=george@autopilothq.com
These values allow you to customize the response value based on the contact whom is being emailed. For example, you might look up George’s most recent shopping cart and return a list of the items specific to her.
Please note that we don’t currently support having your own query string parameters added to your URL.
Testing, publishing and sending emails
When a test email is sent, or an email is published, we check your Liquid syntax to make sure it is valid. The reason we do this is that if it is invalid syntax, the email will not be able to send.
If it does fail, we will give you the reason for the failure - but it will be in fairly technical language, coming from Liquid itself. If you have trouble with this please contact our support team and we will help you. We would encourage you to gradually add Liquid to your templates and publish regularly, rather than doing a whole bunch at once only to find issues with it.
If a particular value for a contact field cannot be found by liquid or you just do some nonsense like this:
{{ fiushfioehur }}
Liquid’s approach is just to output nothing. We strongly encourage you to use the | default filter whenever possible in places where you are not certain that this contact will have the value.
Experimentation is the best way to get good at this, and given the "Send Test" feature will also run the Liquid code for you so you can try it as much as you need to get it right.