Documentation Basics Templating

Templating with Handlebars

Use dynamic variables and templates to create personalized, data-driven conversations.

Overview

UniversalChatbot uses Handlebars templating syntax to insert dynamic values into your flow messages, API requests, conditions, and other configurations. This allows you to personalize conversations and work with data collected during the flow.

With templating, you can:

  • Address users by name in messages
  • Include collected information in API requests
  • Display dynamic data fetched from external services
  • Reference system variables like timestamps and user IDs

Basic Syntax

Handlebars expressions are wrapped in double curly braces: {{expression}}

Simple Variable Substitution

To output the value of a variable, use its name within double curly braces:

Hello, {{name}}! Welcome to our service.

If name is set to "Sarah", this renders as: Hello, Sarah! Welcome to our service.

Nested Property Access

Access nested properties using dot notation:

Your order total is {{order.total}} with {{order.items.length}} items.

Accessing Data

Variables in your templates come from several sources:

Flow Variables

Variables created by nodes during flow execution. For example, a Prompt node that stores user input in a variable called user_email:

We'll send confirmation to {{user_email}}

API Response Data

Data returned from API Call nodes is stored in the variable you specify. Access the response body using dot notation:

{{api_response.body.user.name}}
{{api_response.body.account.balance}}
{{api_response.status_code}}

Arrays and Objects

When you reference an array or object directly, it's rendered as JSON:

Your tags: {{user.tags}}

Renders as: Your tags: ["vip","enterprise"]

Array Index Access Not Supported

You cannot access specific array elements by index. Patterns like items.0, items[0], or data.results.0.name will not work. Use #each to iterate over arrays instead.

Variable Sources

Variables available in your templates come from different sources:

Source Variables Description
Flow Data {{variable_name}} Variables set by nodes (Prompt, API Call, etc.)
Date & Time {{@today}}, {{@now}} Current date (YYYY-MM-DD) and timestamp
Request Context {{@request.platform}}, {{@request.user.*}} Platform identifier and user information
Platform Data {{@intercom.*}} Platform-specific data (e.g., Intercom contact info)

System Variables

These variables are always available in every flow:

{{@today}}
Current date in YYYY-MM-DD format
{{@now}}
Current timestamp with time zone
{{@request.platform}}
Platform identifier (webchat, intercom, etc.)
{{@request.user.id}}
Unique identifier for the current user
{{@request.user.name}}
User's name (if collected or provided by platform)
{{@request.user.email}}
User's email address (if collected or provided by platform)
{{@request.user.phone}}
User's phone number (if collected or provided by platform)

Platform-Specific Variables

When deployed to specific platforms, additional variables become available with user and context data from that platform. See the Deployments documentation for platform-specific variable references.

Supported Features

