Skip to content

Looking to send messages to the UK from a new Sender ID? From 4th April, you will need to contact us to set this up.

Email.
Get support for your Esendex Email products.

Esendex Templating Language

This article aims to provide you with clear descriptions and explanations of fundamental concepts in MJ Templating Language. You will find practical examples throughout the article, which effectively illustrate how to use the language in real-world scenarios.

Summary

Variable Types

Esendex offers four types of variables, each serving a different purpose in the templating language. These variable types include:

  1. Data (static): These variables are used for static data that doesn’t change frequently. They are typically pre-defined values.
  2. Var (dynamic): Var variables are used for dynamic data that can change based on different conditions or inputs.
  3. Predefined MJ variables: These variables are predefined by Esendex and provide useful information and functionality within the templating language.
  4. Segmentation variable structures: These variables are utilized for complex segmentation purposes and are not the main focus of this article.

We will be focusing primarily on the first two variable types (data and var), but will also touch briefly on predefined variables.

The most commonly used variable types are data and var. While both serve the purpose of replacing a placeholder string with a dynamically changing value, they differ in how they should be used, how the value is provided to the system, and the types of messages in which they can be utilized.

In addition to stand-alone variables, the templating language provides tools (functions) that enable users to incorporate variables into more complex logical and arithmetic operations, as well as influence formatting and encoding. In this guide, we will specifically explore the usage of functions such as ‘set’ and ‘FormatNumberLocale’. Furthermore, we will delve into if-conditional statements and for-loops in detail.

Data

The data type of variable is versatile and can be utilised in both Marketing and Transactional messages. This flexibility arises from the fact that it doesn’t require any action from the user to provide a value for the variable placeholder. Instead, the system automatically replaces the value based on the Contact property objects.

Whether you’re sending a campaign or a transactional email, as long as the message is directed to an existing contact and the variable name corresponds to a contact property, the system will be able to process the data variable. If the recipient has a value assigned to that property, it will be displayed in place of the variable placeholder.

Let’s illustrate this with an example. Suppose I set the variable [[data:country]] in the content of my message and send it to one of my contacts. In this scenario, two outcomes are possible:

  1. If the contact has a value set for the “country” Contact property, they will receive the message with the [[data:country]] variable replaced by the corresponding value.
  2. If the contact does not have a value set for the “country” Contact property, they will receive the message without any replacement for the [[data:country]] variable. However, the variable itself will not be displayed as a template language element in the final version of the message.

To provide a concrete example, let’s consider two contacts: user1@domain.tld, who has a “country” property value of “France” and user2@domain.tld, who does not have a value set for the “country” property.

If I send them both the same message containing the sentence:

Hi, how are things in [[data:country]] now after the pandemic?

Both contacts will see different content:

user1@domain.tld will see: “Hi, how are things in France now after the pandemic?”
user2@domain.tld will see: “Hi, how are things in now after the pandemic?”

In the second example, the system simply does not print anything because the user does not have a value set for the associated property of the data variable in use.

Var

It is important to note that the var type of variable should not be used in Marketing templates or Campaign drafts. Although it can be added to these objects, attempting to send such a message will result in a BLOCKED event due to a templating language error. Typically, the error message will indicate that no value was provided for the var variable, which is expected as there is no means to add a value for it.

However, there are ways to make var variables work in a Marketing template or Campaign setting. The two most straightforward approaches are:

  • Adding the var variable with a default value.
  • Defining the variable using a set function.

While these approaches technically work, they can be counterproductive and less useful. This is because they require you to set the variable’s value in the template itself before sending, without allowing for any variation in the displayed value based on the recipient. This contradicts the purpose of having a variable and defeats its flexibility.

The proper utilisation of var variables is to include them in Transactional templates or directly in the content of transactional messages. The values used to replace these variables are provided by the user through the Send API call (as part of the request body) or during the SMTP-relay session (as a custom header), depending on the transactional channel being used.

To declare the variables and provide their respective values, JSON key-value pairs are used. For example, “name”: “John” or “testVariable123″: “testValue“, etc.

