Merge fields: the {{…}} placeholders that personalise pre-written messages
Drop contact data into fixed-mode triggers, follow-ups, voice openers, fallback lines, and the Advanced business-context glossary.
Updated June 26, 2026
Merge fields let you write one message template and have it render
differently per contact. Type {{contact.first_name}} in a follow-up,
and at send time it becomes "Hi Jamie" or "Hi Alex" depending on whose
number is on the other end.
Where they work
Anywhere you're writing a pre-written template — not anywhere the
AI composes its own reply.
- Fixed-mode trigger messages (Triggers tab, when "Fixed message"
- Follow-up steps (Follow-ups tab — each step's message body)
- Voice opener / closer / end-of-call phrase (Voice tab)
- Fallback message (Settings tab, when behaviour is "Send a
- Widget welcome message (Widget config)
- Qualifying question text (Qualifying tab)
- Business Context glossary on Advanced agents
The AI's own replies don't need merge fields because the agent already
sees the contact data and personalises naturally. Writing{{contact.first_name}} in the system prompt is usually redundant.
Syntax
{{token}} → empty string if missing
{{token|fallback text}} → "fallback text" if missing
The token path uses dots: {{namespace.key}}. The optional |fallback
after a pipe renders in place of an empty or missing value.
Always use a fallback on anything that might be empty. First names,
custom fields, and calls from unknown numbers can all hit a blank.{{contact.first_name|there}} reads naturally in both cases.
The tokens
Contact
{{contact.first_name|fallback}}— first name, or extracted from{{contact.last_name|fallback}}— last name{{contact.full_name|fallback}}— whole name{{contact.email|fallback}}/{{contact.phone|fallback}}{{contact.company|fallback}}/{{contact.city|fallback}}/{{contact.tags|fallback}}— comma-joined list
Custom fields (contact-level only)
{{custom.<fieldKey>|fallback}} resolves against the contact's GHL
custom fields. The <fieldKey> is the stable slug from Settings →
Custom Fields (usually contact.your_field_name in GHL). The{{…}} Insert value picker pre-populates with the real field keys
from your location so you don't have to type them.
Note: There's no {{opportunity.*}} or {{custom.vehicle_color}}
for opportunity-level custom fields — opportunities can be multiple per
contact (which one would merge?). See Advanced agents
for how the AI reads opportunity data directly instead.
Agent
{{agent.name|fallback}}— the agent's display name (or persona
Assigned user (contact's CRM owner)
The team member assigned to the contact in GHL. Requires the OAuth
scope users.readonly — reconnect GHL from Integrations if the
values come back empty. Useful for "your rep is Alex at
+1 415 555 0100" style templates.
{{user.name|our team}}— full name{{user.first_name|fallback}}/{{user.last_name|fallback}}{{user.email|fallback}}{{user.phone|fallback}}{{user.extension|fallback}}
Date
{{date.today}}— locale-friendly like "Saturday, November 8"{{date.tomorrow}}— same, next day- Respects the agent's timezone if set (Working Hours tab)
Worked examples
Fixed-mode trigger message, tag-added event:
Hi {{contact.first_name|there}}, thanks for reaching out about
{{custom.service_interest|our services}}. I'm {{agent.name|from the
team}}. Quick question — what's got you looking right now?
Follow-up step, "schedule a chat":
Hey {{contact.first_name|there}}, looping back —
{{user.name|our team}} has some availability
{{date.tomorrow}}. Want me to lock in a time?
Voice call opener:
Hi {{contact.first_name|there}}, this is {{agent.name|calling from}}
about your inquiry. Got a few minutes?
The Insert-value picker
Every merge-aware textarea has a {{…}} Insert value button in the
top-right corner. Click it to get a grouped, searchable list of every
token available — built-ins, your CRM custom fields (auto-fetched),
and a link to this reference page. Typing into the search box filters
live; Enter inserts the top match at the cursor.
How it works at send time
When a pre-written message is about to send, we:
- Load the contact record (name, fields, tags)
- Hydrate contact custom fields (match
fieldKeyto your tokens) - Resolve the assigned user if any
{{user.*}}tokens are used - Substitute every
{{token}}in the template - Send the result
If any step fails (e.g. GHL scope missing, contact deleted), the
affected tokens fall back to their |fallback value or render as
empty — the message still sends. No half-rendered templates.
Common mistakes
- Using tokens in AI instructions — the agent already has the
- Forgetting fallbacks —
"Hi {{contact.first_name}},"on an - Assuming
{{user.*}}works without the scope — if you added - Using
{{custom.*}}for opportunity data — opportunity-level