Skip to main content

How to manage template scripting

Check out how you can implement template scripting in your emails.

Written by Support Team

Template scripting lets you run JavaScript inside a template, so the content of a message can be built at the moment it is sent instead of being fixed when you design it.

Enabling template scripting

Script fields are denoted with {{ }}. Before you can use them, Template Scripting has to be enabled for your account.

  1. Go to Settings > Sending > Advanced.

  2. Turn on "Template Scripting".

For the remaining options on this screen, see the article "Sending Settings".

Where script fields work

Script fields can be used in the subject, the HTML body and the text body.

Content is processed in a fixed order: the HTML body first, then the subject, then the text body. All script fields in one message share a single JavaScript context, so a variable you define in the HTML body is available later in the subject, but not the other way round. Example 1 below relies on this.

The subject line limit

The subject is limited to 200 characters. The limit applies to the subject as you write it, which means the script source counts towards it, not the result the script produces. Because of this, put the main scripting in the HTML body and keep the subject to short expressions.

A campaign template with a longer subject is rejected when you save it. On the transactional API and on SMTP the subject is truncated at 200 characters instead, which can cut a script in half and make the message fail.

Closing a script field

A script field is closed by the first }} that follows it. If a closing brace in your own code sits directly against the delimiter, the field ends early, the rest of your code stays in the message as plain text, and you normally get a syntax error. Leave a space or a newline between the two:

{{var o = ''; for (var i = 0; i < 3; i++) { o += i; } o; }} // works

{{var o = ''; for (var i = 0; i < 3; i++) { o += i;}}} // syntax error

Execution time

Each script field has 10 seconds to complete. A script that runs longer is stopped and the message is not sent.

Merge fields

The scripting engine also includes the Contact and Profile merge fields, for example:

{{ var myname = accountfirstname + ' ' + accountlastname; }}

The Profile fields are accountemail, accountfirstname, accountlastname, accountcompany, accountaddress1, accountaddress2, accountcity, accountstate, accountcountry, accountzip, accountwebsite, accountphone, accountaddress, accountcontactinfo and deliveryreason.

Fields defined in CSV mail merge are also accessible by their column names.

Referring to a merge field that does not exist for the recipient is a JavaScript error, not an empty value. If a field may be missing, guard it rather than assuming it is there.

Generic merge fields

Generic merge fields such as {unsubscribe} and {view} cannot be used with template scripting. They are replaced in a separate, later step, so they are not variables in the scripting engine. Writing one inside a script field, as {{unsubscribe}}, raises a JavaScript error ("unsubscribe is not defined") and the message is not sent.

The same applies to {unsubscribelist}, {unsubscribefromlist}, {reportspam}, {why}, {consent}, {contactprofile} and {referrals}.

Use these tags with single braces, outside of script fields. For more on merge fields, see the article How to use merge fields.

Error handling

A JavaScript error inside a script field prevents the email from being sent and is reported as a bounce. That bounce is recorded as a non-delivery which does not count towards your delivery failure rate, and the message is not retried.

A script error also stops the rest of the send. Because a template error affects every recipient in the same way, the remaining messages in that campaign or send job are cancelled as well. Always preview your template before sending.

Standard JavaScript try/catch can be leveraged to control error handling:

{{

var greeting;

try { greeting = "Dear " + firstname + ","; }

catch (e) { greeting = "Hi there!"; }

greeting;

}}

Note that try/catch does not help with a failed download(), because that function does not throw. See below.

Additional functions

md5(text)

Returns the MD5 hash of a given string.

{{md5('The quick brown fox jumps over the lazy dog')}}

// 9e107d9d372bb6826bd81d3542a419d6

download(url)

Downloads and returns page content as a string.

If the remote server cannot be contacted, download() returns null and does not throw an exception. The script field itself renders as empty, and the failure only surfaces later, when your code uses the result: calling .replace() or reading .length on null is a JavaScript error, which then fails the message and cancels the rest of the send. Check the result before you use it:

{{

var html = download('http://somewhere.com/content');

if (html === null) {

'Sorry, this content is unavailable right now.';

} else {

htmltag(html, 'body');

}

}}

Downloaded content is cached for 30 minutes per URL and reused for the rest of the send job. Content that changes more often than that will not be picked up, and content that has to differ per recipient needs a per-recipient URL, as in Example 1 below.

htmltag(html, tag)

Returns the value of a given tag, for example var subject = htmltag(content, 'title');.

It returns null when the tag is not present in the supplied HTML, so the same care applies as with download().

Example 1: pulling content from a web page

This example downloads a page, uses its title as the subject line and its body as the message content.

Subject line

{{ subject }}

HTML

{{

var subject = 'Your update';

var body = 'Sorry, this content is unavailable right now.';

var html = download('http://somewhere.com?recipient=' + encodeURIComponent(email)); // email is part of the standard merge field set

if (html !== null) {

html = html.replace('[-EMAILADDR-]', email);

html = html.replace('04102014', Math.floor(Math.random() * 100000000));

var title = htmltag(html, 'title');

if (title !== null) { subject = title; }

var content = htmltag(html, 'body');

if (content !== null) { body = content; }

}

body; // this line evaluates to the body content and is returned by this script block

}}

The subject variable is defined in the HTML body and used in the subject line. This works because the HTML body is processed before the subject.

Both download() and htmltag() can return null, so the example sets a default subject and a default body first, and only replaces them once it has a usable value. Without those checks, a page that is unreachable or missing a tag would fail the message and cancel the rest of the send.

Example 2: linking to dated content

Subject line

Today is {{new Date()}}.

HTML

{{

var today = new Date();

var dd = String(today.getDate()).padStart(2, '0');

var mm = String(today.getMonth() + 1).padStart(2, '0');

var yyyy = today.getFullYear();

today = yyyy + '-' + mm + '-' + dd;

null; // this line is so this script block evaluates to null, otherwise it would have evaluated to the content of the today variable

}}

<p>This is a page that links to today's <a href="http://dilbert.com/strip/{{today}}">Dilbert</a> strip.</p>

The day and the month are padded to two digits, so that a date such as 2026-07-05 is built correctly and the link resolves.

Example 3: a fallback for a missing merge field

Merge fields with an alternative display when you do not have data for that merge field. For example, you want to show the first name of your recipient if you have it on file, but show "Hi there!" if you do not.

{{var greeting = "Dear " + firstname + ","; if (firstname.length == 0) greeting = "Hi there!"; greeting;}}

The closing greeting; is what makes the block output the greeting. A script field renders whatever its last statement evaluates to, so a block that ends with an assignment inside an if renders nothing whenever that branch is not taken.

If firstname might not exist for the recipient at all, as opposed to being present but empty, wrap the block in try/catch as shown under Error handling.

If you need any further assistance, feel free to reach out to our Customer Support Team, available 24/7. We're always happy to help!

Did this answer your question?