Templating Guide
We use a Handlebars-based template engine that lets you build fully dynamic email templates. It provides powerful features to customize content based on your data.
- Variables: Insert placeholders that are automatically replaced with real values when the email is sent.
- Conditionals: Show or hide sections of content based on specific conditions.
- Loops: Iterate over collections such as arrays, maps, slices, or structs to generate repeated or dynamic sections.
- Custom Helpers: Apply custom logic for formatting, comparisons, and advanced template behavior.
Based on your workspace, contact, and event data, you can use simple variables, expressions, and nested objects or arrays to create highly flexible and complex templates.
Available Variables
Every email template has access to the following top-level variables, automatically populated at render time:
| Variable | Type | Description |
|---|---|---|
preview_text | String | The preview text for the email, displayed in the inbox before the email is opened. |
workspace | Object | Refers to Workspace Properties that can be created at Workspace Settings. Access nested properties with dot notation: {{workspace.name}}. |
contact | Object | Contains data about the recipient contact (e.g. email_address, name, custom fields). Access nested properties with dot notation: {{contact.email_address}}. |
actions.view_online_url | String | A URL that allows the recipient to view the email in their browser. |
actions.confirm_url | String | A URL for the recipient to confirm their subscription. |
actions.unsubscribe_url | String | A URL for the recipient to unsubscribe from future emails. |
event | Object | Contains data about the event that triggered the email (if applicable). Access nested properties with dot notation: {{event.name}}. |
For example, to include an unsubscribe link and greet the contact by name:
Built-in & Custom Helpers
In addition to Handlebars built-in helpers (if, unless, each, with, lookup, etc.), we've registered several custom helpers for your convenience:
| Helper | Description |
|---|---|
eq | Returns true if two values are equal. Usage: {{#if (eq status "active")}}...{{/if}} |
ne | Returns true if two values are not equal. Usage: {{#if (ne role "admin")}}...{{/if}} |
gt | Returns true if the first value is greater than the second (numbers only). Usage: {{#if (gt amount 10)}}...{{/if}} |
lt | Returns true if the first value is less than the second (numbers only). Usage: {{#if (lt score 50)}}...{{/if}} |
gte | Greater than or equal comparison (numbers only). Usage: {{#if (gte amount 100)}}...{{/if}} |
lte | Less than or equal comparison (numbers only). Usage: {{#if (lte score 40)}}...{{/if}} |
and | Logical AND. Returns true if both values are truthy. Usage: {{#if (and a b)}}...{{/if}} |
or | Logical OR. Returns true if either value is truthy. Usage: {{#if (or a b)}}...{{/if}} |
not | Logical NOT. Returns true if the value is falsy. Usage: {{#if (not is_disabled)}}...{{/if}} |
uppercase | Converts a string to uppercase. Usage: {{uppercase name}} |
lowercase | Converts a string to lowercase. Usage: {{lowercase email}} |
capitalize | Capitalizes the first letter of a string. Usage: {{capitalize city}} |
truncate | Truncates a string to a specified length, adding ellipsis if needed. Usage: {{truncate description 50}} |
default | Returns the default value if the variable is undefined or empty. Usage: {{default value "N/A"}} |
formatDate | Formats a date string according to the specified format. Usage: {{formatDate value "Y-m-d"}}. See Carbon date formatting docs. |
raw | Outputs HTML content without escaping, allowing raw HTML to render directly. Use with caution. Usage: {{raw html}} |
If you need additional custom helpers, you can request them via our support channels, and we'll get coding!
Example Template
Nesting Helpers
Helpers can be combined to build compound expressions. Wrap each helper call in parentheses and nest them as needed:
Using #with for Scoping
The #with block helper lets you scope into a nested object, so you don't have to repeat the parent key on every variable:
This is equivalent to writing {{capitalize contact.first_name}}, {{contact.email_address}}, etc., but keeps your templates cleaner when referencing many properties from the same object.
HTML Escaping
All variable output is HTML-escaped by default to prevent XSS vulnerabilities. For example, if a variable contains <b>bold</b>, it will render as the literal text <b>bold</b> rather than bold.
To output raw, unescaped HTML, use the raw helper:
Only use raw with content you trust. Never use it with user-supplied input that hasn't been sanitized.
Fallback Rendering
If a template fails to compile due to syntax errors, CampaignLark will attempt a fallback render before discarding the email. During fallback, simple variable placeholders like {{contact.first_name}} and {{workspace.name}} are still replaced with their actual values and the resulting HTML is injected into the send queue. Complex expressions, conditionals, and loops will not be processed during fallback.