What Works

  • Variable substitution: {{name}}, {{user.email}}
  • Nested property access: {{response.body.data.id}}
  • System variables: {{@today}}, {{@user_id}}
  • Array/object JSON output: Arrays render as JSON strings
  • Missing value handling: Missing variables render as empty strings
  • Block helpers: {{#if}}, {{#unless}}, {{#each}}, {{#with}}
  • Else blocks: {{else}} within conditionals

Block Helpers

Conditionals with #if

{{#if premium_member}}
Welcome back, valued member!
{{else}}
Consider upgrading to premium for more features.
{{/if}}

Negation with #unless

{{#unless email_verified}}
Please verify your email to continue.
{{/unless}}

Iteration with #each

Your items:
{{#each cart.items}}
- {{this.name}}: {{this.price}}
{{/each}}

Special variables available inside #each:

{{@index}} - Current iteration index (0-based)
{{@first}} - True if first item
{{@last}} - True if last item

Example using @last to add commas between items:

{{#each items}}{{this}}{{#unless @last}}, {{/unless}}{{/each}}

Renders as: a, b, c

Context switching with #with

{{#with user.address}}
{{street}}, {{city}} {{zip}}
{{/with}}

Helper Functions

UniversalChatbot provides built-in helper functions for common operations. Use them directly or combine with #if for conditional logic.

String Helpers

Helper Usage Output
upcase {{upcase name}} JOHN
downcase {{downcase name}} john
capitalize {{capitalize name}} John
titleize {{titleize title}} The Quick Fox
truncate {{truncate text "20"}} This is a long te...
default {{default name "Guest"}} Guest (if empty)

Comparison Helpers

Use with #if for conditional rendering. Literal values must be quoted.

Helper Usage Description
eq {{#if (eq status "active")}} Equal to
ne {{#if (ne status "banned")}} Not equal to
gt {{#if (gt count "5")}} Greater than
gte {{#if (gte count "5")}} Greater than or equal
lt {{#if (lt count "5")}} Less than
lte {{#if (lte count "5")}} Less than or equal

Logical Helpers

Helper Usage Description
and {{#if (and premium verified)}} Both must be true
or {{#if (or admin moderator)}} Either can be true
not {{#if (not banned)}} Invert the value

Array Helpers

Helper Usage Description
size {{size items}} Returns array length
contains {{#if (contains tags "vip")}} Check if array has item
join {{join items ", "}} Join array elements
is_empty {{#if (is_empty items)}} Check if nil or empty
is_present {{#if (is_present items)}} Check if has values

Math Helpers

Helper Usage Result
add {{add price tax}} 100 + 10 = 110
subtract {{subtract total discount}} 100 - 20 = 80
multiply {{multiply quantity price}} 5 * 20 = 100
divide {{divide total count}} 100 / 4 = 25

Other Helpers

{{json object}} - Outputs value as JSON string

Combining Helpers

Helpers can be nested using subexpressions (parentheses):

// Uppercase with fallback
Hello {{upcase (default name "guest")}}!

// Check if array has many items
{{#if (gt (size items) "5")}}
You have many items in your cart.
{{/if}}

// Combined conditions
{{#if (and (gt age "18") verified)}}
You're eligible for this offer.
{{/if}}

Note: Literal values in helper calls must be quoted: use "5" not 5. Variable references don't need quotes.

What's Not Supported

Limitations

  • Array index access: items.0, items[0] - use #each instead
  • Comments: {{! comment }} syntax is not supported
  • Unquoted literals: Use "5" not 5 in helper calls
  • Partials: {{> partialName}} partial includes
  • Raw blocks: {{{{raw}}}}...{{{{/raw}}}}
  • Hash arguments: {{helper key=value}} named parameters

No HTML Escaping

Unlike standard Handlebars, our implementation does not HTML-escape output since we're working with plain text messages, not HTML. This means {{variable}} and {{{variable}}} produce the same result.

Working with Arrays

Since array index access isn't supported, use these approaches instead:

Use #each to iterate

{{#each api_response.body.items}}
Item: {{this.name}} - {{this.price}}
{{/each}}

Structure APIs to return direct values

Instead of returning nested arrays requiring index access, configure your APIs to return the specific data you need:

Instead of accessing response.orders.0.items:
// Configure API to return current_order directly
{{current_order.items}}

Access @index within #each

Within an #each block, you can access the current index using @index:

{{#each products}}
{{@index}}. {{this.name}} - ${{this.price}}
{{/each}}

Practical Examples

Personalized Greeting

Hi {{customer_name}}! Thanks for reaching out about your {{inquiry_type}}.

I can see you're contacting us on {{@today}}. Let me help you with that.

API Request URL

https://api.example.com/orders/{{order_id}}/status

Dynamic Request Body

{
  "customer_id": "{{customer_id}}",
  "email": "{{email_address}}",
  "requested_at": "{{@now}}",
  "platform": "{{@platform}}"
}

Conditional Message

{{#if order_status.body.shipped}}
Great news! Your order has shipped and should arrive by {{order_status.body.estimated_delivery}}.
{{else}}
Your order is being prepared and will ship soon.
{{/if}}

Listing Items

Here are the products matching your search:

{{#each search_results.body.products}}
{{@index}}. {{this.name}} - ${{this.price}}
{{/each}}