Template Variables
Personalize messages, notifications, and other content with dynamic variables.
Basic Syntax
Use double curly braces: {{variable.property}}
Hello {{member.first_name}}, welcome! I'm {{assistant.name}}.
Available Variables
Member
| Variable | Example |
|---|---|
{{member.first_name}} | "Jane" |
{{member.name}} | "Jane Smith" |
{{member.email}} | "jane@example.com" |
{{member.phone}} | "+1 555 123-4567" |
{{member.date_of_birth}} | "1980-06-15" |
{{member.age}} | 45 |
Member Form Data
Access data type fields by slug and field name:
{{member.data.contact_info.emergency_contact}}
{{member.data.profile.company_name}}
Member Collections
Access collection data types with count, latest record, and recent records:
{{member.collections.patient_visits.count}}
{{member.collections.patient_visits.latest.data.diagnosis}}
{{member.collections.patient_visits.latest.created_at}}
{{member.collections.lab_results.latest.data.result}}
Loop through recent records (up to 50 per type):
{% for visit in member.collections.patient_visits.recent %}
- {{visit.data.diagnosis}} ({{visit.created_at}})
{% endfor %}
Filter by field value across recent records:
{% for visit in member.collections.patient_visits.recent | selectattr("data.status", "equalto", "completed") %}
- {{visit.data.diagnosis}} ({{visit.created_at}})
{% endfor %}
Performance:
.recentloads up to 50 records per collection type (newest first). Use.recent | selectattr(...)when you need to filter by a field value.
Tip:
{{member.data.<collection>.<field>}}also works for collections but returns a non-deterministic record when multiple exist. Usemember.collectionsfor reliable, structured access.
Assistant (Agent in the assistant role)
The assistant variable refers to the AI agent assigned to the current workflow or task — the agent acting in the assistant role for this conversation.
| Variable | Example |
|---|---|
{{assistant.name}} | "Support Bot" |
{{assistant.first_name}} | "Support" |
Task
| Variable | Example |
|---|---|
{{task.name}} | "Customer Onboarding" |
{{task.description}} | "Complete setup" |
Chat
| Variable | Example |
|---|---|
{{chat.id}} | "cht_987654321" |
Phone number (in phone-voice / phone-sms chats)
The workspace phone number the current chat arrived on. Only populated for chats with a linked workspace phone number — typically phone-voice and phone-sms. Renders empty for web-chat and other channels.
| Variable | Example |
|---|---|
{{phone_number.number}} | "+15551234567" |
{{phone_number.name}} | "Reception" |
{{phone_number.brand_name}} | "Acme Health" |
Example template:
You can reach us back at {{phone_number.number}} ({{phone_number.brand_name}}).
Call (in call:completed events)
Only available on call:completed event rules. Lets you branch on how the
call actually ended.
| Variable | Example |
|---|---|
{{call.disposition}} | "busy", "no-answer", "completed", "failed", or "canceled" |
Example CEL condition on a call:completed rule:
call.disposition == "busy"
Example template:
Sorry we missed you — the line was {{call.disposition}} when we called.
Record (in data record events)
| Variable | Example |
|---|---|
{{record.id}} | "12345" |
{{record.data.field_slug}} | Field value |
{{record.owner.name}} | "Jane Smith" |
Snippets
Workspace-scoped reusable text fragments. Reference them anywhere a template is supported.
{{snippets.tone.professional}}
{{snippets.address.hq}}
Snippets can reference other snippets (up to 3 levels deep), so you can compose longer templates from smaller reusable pieces.
Date & Time
Always available as {{datetime.*}}. Common keys:
| Variable | Example |
|---|---|
{{datetime.today}} | "2026-04-28" |
{{datetime.now}} | "2026-04-28T14:32:00Z" |
{{datetime.start_of_week}} | "2026-04-27" |
Filters
Gravity Rail templates are rendered with Jinja2, so every standard Jinja2 filter is available — upper, lower, title, capitalize, trim, default, length, join, replace, truncate, int, float, round, sum, min, max, urlencode, and more. Use them with the pipe (|) syntax: {{ value | filter }}.
On top of those, Gravity Rail adds a few custom filters tailored for member data.
oxford_join — format a list with Oxford commas
Turns a list of values into a grammatically natural English phrase.
| Input | Output |
|---|---|
['apple'] | apple |
['apple', 'pear'] | apple and pear |
['apple', 'pear', 'plum'] | apple, pear, and plum |
Today we discussed {{ member.data.visit.topics | oxford_join }}.
date — format dates and timestamps
Reformats a date, time, or datetime value. Default output is YYYY-MM-DD; pass any strftime format string to customize.
{{ record.created_at | date }} → 2026-04-15
{{ record.created_at | date('%d/%m/%Y') }} → 15/04/2026
{{ record.created_at | date('%B %d, %Y') }} → April 15, 2026
{{ member.date_of_birth | date('%b %d') }} → Apr 15
If the input can't be parsed as a date, the original value is returned unchanged. Empty or missing values render as "".
enum_label — show the readable label of a select-field value
Form fields of type Select and Multi-select store values as short slugs (e.g. high, follow_up_needed). Use enum_label to render the human-readable label the field was configured with instead of the slug.
{{ member.data.call_log.call_reason | enum_label('call_reason', 'call_log') }}
→ "Appointment follow-up"
{{ record.data.status | enum_label('status') }}
→ "Awaiting Response"
How to use it:
- First argument: the field slug inside the data type.
- Second argument (optional): the data type slug. You can omit it when the template is rendered in the context of a record of that data type (event rules on records, record-scoped actions).
Behavior:
- Works with
member.data.*,member.collections.*.latest.data.*,record.data.*, and any other enum value. - Falls back to the raw value if the field, option, or data type can't be resolved — it never errors.
- Respects workspace permissions — if the template executes under a role that can't read the referenced data type, the filter falls back to the raw value instead of leaking the label.
Examples
Simple greeting
Hi {{member.first_name}}, thanks for reaching out!
With form data
Your order for {{member.data.order.product_name}} is confirmed.
Shipping to: {{member.data.shipping.address}}
Conditional content
{% if member.data.profile.company %}
Company: {{member.data.profile.company}}
{% endif %}
Readable enum values in reminders
Your {{ record.data.appointment_type | enum_label('appointment_type') }}
is on {{ record.data.visit_date | date('%A, %B %d') }}.
Composing snippets + filters
{{ snippets.tone.professional }}
You mentioned {{ member.data.intake.concerns | oxford_join }}.
Our next step is {{ record.data.next_step | enum_label('next_step', 'intake') }}.
Title-cased greeting with formatted date
Hi {{ member.first_name | title }}, thanks for reaching out!
Your visit is scheduled for {{ record.data.visit_date | date('%B %d') }}.
Tips
- Test first - Preview templates before using in production
- Handle missing data - Use
{% if %}for optional fields - Use snake_case - All variable names use
snake_caseformat
Related
- Actions — Use template variables in automated notifications
- CEL Expressions — Write dynamic conditions using similar variables
- Forms — Define the data types that template variables access