In the context of Send API v3, the object that holds the variables is named “Vars.” For Send API v3.1, the principle remains the same, but the object is named “Variables.” For SMTP-relay-generated messages, the custom header that should contain the JSON-encoded variables is “X-MJ-Vars.”

Please note that for the Templating Language to be processed correctly and not as plain text, the Esendex system relies on specific properties that indicate whether the template language elements should be treated as such. These properties are of Boolean type, and below you will find the appropriate property name for each transactional channel:

  • Send API v3: “Mj-TemplateLanguage”
  • Send API v3.1: “TemplateLanguage”
  • SMTP-relay: “X-MJ-TemplateLanguage”

It’s important to keep in mind that the default value for each of these properties is “false” or “0”. If this detail is overlooked, even if the configurations are correct, the template language setups may not work as expected. This is because without enabling the above properties, the system interprets the templating language elements in the sent message as ordinary text strings without any additional significance.

Lastly, in a niche scenario where users create campaign draft objects via the API and intend to use templating language in the content of the campaign draft, they need to ensure that the “/campaigndraft/$ID/detailcontent” object associated with their draft includes the following property in the “Headers” object:

 

Tamplating

 

By including this property, the system recognises the use of templating language in the campaign draft’s content.

Default values

Both var and data variables support the use of default values. A default value acts as a fallback or safety-net value that users provide to our system when setting up the variable in the template or body of the message. If certain conditions are met, the default value will be displayed by our system:

  • data variables: If the contact receiving the message does not have a Contact property value set for that specific variable/contact property.
  • var variables: If no value is pushed through the API call or SMTP session.

In these scenarios, the default value serves as a substitute to ensure that there is always a value displayed for the variable, even when the necessary data is not available or provided.

Syntax

With the above considerations in mind, let’s delve into the proper syntax for stand-alone variables (variables that are not being used within a function).

Var variables

  • To add a var variable, use the following syntax: {{var:variableName}}
  • To provide a default value along with the variable: {{var:variableName:defaultValue}}
    Alternative syntax: {{var:variableName:”defaultValue”}} (both options work equally well)
  • To print a space as the default value, enclose it in quotation marks: {{var:variableName:” “}}
  • To display nothing as the default value, use empty quotation marks: {{var:variableName:””}}

Data variables

  • To add a data variable, use the following syntax: [[data:contactPropertyName]]
  • To provide a default value along with the variable:[[data:contactPropertyName:defaultValue]]
    Alternative syntax: [[data:contactPropertyName:”defaultValue”]]

Note: While double curly braces instead of double square brackets also work for data variables, it is recommended to use square brackets unless required for specific functions that demand double curly braces.

It’s important to note that the system’s behaviour differs when it encounters a situation where it lacks a value for a data variable compared to a var variable. If a data variable does not have a default value and the contact does not have a value set for the respective property, a whitespace will be printed in the message. However, not having a default value for a var variable and not declaring it in the API call or SMTP session will result in the message being blocked.

Default values are not mandatory, but they can be helpful in preventing message blocking. By default, when the system encounters a var variable without a provided value, it blocks the message. To influence this behaviour, you can include a special Boolean property in your API call or SMTP header:

  • Send API v3: “Mj-TemplateErrorDeliver”
  • Send API v3.1: “TemplateErrorDeliver”
  • SMTP: “X-MJ-TemplateErrorDeliver”

The default value for this property is “false,” so enabling it manually allows messages to be sent even if there are templating language errors. Enabling this property prevents messages from being blocked.

Lastly, users can choose whether they want to be notified via email when their messages are blocked due to templating language errors. This can be achieved through another special property:

  • Send API v3: “Mj-TemplateErrorReporting” (example: “Mj-TemplateErrorReporting”: “reports@domain.tld”)
  • Send API v3.1: “TemplateErrorReporting” (example: {“Email”: “reports@domain.tld”, “Name”: “Recipient Name”})
  • SMTP: “X-MJ-TemplateErrorReporting” (custom header example: X-MJ-TemplateErrorReporting: “reports@domain.tld”)

 

 

