Templating  languages, sometimes called personalization languages – every customer engagement platform has one, but in a different flavour. So which one is the best one?

To find out, I’ve taken 15 most popular customer engagement platforms used for B2C marketing and analyzed the capabilities of their personalization languages to find out which ones offer the most capabilities and customization.

PlatformTemplating Language
ActiveCampaignPersonalization tags
Adobe CampaignECMAScript for XML (E4X)
BrazeLiquid
CleverTapLiquid
Customer.ioLiquid & EMCAScript
EmarsysEmarsys Scripting Language (ESL)
HubSpotHubSpot Markup Language (HubL)
IterableHandlebars
KlaviyoPersonalization tags
LeanplumJinja
MailchimpPersonalization tags
MoEngageJinja
OneSignalLiquid
Salesforce Marketing CloudAMPscript, GTL,  Server-side JavaScript
SendGridHandlebars

Some of the most popular personalization languages are Liquid, Jinja and Handlebars, but there are also platforms like Salesforce who use custom languages – AMPscript.

Also, two platforms using the same templating language doesn’t mean they offer the same capabilities – for example, Liquid OneSignal supports fewer tags compared to Liquid in Braze. This happens because the platforms choose to support different versions of the language, or choose not to support certain functionalities due to their complexity and potential commuting resources they would use.

Comparing Liquid, Jinja, Handlebars and other Templating Languages

Based on my experience, there are 5 things I look for in every personalization language. Each capability builds upon the previous ones, creating a hierarchy of personalization power.

1. Inserting Dynamic Values

The foundation of any personalization language is its ability to dynamically insert values into various communication channels – from emails and push notifications to in-app messages and SMS campaigns. These dynamic values typically come from three main sources:

  • User profile data: Names, preferences, past behaviors
  • Campaign or Flow attributes: Send time, campaign ID, trigger events
  • External data: Promo codes, product information, inventory status

Code:

Hi {{firstName}}, your flight to {{trigger.city}} has been delayed.

Output:

Hi John, your flight to Paris has been delayed.

2. Using Conditional Logic & Operators

This is where personalization gets interesting. Conditional logic acts as the “brain” of your templates, determining what content each user sees based on specific conditions. It’s powered by two key elements:

  • Control Structures: if/else statements and for-loops that direct content flow.
  • Operators: Mathematical and logical tools (addition, subtraction, equals, contains, greater than) that enable comparisons and calculations.

Code:

{% if user.lang == "en" %}
Hi, your flight has been delayed.
{% else if user.lang == "fr" %}
Bonjour, votre vol a été retardé.
{% endif %}

3. Applying Filters

Think of filters as your content’s styling team. They transform raw data into polished, presentation-ready format without changing the underlying information. Common applications include:

  • Array Manipulation: Sorting lists, filtering collections
  • Text Transformation: Capitalizing names, truncating long descriptions
  • Date Formatting: Converting timestamps to user-friendly formats
  • Number Formatting: Rounding decimals, adding currency symbols

Code:

Hi {{firstName}}
Hi {{firstName | capitalize }}
Hi {{firstName | length }}

Date is: {{user.subscription_expiration_date}}
Date is: {{user.subscription_expiration_date | | date: "%B %-d, %Y"}}

Output:

Hi John
Hi JOHN
Hi 4

2024-11-04T13:18:25Z
November 4, 2024

4. Assigning Variables

Variables are temporary containers that make complex personalization more manageable and efficient. Instead of repeating the same calculation or data manipulation multiple times, you store it once and reuse it throughout your template. It’s a foundational element of programming languages, yet many platforms don’t support this – severely limiting their personalization capabilities.

Code:

{% set name = "John" %}
{% set favorite_fruit = "Pineapple, Cherry, Apricot" %}

{% for fruit in favorite_fruit %}
{% if fruit == "Pineapple" %}
Hey {{name}}, here's a recipe for Pina Colada.

{% else if fruit == "Mango" %}
Hey {{name}}, here's a recipe for Mango Margarita.
{% endif %}

{% endfor %}

Output:

Hey John, here's a recipe for Pina Colada.

5. Fetching Dynamic Data via API

The most advanced capability of personalization languages is the ability to make API calls to fetch real-time data during message rendering. This allows for truly dynamic content and advanced use cases like:

  • Content Recommendations: “You might like Beetlejuice because you watched Wednesday.”
  • Weather-Based Recommendations: “It’s 75°F in Miami – perfect for our new summer collection!”
  • Live Inventory Updates: “Only 3 left in stock at your nearest store.”

Personalization Platform Power Rankings

After analyzing 15 leading customer engagement platforms and their templating languages, clear patterns emerge in their personalization capabilities. Here’s how they stack up:

They’ll help you  to achieve your wildest wishes:

  • Liquid – used by Braze, CleverTap, Customer.io, OneSignal
  • Jinja & Jinja-derivatives – used by Leanplum, MoEngage, HubSpot, Emarsys
  • JavaScript-based – used by AdobeCampaign, Salesforce Marketing Cloud

They’ll serve you well, but some things will always be out of reach.

  • Handlebars – used by Iterable, SendGrid
  • Personalization tags – used by Klaviyo

I feel sorry for you

  • Personalization & Merge tags  – used by ActiveCampaign and Mailchimp

*The table has horizontal scroll.

PlatformTemplating LanguageInserting Dynamic ValuesConditional Logic & OperatorsApplying FiltersAssigning VariablesFetch Dynamic Content via API
ActiveCampaignPersonalization tagsYesIf/elseVery limitedNoNo
Adobe CampaignECMAScript for XML (E4X)YesIf/else, for, while, switch caseYesYesYes, via External API
BrazeLiquidYesIf/else for, case, unlessYesYesYes, via Connected Content
CleverTapLiquidYesIf/else, for, switch case, unlessLimitedYesYes, via Linked Content
Customer.ioLiquid & EMCAScriptYesIf/else, for, case, unlessYesYesYes, via Webhook actions & JavaScript
EmarsysEmarsys Scripting Language (ESL)YesIf/else, foreachLimitedYesNo, but feed into relational data
HubSpotHubSpot Markup Language (HubL)YesIf/else, forYesYesYes, Serverless functions
IterableHandlebarsYesIf/else, each, unlessLimitedYesYes, via Data Feeds
KlaviyoPersonalization tagsYesIf/else, forLimitedNoNo
LeanplumJinjaYesIf/else, forYesYesYes, Linked Data
MailchimpPersonalization tagsYesIf/elseNoNoNo
MoEngageJinjaYesIf/else, forLimitedYesYes, Content APIs
OneSignalLiquidYesIf/else for, unlessLimitedYesNo
Salesforce Marketing CloudAMPscript (proprieraty), GTL (based on Handlebars) & Server-side JavaScriptYesIf/else, for, while. switch caseYesYesYes, AMPscript HTTP functions
SendGridHandlebarsYesIf/else, each, unlessLimitedNoNo

The Conclusion

In the end, open-source templating languages like Liquid and Jinja dominate the top tier for good reason—they’re battle-tested and feature-rich, while custom solutions often end up reinventing the wheel (not always well).

Most templating languages share similar syntax patterns, so learning a popular one will give you transferable skills across platforms. To wrap up, here’s a cheat sheet showing which templating languages are most similar and different.

Email templating languages comparison

How did you like this post?

Thanks for your feedback!

🚀

Why name denis-test.com?

© 2024 Denis Kolbas

Privacy Policy