Purpose: This article explains how merge fields work in Communication Templates: how to insert them with the merge field picker, which fields are available for each audience, and what happens when a field cannot be filled in.
Merge fields let one template produce a personalized message for every recipient, pulling values such as the learner's name, the event dates, or the venue address from your Administrate data at the moment each communication is sent.
This article explains:
- What merge fields are and what they look like
- Inserting fields with the merge field picker
- How the audience controls which fields are available
- Custom fields in templates
- Formatting dates, times, and currency values
- Macros, conditions, and loops for richer content
- What happens when a field is empty or invalid
- Where to get help with template questions
On this page
- What merge fields are
- Insert fields with the merge field picker
- The audience controls which fields are available
- Fields from related records
- Custom fields
- Formatting dates, times, and currency
- Macros: ready-made building blocks
- Conditions, loops, and other Jinja features
- Empty and invalid fields
- Fields beyond the picker (advanced)
- Finding the full field list
- Getting help with templates
- Tips for using AI with Jinja templates
- Troubleshooting
What merge fields are
A merge field is a placeholder written between double curly braces, for example:
Hi {{ contact.first_name }}, your course starts on {{ event.start_tz }}.
When a communication is sent, each placeholder is replaced with the matching value for that recipient. Merge fields work in the template body and in the email subject line, in both email and SMS templates.
Merge fields are not limited to communications: document templates such as Sign-in Sheets and Print-Outs and Certificates use the same picker and the same syntax described here.
Under the hood, templates use Jinja, a widely used templating language. You do not need to know Jinja to work with merge fields, because the picker writes the syntax for you, but the language is there when you want more than single values: conditions, loops, and formatting are all available, and the Macros group in the picker gives you the most common ones ready-made.
Insert fields with the merge field picker
You do not need to memorize field names. The template editor includes a merge field picker that lists the fields available to your template:
- Open the template and place your cursor where the field should go.
- Select the M icon in the editor toolbar to open the merge field picker.
- Browse or search the list. Fields are grouped by the record they belong to, and you can expand a related record (for example the Event's Location) to see its fields.
- Select a field and choose Add to insert it at the cursor.
The picker inserts the placeholder with the correct name and, for dates, times, and money values, includes the right formatting automatically. Inserting from the picker is the recommended way to add merge fields.
Note
The picker is easy to miss. If you have been typing field names by hand or copying them from older templates, look for the M icon in the toolbar of the template editor.
The audience controls which fields are available
The template's Audience decides who receives the message and, with it, which records the template can draw fields from. A template addressed to Students can reference the learner's registration; a template addressed to a Booking Contact can reference the booking instead.
| Audience | Records available to the template |
|---|---|
| Students | The learner's registration and achievements, plus the Event and Course details reached through the registration |
| Learner Booking Contacts | The learner's registration and achievements, as above |
| Contact | The contact and the Event |
| Event Staff | The Event's details, plus the staff member's own assignment on that Event, such as their role. Separate Administrators and Instructors audiences target a single role |
| Booking Owner / Booking Contact / Booking Recipient | The booking, including its details and attributes |
| Payment Billing Email | The payment only: its amount, number, dates, payment lines, and the paying account's name as a field. The payment has no link to learner or booking records, so those cannot be referenced |
| Gift Voucher Recipient | The gift voucher, which carries the recipient's name, email, and postal address, the gift message, the voucher code, balance, and expiry as its own fields. There is no separate contact record behind a voucher recipient |
| Training Pass Recipient | The training pass, including the holder's Contact and Account and the pass type reached through it |
| Training Token Point of Contact | The token issue, including its token account |
| Learning Assignments | The learner's Learning Path assignment, plus the Learning Path and learner details reached through it |
| SurveyMonkey Respondents | The Event, plus the Survey Link field, which inserts the link to the survey (see SurveyMonkey Integration) |
| Scheduled | Used to deliver scheduled reports. These templates are plain content with no merge fields available (a merge field in the template blocks the save with an error); the report itself arrives as an email attachment rather than as content merged into the message |
If a field you expect is missing from the picker, check the audience first: the same field list is not shared across audiences, and changing the audience changes what the picker shows.
The records in the table are the template's starting points. From each of them you can chain into related records (see Fields from related records), but records with no connection to the audience's starting points are unavailable, and the save-time check enforces this: a Payment Billing Email template referencing the learner will not save.
Fields from related records
Merge fields can reach through a record to its related records by chaining names with a dot. For example, an Event template can reference the Event's Location, and through it the Location's Region:
{{ event.location.name }}
{{ event.location.region.name }}
In the picker, related records appear as expandable groups, so you can navigate to these fields without writing the chain yourself.
Custom fields
Custom fields defined on your instance appear in the picker alongside the standard fields, and are inserted in a bracketed form:
{{ event.custom["<field key>"] }}
The bracketed key is the field's Unique API Name where one is set, otherwise an internal key; it is not the name you see on screen. Insert custom fields from the picker rather than typing them: a mistyped key is not caught when the template is saved and simply renders blank.
Custom fields are available in templates for these record types: Learners, Events and Sessions, Accounts, Contacts, Course Templates, Achievements, Learning Paths, Learning Path learners, and Bookings. A custom field becomes available whenever the template's audience gives it access to a record of that type, whether directly or through a related record such as delegate.event.
For bookings, custom fields are labeled Attributes and work the same way. Because custom fields differ from instance to instance, the picker is the reliable way to see which ones are available to your template.
Formatting dates, times, and currency
Formatting is applied with a Jinja filter: a pipe after the field name, followed by the formatting instruction. When you insert a date, time, or money field from the picker, the right filter is added for you:
{{ event.start | date_format(tz=event.tz_name) }}
-> 18 July 2026
To change the presentation, edit the filter rather than retyping the whole placeholder.
The six filters
| Filter | What it does |
|---|---|
date_format |
Formats a date |
time_format |
Formats a time |
datetime_format |
Formats a date and time together |
currency |
Formats a number with thousands separators and two decimal places |
date_diff |
The difference between two dates, in "days" or "years"
|
format_newlines |
Converts line breaks in a plain-text field into HTML line breaks, so multi-line notes display properly in an email |
One example of each, with the output it produces:
{{ event.start | date_format(date_format="full", tz=event.tz_name) }}
-> Saturday, 18 July 2026
{{ event.start | time_format(tz=event.tz_name) }}
-> 09:00 BST
{{ delegate.created_at | datetime_format() }}
-> 1 Jul 2026, 14:32:00
{{ delegate.price | currency }}
-> 1,250.00
{{ event.start | date_diff(delegate.created_at, "days") }}
-> 17
{{ event.notes2 | format_newlines }}
-> Park at the rear of the building.<br>Ring the bell at reception.
Note
The currency filter does not add a currency symbol. Type the symbol yourself, or insert the record's currency field alongside it.
Date and time styles
The date and time filters accept four named styles:
-
short: 18/07/2026 or 09:00 -
medium: 18 Jul 2026 or 09:00:00 -
long: 18 July 2026 -
full: Saturday, 18 July 2026
Each filter has its own default, chosen to suit typical use:
-
date_formatdefaults tolong -
time_formatdefaults toshort -
datetime_formatdefaults tomedium
To pick a different style, pass it using the filter's own name as the option:
{{ event.start | date_format(date_format="full", tz=event.tz_name) }}
-> Saturday, 18 July 2026
Time zones
- Passing
tz=converts the value into that time zone and labels the time with its abbreviation (the "BST" in the outputs above). - The picker inserts
tz=event.tz_namefor Event times, so learners see the Event's local time. - You can pass a fixed zone instead, such as
tz='Europe/London'; any name from the IANA time zone database works.
Custom patterns
For full control over dates and times, pass a pattern string instead of a named style. Pattern letters follow the CLDR date field symbols convention used across the industry; the most useful letters are:
-
yyyyyear -
MMMMfull month name,MMMabbreviated -
ddday of the month -
EEEEweekday name -
HHhours on the 24-hour clock,hhours on the 12-hour clock -
mmminutes -
athe AM/PM marker
{{ event.start | date_format(date_format="EEEE d MMMM", tz=event.tz_name) }}
-> Saturday 18 July
{{ event.start | time_format(time_format="h:mm a", tz=event.tz_name) }}
-> 9:00 AM BST
{{ event.start | time_format(time_format="HH:mm", tz=event.tz_name) }}
-> 09:00 BST
American, European, and other regional formats
Formats automatically follow the language of the template translation being sent, including its regional conventions:
- an American English translation gets month-first dates and the 12-hour clock
- a British or European English translation gets day-first dates and the 24-hour clock
- other languages render their own conventions, for example German produces "18. Juli 2026"
To force a convention regardless of the translation, pass locale=:
{{ event.start | date_format(date_format="short", locale="en_US") }}
-> 7/18/26
{{ event.start | date_format(date_format="short", locale="en_GB") }}
-> 18/07/2026
{{ event.start | time_format(locale="en_US") }}
-> 9:00 AM
{{ event.start | time_format(locale="en_GB") }}
-> 09:00
The locale= value is a standard language or language and region code (de, fr_CA, en_US, pt_BR, and so on, from the Unicode CLDR standard). It is not limited to the languages enabled on your instance, and an unrecognized code falls back to British English.
More formatting options
Jinja's built-in filters also work, such as upper, lower, length, join, and default (a fallback when a value is empty: {{ contact.first_name | default("there") }}).
Macros: ready-made building blocks
Some content needs more than a single value, for example a list of every session on an Event. The merge field picker includes a Macros group with prepared snippets for the most common of these, so you do not have to write the underlying loop yourself.
The macros offered depend on the template's audience:
| Audience | Macros |
|---|---|
| Students / Learner Booking Contacts | All Sessions, All Instructors, All Students, All Payment References |
| Event Staff | All Sessions, All Instructors, All Students, Students Table (a name and signature table for sign-in) |
| Booking Owner / Booking Contact / Booking Recipient | All Interests (the booking's line items with prices), All Payment References |
| Learning Assignments | Track Details, Learning Path Outline |
A macro is ordinary template content once inserted, not a locked block. You can edit the inserted snippet to change wording, separators, or which fields it shows, which also makes macros a good starting point to copy and adapt for lists the picker does not offer.
Conditions, loops, and other Jinja features
Because templates are Jinja, you can go beyond inserting single values. The Jinja template documentation covers the full language; the pieces most useful in Administrate templates are:
-
Formatting filters change how a value is displayed; see Formatting dates, times, and currency above for Administrate's filters and Jinja's built-ins.
-
Conditions show content only when something is true. An
{% else %}branch is optional, and conditions can test comparisons as well as fields; see the Jinja documentation on if for the full syntax:
{% if delegate.passed %}Congratulations on passing!{% else %}Please contact us about next steps.{% endif %}
-
Loops repeat content for each item in a list, which is what the macros are built from. Inside a loop,
loop.indexnumbers the items andloop.lastis true on the final one, which is how the example below places commas between items; see the Jinja documentation on for for more, including sorting and filtering the list:
{% for session in delegate.event.sessions %}{{ session.title }}{% if not loop.last %}, {% endif %}{% endfor %}
Templates run in a restricted sandbox, so Jinja features that reach outside the template are unavailable, and a template can never change your data: merge fields read values, nothing more.
Empty and invalid fields
Two different situations look similar but behave differently:
-
The field exists but has no value for this recipient. The placeholder renders as blank. The message still sends, with an empty space where the value would be. For example, if an Event has no External Notes,
{{ event.notes2 }}produces nothing. - The field does not exist. Administrate checks every merge field when you save the template. A placeholder that does not match a real field blocks the save with an Invalid merge field error, so typos are caught before any message is sent.
A template that saves cleanly can still fail at send time in rare cases, for example when a formatting instruction is applied to a value it cannot handle. When that happens the communication is not sent and the trigger log records a "Template could not be rendered" error, so check the trigger logs if an expected message never arrived.
Note
Because empty fields render as blank without any warning, send yourself a test of the template using realistic data before putting it into use, and take care with sentences that read badly when a value is missing. Rely on a test send rather than the browser preview: previews may not populate merge fields, depending on the preview method and available context.
Fields beyond the picker (advanced)
The picker shows a curated list of the most useful fields, but it is not exhaustive. The records behind a template carry additional fields, and some related records can be reached with a dot chain even where the picker does not offer a group for them. If you know a field exists, you can type its placeholder by hand. The Merge Field Reference lists every field for every template object, including the ones the picker does not show.
Hand-typed fields go through the same save-time check as picked fields: if the name does not match a real field, the template will not save; if it saves, it will work.
Note
This is an advanced technique. Field names follow Administrate's internal data model rather than the labels you see on screen, and hand-typed fields do not come with the picker's automatic formatting. Test the template carefully, and ask your implementation contact or Administrate Support if you need help finding the right field name.
Finding the full field list
The Merge Field Reference lists the fields on every template object, including the advanced fields the picker does not show. Two things it cannot cover: your instance's custom fields, which differ from instance to instance, and how far you choose to chain into related records. For those, the picker is the authoritative view of what your template can use right now.
Getting help with templates
For everyday questions, such as which field to use or why a value came through blank, contact Administrate Support.
For heavier template work, conditions, loops, or reworking a complex layout, two other routes work well:
- AI assistants are very good at Jinja. Working with templates is a task AI handles well; see Tips for using AI with Jinja templates below for how to get good results.
- Technical colleagues will find it familiar. Jinja is one of the most widely used templating languages, so web developers and technically minded colleagues have often worked with it or something very similar.
Tips for using AI with Jinja templates
An AI assistant can rework a template far faster than trial and error in the editor, and experimenting is safe: an invalid field cannot be saved, so a wrong suggestion is caught before it can reach a recipient. To get good results:
- Say what the template is. Tell the assistant it is a Jinja email template from Administrate. Naming the language matters; Jinja is widely known, so the assistant will use the right syntax.
- Give it the documentation instead of letting it guess. Share this article and the relevant tables from the Merge Field Reference so the assistant works from the fields that actually exist.
- Paste the real template. For emails, copy from the editor's HTML view so nothing is lost in translation.
- Ask for the complete template back, not a fragment, so you can paste the result straight into the editor.
- Verify the result. Save it (the save-time check catches any invalid field) and send yourself a test with realistic data to check for blank values.
- Iterate in the same conversation. If the first result is not quite right, describe what to adjust; the assistant still has your template and field list.
A prompt along these lines works well:
I have an email template from Administrate, a training management
platform. Templates use the Jinja templating language, and I have
included Administrate's documentation of the fields available to me.
What I want changed: list each session on its own line with its date,
and only show the "bring your laptop" paragraph when the event has
External Notes.
My current template (from the editor's HTML view):
[paste your template here]
Available fields (from Administrate's Merge Field Reference):
[paste the tables for your template's objects, for example Learner
registration and Event]
Please return the complete updated template with everything else
unchanged, and briefly explain what you changed.
Replace the "what I want changed" line with your own goal.
Troubleshooting
- The field I need is not in the picker: check the template's audience. If the audience is right and the field still is not listed, it may be reachable as a hand-typed field; contact your implementation contact or Administrate Support.
- The placeholder came through blank: the field had no value for that recipient. Check the source record.
- I cannot save the template: an Invalid merge field error means one of your placeholders does not match a real field. Re-insert it from the picker.
- The communication never sent: check Trigger Logs for a "Template could not be rendered" error.