Predefined variables

In our system, certain variable names are reserved for predefined static variables. These variables allow users to specify a variable that corresponds to a specific system-based value. Some commonly used predefined variables include:

  • Recipient contact’s ID
  • Recipient contact’s email address
  • Template’s ID
  • Social media shareable links for the online version of the email (Twitter, Facebook, LinkedIn, etc.) – this is applicable for newsletters just like the standard online versions/PERMALINKS.

The syntax for using any of these predefined variables is as follows: {{predefinedVarHere}}.

Example: {{mj:template.ID}} will display the template ID in the final version of the message if a template was used to send the email.

Please note that there are other reserved variables, such as the Unsubscribe link or the Online version, which are introduced using double square brackets (e.g., [[PERMALINK]]). These variables are typically added automatically by the system, but users can also manually introduce them in Drag-and-Drop, raw HTML, raw MJML templates, or campaign draft detailcontent objects. It’s important to remember that these special predefined variables should not be introduced with curly brackets. Introducing them with curly brackets will cause the system to treat them as variables that need to be defined in an API call or during an SMTP session (as “var” variables) rather than variables that the system can fetch on its own.

Therefore, any predefined static variable specified in the reference documentation mentioned above (starting with “mj:”) must be introduced using “{{}}“, while any predefined variable not listed in that documentation (not starting with “mj:”) should be introduced using “[[]]“.

 

Multidimensional objects & multidimensional arrays

Our templating language does permit the usage of multidimensional objects and multidimensional arrays – these are useful in various situations, for example – to introduce values that would be used in a for-loop.

A multidimensional object or array is one that involves variables that are nested one under the other. These are only usable in transactional templates/messages, as they require that the values get provided by the user and this needs to be done via a specific JSON structure.

Here is an example of a multidimensional variable that would need to be presented as a multidimensional object in the JSON data where variables for that message will be declared:

{{var:clothes.winter.coat}}

Each dot (“.”) represents a “layer” of nesting – the leftmost value indicates the outermost level, while the further to the right we move, the further down within the nested structure we find ourselves. Here is the correct JSON structure that needs to be used, so that our system properly locates the value for the “clothes.winter.coat” variable (the example includes the v3.1 “Variables” property but that would vary depending on the transactional channel used, as discussed in a previous section):

 

Tamplating

 

The above setup would result in the word “blazer” being displayed in the position where “{{var:clothes.winter.coat}}” was placed in the template/content of the email.

As for multidimensional arrays, these are more commonly used – specifically in for-loops (more on those in another section). The logic behind how to structure the JSON data would be similar to the one used in the example shown above, with some additions to it (namely, JSON arrays).

Here is a simple example: {{customer.Name}}

If we imagine that this is going to be a variable used in a for-loop (which means we want to assign different values under the same variable – in this case “Name”), we could use an array with nested objects to achieve that. Here is what the JSON would look like:

Tamplating

 

As you can see, we have a nested variable called “Name” under the layer called “customer”, so our JSON structure needs to reflect that. We define “customer” first and we specify that it is an array by opening the square brackets. Within the square brackets, we can use multiple pairs of curly braces to define different values for the “Name” variable. If we weren’t using a multidimensional array (which in a real-life scenario would also be combined with a for-loop), we would not have been able to use the “Name” variable multiple times with different values. We would have needed to use something along the lines of “Name1”, “Name2”, “Name3”, etc. Thus, utilizing a multidimensional array saves us work, makes our JSON easier to manage, all while allowing us to reuse the same variable Name with different values.

We will take a look at another simple multidimensional array in the For-loop section, as well as at a more complex one (one with more layers of nesting).

 

 

If-conditional statements

If-conditional statements are used to introduce requirements that determine whether a specific piece of information should be displayed. They can also include alternative values to be displayed if the initial requirement is not met, using else statements. Additionally, an alternative requirement can be introduced using the elseif conditional statement. An if-statement must be closed with an endif operator.

