Testing & Troubleshooting Velocity
Dynamic Content Preview
Before sending, preview how Velocity variables render with real data directly in the message editor.
Go to Messages → Messages, open the email, and click Additional settings → Configuring dynamic content.
Enter the parameter values in JSON format and click View message:
{
"firstName": "Jordan",
"subscriptionPlan": "Premium",
"price": 49.99,
"items": [
{
"product": "One-month subscription",
"renewalDate": "2026-04-03"
}
]
}If there are errors in the Velocity code, the preview will show an error description instead of the rendered message.
Testing with Event History
To test a triggered message with real event data:
- Go to Automation → Event history.
- Find the relevant event type and click on any event.
- Copy the parameters from the event.
- Paste them into the Configuring dynamic content panel.
This ensures the variable names in your template match exactly what the event sends.
Checking Available Variable Context
The variables available in a message depend on the data source:
| Source | Available in |
|---|---|
| Contact fields | Any message, any channel |
| Event parameters | Messages sent through the workflow triggered by that event |
| External source data | Messages with the data source connected |
If a variable renders as empty or as a literal string, check whether the expected data source is actually available in the current context.
Case Sensitivity Rules
| Data type | Case sensitivity |
|---|---|
| Contact field names | Case-insensitive: ${firstName} = ${FIRSTNAME} |
| Event parameter names | Case-sensitive: $subscriptionPlan ≠ $SubscriptionPlan |
| External source field names | Case-sensitive: matches column headers or JSON keys exactly |
The most common mistake when moving from contact fields to event params: assuming field names are case-insensitive everywhere. They are not.
Variable not Substituted
Symptom: the message contains a literal $firstName or $subscriptionPlan instead of the actual value.
Causes and fixes:
| Cause | Fix |
|---|---|
| Variable name doesn't match the field or parameter name | Check spelling and case against the contact field list or event parameters in Event history |
Value is missing and bare $var syntax is used | Use $!{var} (silent) or ${var|'fallback'} |
| Event parameter is not available in this context | Verify the message is sent through the correct workflow |
| External data source is not connected to the message | Connect the data source in message settings |
Directive Rendering Issues in Email
Symptom: #foreach or #if content renders as raw text, or the email layout breaks.
Cause: directives in email HTML must be wrapped in comments. Without the comment wrapper, the email client treats them as invalid markup.
Fix: wrap all directives in HTML comments:
<!--#foreach($item in $items)-->
<tr>
<td>$!item.product</td>
</tr>
<!--#end-->
<!--#if($billingCountry == 'US')-->
<p>Billed in USD.</p>
<!--#end-->This rule applies only to email. In SMS, Mobile Push, Web Push, and App Inbox, directives are used without comment wrappers.
Common Mistakes with Arrays and Nested Objects
Index out of bounds
$items[2].product — error if the array has fewer than 3 elements.
Fix: use #foreach when the array size is not known in advance, or check the size first:
#if($items.size() > 2)
$items[2].product
#end
Wrong Variable Path for Structured Data
A variable may fail if the path does not match the actual structure of the event payload, external source response, or webhook response.
Fix: check the available fields and nested structure in your test data, then update the variable path accordingly.
Missing #end
#endEvery #if and #foreach must be closed with #end. A missing #end breaks rendering for everything after it in the template.
<!--#if($billingCountry == 'US')-->
<p>Billed in USD.</p>
<!--#end-->Nested Object not Resolving
$lastTraining.trainingDay— works iflastTrainingis an object$lastTraining[0].trainingDay— use this iflastTrainingis an array
If a nested value is not rendering, check whether the parent is an object or an array in the event payload.
Next Steps
- Velocity Reference — full syntax reference
- Using Velocity in Messages — practical examples for message templates
- Using Velocity in Workflows — practical examples for workflow expressions
Updated about 5 hours ago
