Syntax
SendX renders email content with Go’s template engine, so every merge tag is wrapped in double curly braces and must start with a leading dot (.):
| You want to insert… | Use this | Renders as |
|---|---|---|
| A text value | Hi {{.FirstName}}! | Hi Jane! |
| A value inside a sentence | Your order {{.orderId}} is confirmed. | Your order A12345 is confirmed. |
| A dynamic image | <img src="{{.imageUrl}}" /> | <img src="https://cdn.example.com/x.png" /> |
| A dynamic button/link | <a href="{{.buttonUrl}}">{{.buttonLabel}}</a> | <a href="https://app.example.com/pay">Pay now</a> |
src and href.
Personalizing transactional emails (POST /send/template)
When you send a transactional email with a saved template, you supply the per-recipient values in the customFields object on each to entry. Every key you pass becomes a merge tag of the same name.
Keys map verbatim: the key
orderId populates {{.orderId}}, amount populates {{.amount}}, and so on. You do not need to pre-define these as custom fields in your account — any ad-hoc key works for transactional sends.Variables available in transactional templates
The transactional send path builds a minimal data context. The following are available in a/send/template render:
| Merge tag | Source |
|---|---|
{{.Name}} | The recipient’s name field |
{{.Email}} | The recipient’s email field |
{{.<anyKey>}} | Any key you pass in customFields |
Personalizing campaigns & automations
For campaigns, drip sequences, and workflow emails, SendX pulls values from the contact’s stored profile, so a richer set of native tags is available automatically:| Merge tag | Description |
|---|---|
{{.FirstName}} | Contact’s first name |
{{.LastName}} | Contact’s last name |
{{.Name}} | First + last name |
{{.Email}} | Contact’s email address |
{{.Company}} | Contact’s company |
{{.CreatedDate}} | Date the contact was added (YYYY-MM-DD) |
{{.ViewInBrowserLink}} | ”View in browser” URL |
{{.GlobalUnsubscribeLink}} | Unsubscribe URL |
{{.Address}} | Your account’s physical mailing address (CAN-SPAM footer) |
City becomes {{.City}}. See Custom field naming rules below.
Default (fallback) values
If a value might be missing or blank, wrap it with thefallback helper so the email never shows an empty gap:
FirstName is empty, this renders Hi there!. The SendX editor inserts this form automatically for every merge tag, using "there" as the default — so review the defaults if you want something other than “there” to appear for blank values.
Conditional content & loops
Because SendX uses Go templates, you can conditionally show content or loop over lists. Conditional:Helper functions
A few useful helpers are available inside tags (used as{{helper arg1 arg2}}):
| Helper | Example | Description |
|---|---|---|
fallback | {{fallback .FirstName "there"}} | Returns the default if the value is empty/blank |
capitalize_words | {{capitalize_words .city}} | Title-cases the value |
first_character | {{first_character .FirstName}} | First character (e.g. for an avatar initial) |
formatdate | {{formatdate .date "02 Jan 2006"}} | Formats a date |
todaydate / tomorrowdate / yesterdaydate | {{todaydate "02 Jan 2006"}} | Relative date helpers |
days_until / days_since | {{days_until .expiry}} | Day-count helpers |
Custom field naming rules
When you create a custom field in SendX, the name you pick becomes its merge tag. A few rules apply:- Names are sanitized to letters, digits, and underscores — any other character (including spaces) becomes
_. A field namedOrder IDbecomes the tag{{.Order_ID}}. - These names are reserved (they collide with native attributes) and can’t be used for custom fields:
email,firstname,lastname,company,name. - For transactional
customFieldskeys, use the same rule of thumb — stick to letters, digits, and underscores, and don’t start a key with a digit, so it can be addressed as{{.key}}.
The opaque IDs you see in the REST API (e.g.
custom_field_MnuqBAG2NPLm7PZMWbjQxt) are not what you use in templates. Templates always reference custom fields by their human-readable name.Troubleshooting
A value shows as blank or as 'there'
A value shows as blank or as 'there'
The field had no value for that recipient. Pass the value in
customFields (transactional) or set it on the contact (campaigns). Empty values wrapped in {{fallback .X "there"}} render the default — change the default text if “there” isn’t what you want.A native tag like {{.ViewInBrowserLink}} is empty in a transactional email
A native tag like {{.ViewInBrowserLink}} is empty in a transactional email
Those campaign-level system variables aren’t injected for transactional
/send/template sends. Only {{.Name}}, {{.Email}}, and your customFields keys are available there.