Typically, if-conditional statements are introduced using template language blocks in a Drag-and-Drop template. However, they can also be added within Text elements. These statements can be used in both Marketing and Transactional templates, although Transactional templates provide more flexibility. In a Transactional template, if-conditionals can be built based on the values of var variables, which are pushed via the Send API or SMTP, as well as data variables, which operate with Contact property values. In a Marketing template, only data variables can be used since there is no way to push values for var variables.

Here is an example of a simple if-conditional statement used in a Marketing template:

 

 

Here is an example of the template language in use:

{% if data:firstname %}
PRINT THIS IN THE MARKETING MESSAGE
{% endif %}

In this example, the template language starts with an opening clause that contains the condition itself. If the condition is met (i.e., the recipient has a value set under the “firstname” property), the system will display the content within the block (“PRINT THIS IN THE MARKETING MESSAGE”). The closing clause signifies the end of the If-conditional section.

The If-conditional statement relies on a Contact property (“firstname”). The system will check whether the recipient has a value set under the “firstname” property. If the answer is yes, the system will include the content within the block in the final version of the email. If the answer is no, the specific string will not be displayed.

Here is an example of what the final version of the email may look like for a recipient who has a defined “firstname” property:

 

Tamplating

 

Here is an example of the final version of the email for a recipient who does not have a defined “firstname” property:

 

Tamplating

 

The above If-condition checks whether the property is defined for the recipient. However, you can introduce a specific value that the property should have for the conditional content to be printed. For example:

 

Tamplating

 

In this example, the conditional content “PRINT THIS IN THE MARKETING MESSAGE” will only be present in the recipient’s version of the message if the “firstname” Contact property is set to the value “Gina”. This condition ensures that the content is displayed exclusively for recipients whose “firstname” property matches the specified value of “Gina”.

Let’s take a closer look at a couple of examples involving Transactional templates. These examples demonstrate the use of both var variables and Template language elements, and they can be applied within Text blocks or Template language blocks.

Example 1: Utilizing a var variable in a Transactional template

 

Tamplating

 

In this example, we are checking if the var “variable” is defined. The condition is either true or false, acting as a Boolean property.

Here’s what you can expect in different scenarios:

  • If the var “variable” is not defined in the Send API (SAPI) call or SMTP session, it will result in a Template language error. Adding a default value in the if-conditional (var:variable:defaultValueHere) will always print “PRINT THIS STRING IN THE TRANSACTIONAL EMAIL” for recipients where the variable is not defined.
  • If the variable is set as true in the SAPI call or SMTP session, the condition will be met.
  • If the variable is set as “anyValueYouCanThinkOfOtherThanFalse” in the SAPI call or SMTP session, the condition will be met.
  • If the variable is set as false in the SAPI call or SMTP session, the condition will NOT be met. Note the difference between “variable”: “false” (previous scenario) and “variable”: false (current scenario).

Example 2: Showcase of other comparison and logical operators (else, elseif, and ifelse + AND)

 

Tamplating

 

This example demonstrates the use of different comparison operators and logical operators. It includes the if, else and elseif statements combined with the logical operator AND.

Finally, here is a screenshot to provide visual reference:

 

Tamplating

 

These examples illustrate how var variables and various operators can be utilized effectively within Transactional templates to customize the content based on specific conditions.

Now, let’s examine pairs of JSON data along with the corresponding results they produce for the end recipient:

JSON 1:

Tamplating

Tamplating

JSON 2:

Tamplating

Tamplating

 

JSON 3:

Tamplating

Tamplating

 

JSON4:

Tamplating

Tamplating

 

Essentially, in order for the value “I’ll consider going out” to be displayed, we require the following conditions to be met simultaneously: the “weather” must not be “bad”, the “bankAccountBalance” value should be different from 0, and the “haveFreeTime” variable must be true (or defined). If any of these three conditions is not met, the value “I won’t be going out” or “I’ll stay at home” will be displayed, depending on which condition is not satisfied.

Please note the usage of the logical operator AND, which necessitates the use of parentheses () to ensure proper grouping of the conditions.

 

