Velocity Reference

Our system features the dynamic content option using the Apache Velocity library. Let’s review the most common Velocity features to use in Reteno.

Quick reference for Velocity syntax in Reteno.

For practical examples, see Using Velocity in Messages and Using Velocity in Workflows.


Variable Formats

FormatDescription
$discountIf the variable does not exist, outputs the literal text $discount
$!discountSilent — outputs nothing if the value is missing
${discount}Braces unambiguously delimit the variable name from adjacent text
$!{discount}Silent and unambiguous — recommended for production use
${discount|$otherGift}Outputs the fallback value if the variable is missing

Nested Objects

Use dot notation to access fields inside an object:

  • $item.product
  • $lastTraining.trainingDay
  • $manager.phone

Arrays and Indexes

Access an element by index (0-based):

  • $!arrayName[0]
  • $!items[0].parameterName

If the specified index does not exist, an error will occur at send time. Use a loop when the array size is not known in advance.

Get the array size:

  • $!arrayName.size()

Note The exact access path depends on the structure of the payload. Some events contain a plain array, while others wrap it inside an object.


Loops

Iterate over all elements in an array with #foreach:

#foreach($item in $!arrayName)
  $foreach.count: $!item.name
#end

$foreach.count is the loop counter, starting from 1.

Stop the loop early with #break:

#foreach($item in $!arrayName)
  $!item.name
  #if($foreach.count > 5) #break #end
#end

In email HTML, wrap directives in comments: <!--#foreach(...)-->, <!--#end-->


Assignment

Assign a value to a variable for reuse within the template:

#set($var = 'value')

#set($total = $mathTool.add($price, $tax))

Conditions

Basic condition:

#if($!param == 'value')
  content
#end

With alternative:

#if($!param == 'value')
  content
#else
  altContent
#end

Multiple conditions:

#if($!param == 'value1')
  content1
#elseif($!param == 'value2')
  content2
#else
  altContent
#end

Check for non-empty value:

#if($!param && $!param != '')
  content
#end

Operators

Comparison

OperatorMeaning
==Equal
!=Not equal
gtGreater than
ltLess than
geGreater than or equal
leLess than or equal

Logical

OperatorMeaning
&& or andLogical AND
|| or orLogical OR
! or notLogical NOT

String comparison

  • $!firstString.equals($!secondString)
  • $!firstString.equalsIgnoreCase($!secondString)

Arithmetic

  • $mathTool.add($v1, $v2)
  • $mathTool.sub($v1, $v2)
  • $mathTool.mul($v1, $v2)
  • $mathTool.div($v1, $v2)

Number Formatting

Integer without rounding:

  • $numberTool.integer($v1)

Money amount with two decimal places:

  • $!numberTool.format('#.00', $v1)

Dates

Output

Current date:

  • $!dateTool.currentDate()
  • $!dateTool.currentDate('dd.MM.yyyy HH:mm:ss', 'GMT+3')

Current Unix timestamp:

  • $!dateTool.currentTimeStamp()

Format a date from the event or contact field:

  • $!dateTool.formatDate('dd.MM.yyyy', $!date)
  • $!dateTool.formatDate('yyyy-MM-dd HH:mm:ss', $!date)

Format in the contact's time zone:

  • $!dateTool.formatInContactTimezone('dd/MM/yyyy HH:mm:ss', $!dateTime)

Arithmetic

Given "date": "01/01/2020 12:00":

  • $!dateTool.addYears($!date, 2) → 01/01/2022 12:00
  • $!dateTool.addMonths($!date, 5) → 01/06/2020 12:00
  • $!dateTool.addDays($!date, 15) → 16/01/2020 12:00
  • $!dateTool.addHours($!date, 7) → 01/01/2020 19:00
  • $!dateTool.addMinutes($!date, 15) → 01/01/2020 12:15

Negative values subtract:

  • $!dateTool.addDays($!date, -7)

With custom input format — given "customDate": "12:00 2020-30-04":

  • $!dateTool.addYears($!customDate, 2, 'HH:mm yyyy-dd-MM') → 12:00 2022-30-04

With custom input and output format — given "dateTime": "2020-05-01T00:00":

  • $!dateTool.addDays($!dateTime, 2, "yyyy-MM-dd'T'HH:mm", 'dd-MM-yyyy') → 03-05-2020
  • $!dateTool.addHours($!dateTime, 7, "yyyy-MM-dd'T'HH:mm", 'dd/MM HH:mm') → 01/05 07:00
  • $!dateTool.addMinutes($!dateTime, 2, "yyyy-MM-dd'T'HH:mm", 'HH:mm') → 00:02

Difference between two dates

Given "firstDate": "01/01/2019", "secondDate": "05/05/2020":

  • $!dateTool.diff($!firstDate, $!secondDate, 'YEARS') → 1
  • $!dateTool.diff($!firstDate, $!secondDate, 'MONTHS') → 16
  • $!dateTool.diff($!firstDate, $!secondDate, 'DAYS') → 490
  • $!dateTool.diff($!firstDate, $!secondDate, 'HOURS') → 11760
  • $!dateTool.diff($!firstDate, $!secondDate, 'MINUTES') → 705600

With custom format — given "customDate1": "17:15 05/05/2020", "customDate2": "10:05 01/01/2019":

  • $!dateTool.diff($!customDate1, $!customDate2, 'HH:mm dd/MM/yyyy', 'MINUTES') → 706030

Strings

Get string length:

  • $!var.length()

Extract a substring:

  • $!var.substring(startIndex, endIndex)

Replace part of a string:

  • $!var.replace('oldValue', 'newValue')

Change case:

#set($example = 'Ukraine')
$example.toUpperCase()    → UKRAINE
$example.toLowerCase()    → ukraine

Accessing External Source Data

External source data can be used in Velocity when the relevant source is connected, and its values are available in the current context.

The syntax is the same Velocity syntax used for other data in Reteno.

The exact variable path depends on the structure of the returned data and the field names in the source.

Use the field names and data structure available in your source configuration or test payload.

Webhook response data

Webhook response data can be accessed with Velocity when the webhook data is available in the current workflow or message context.

Use the field names exposed by the webhook response and reference them according to the response structure.

As with other data sources, availability depends on the current context.