Template Variables

Personalize messages and notifications with dynamic variables like member names and form data.

Advanced
6 min read

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

VariableExample
{{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: .recent loads 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. Use member.collections for 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.

VariableExample
{{assistant.name}}"Support Bot"
{{assistant.first_name}}"Support"

Task

VariableExample
{{task.name}}"Customer Onboarding"
{{task.description}}"Complete setup"

Chat

VariableExample
{{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.

VariableExample
{{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.

VariableExample
{{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)

VariableExample
{{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:

VariableExample
{{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.

InputOutput
['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_case format
  • Actions — Use template variables in automated notifications
  • CEL Expressions — Write dynamic conditions using similar variables
  • Forms — Define the data types that template variables access