For-loops

For-loops allow you to cycle through multiple iterations of a variable or loop through a list of variables, providing flexibility and dynamic content. It’s important to note that for-loops should only be used in Transactional templates and not in Marketing templates, as the values or iterations cannot be introduced in a Marketing message.

Let’s take a look at a simple representation of a for-loop:

 

Tamplating

 

In this example, we define a for-loop with the variable name “Test” and specify the namespace where the system should look for it (var:Test). We assume a simple variable with one iteration. The API call or SMTP headers should include the following JSON structure:

Tamplating

 

Please note that the previous “multidimensional arrays” section contains an alternative way of presenting the same kind of structure that can also be used with for-loops.

The for-loop will be replaced by the values provided in the JSON structure. Here’s an example of what the resulting message would look like.

 

Now, let’s imagine a scenario where you’re part of a company’s Public Relations team and need to send an email to the Financial department. You want to communicate the names, country of residence, and contact phone numbers of three customers who have won a game held by your company and need their contact information reviewed by the Financial team.

To accomplish this, you can utilize a for-loop in your message to cycle through different iterations of the same variable name (e.g., Name, Phone, etc.) and have different values displayed each time.

Here’s an example of how you can set up such a template language configuration:

Tamplating

 

In this case, we use the variable name “customer” to cycle through the customer details provided in the API call or SMTP headers. The JSON structure should follow this format:

Tamplating

 

By using this approach, you simplify the JSON structure and reduce the risk of errors. The resulting email will display the customer details based on the provided iterations.

 

Lastly, let’s explore a more complex example that involves a multidimensional array structure. In this case, we’ll assume a scenario related to winter clothing items.

Here’s the configuration for the for-loop in the template:

Tamplating

 

In this example, we use the “value” variable located under the “items” namespace in the JSON structure. We specify two types of items (coats and hats) with their respective variables nested under multiple layers of variables.

Here’s how the JSON structure for this example would look:

Tamplating

 

The resulting message would display the winter coat and hat values based on the provided iterations.

Tamplating

 

By utilizing for-loops, you can dynamically iterate through variables and generate personalized content in Transactional templates. It’s important to ensure the proper JSON structure and follow the template language syntax to achieve the desired results.

If-conditional statement and For-loops key takeaways table:

Tamplating

 

 

 

Text Blocks – HTML Blocks – Template Language Blocks

When working with email templates, there are different approaches to incorporating template language structures. They can be introduced through Text blocks, HTML blocks, or Template Language blocks in DnD Transactional templates. Additionally, they can be directly embedded within the content of the email.

It is generally advisable to separate raw HTML content from template language structures whenever possible. When there is a need to combine them, such as when creating a table with variable iterations using a for-loop, it is generally safer to utilize an HTML DnD block and incorporate the template language within it rather than adding raw HTML to a Template Language block.

Template Language blocks are especially useful when working with If-conditional statements. Each operator within the If-conditional can be placed in a separate Template Language block, with various other DnD elements serving as the content that will be displayed based on a specific condition. For example, you can display an image element, video element, or button if certain criteria are met. It is possible to open a for-loop or If-conditional in one block and close it in another, providing flexibility and organization.

To maintain clarity and separation, it is recommended to place template language structures in dedicated Template Language blocks rather than mixing them with other content. While plain text can be added within a Template Language block, it is best to use separate blocks for more complex content. When combining raw HTML with template language structures, it is advisable to utilize a raw HTML block where the code is stored alongside the template language, rather than including raw HTML within a Template Language block.

Functions

As discussed earlier, Functions are an essential part of the Esendex templating language, offering a range of operations that can be performed by the system. These functions enable formatting effects across different areas, such as:

  • Mathematical operations: rounding numerical values.
  • String manipulations: converting strings to uppercase or lowercase, or capitalizing the first letter.
  • Number formatting: formatting numbers based on specific rules.
  • URL encoding: converting a string to a URL-safe format.
  • String escaping: ensuring special characters in a string are properly encoded.

By combining these functions with variables, if-conditional statements, and operators mentioned in the Esendex template language reference, you can create highly customizable and dynamic content.

In this section, let’s explore two specific functions: the Set function and the FormatNumberLocale function.

Set function

The Set function is a powerful feature that allows us to assign a value directly to a variable within the template or email content, eliminating the need to declare the variable in the SAPI call or SMTP session.

Let’s take a look at an example:

 

 

In the above example, we use the Set function to assign a value to the variable “testVar” within the template itself. On the next line, we are using the same variable within a sentence.

By using the Set function, I can push a message with an empty Variables object like this:

 

Tamplating

 

This approach allows us to send messages without explicitly defining the variable in the API call, and the message will not be blocked. Here’s the result when the message is sent:

 

Tamplating

 

One of the interesting aspects of the Set function is that you can use it multiple times within the same content to update the value of the same variable. Let’s see an example that corrects a statement:

 

 

In the example above, we update the value of the variable “testVar” within the template. The second assignment overrides the initial value, resulting in the following output:

 

It’s important to note that if you pass a value for the same variable through the API call or SMTP session, it will not override the value set using the Set function within the template.

FormatNumberLocale function

The FormatNumberLocale function allows you to format floating-point numbers (numbers with decimal fractions) according to specific rules. It relies on three properties:

  • Format: Specifies the desired format of the number.
  • Number: Provides the number to be formatted.
  • Locale: Selects the locale to determine the decimal point and thousand separator.

For example, consider the following template code:

Tamplating

 

In this example, we use the French locale (“fr_FR”) to format the number 3500 using the format “#,###.00”. The result will be:

Tamplating

 

You can see that the number now includes thousands separators and decimal points according to the French format.

The FormatNumberLocale function also supports other format variations, such as:

Tamplating

 

These examples demonstrate how slight variations in the format can affect the result. The locale “en_GB” is used for formatting. The outputs will be:

Tamplating

 

When using dynamic variables with the FormatNumberLocale function, make sure to follow the correct syntax:

Tamplating

 

Ensure that the “var:VarName” variable is provided without quotation marks or brackets. Additionally, provide the value for the variable as an integer in the API call or SMTP session:

Tamplating

 

Using quotation marks around the value will cause errors in the templating language.

These functions, along with the vast capabilities of the Esendex template language, empower you to create highly customized and dynamic content in your emails.

 

 

 

 

Extra Notes

It is worth mentioning that variables can be added outside of Text boxes, HTML, or Template Language blocks. You can introduce variables in various other elements, such as hyperlinks, buttons, and image URLs in Image DnD elements.

When using a variable inside a hyperlink or a button’s URL, you can utilize a default variable value. However, it’s important to note that you cannot use a default variable inside the URL associated with an Image DnD element. The system will allow you to save the variable in the URL field with a default value, but it will strip it right away.

Please keep in mind that when adding a default variable within the link of a Button element or a hyperlink, it is possible and works fine. However, you may encounter an error notification in the editor, which can be disregarded. Ensure that the default value is added without quotation marks and without an HTTP/HTTPS protocol at the beginning. For example: {{var:Link:www.esendex.com}}

Template error management

Explore this comprehensive article that will walk you through the process of leveraging the Esendex Template Error Management feature. This powerful feature automates the verification of your templates, saving you valuable time and eliminating the need for manual checks. Say farewell to the tedious task of individually reviewing each template, and welcome a streamlined approach to efficient error management.

Another important point to consider is the declaration of variables in the SAPI call/SMTP session. It should exactly match how they have been added in the message’s content. Case-sensitivity plays a crucial role, so be vigilant for any discrepancies in letter case. Additionally, when using a dot (.) in variables, it indicates multidimensional objects or arrays. If a separator is needed instead of indicating a multidimensional structure, an underscore (_) is a better choice than a dot.

Need more help

Generic selectors
Exact matches only
Search in title
Search in content
Post Type Selectors
Current service status

Can't find what you're looking for?

Speak to a member of our support team.