|
| 1 | +--- |
| 2 | +sidebar_position: 4 |
| 3 | +--- |
| 4 | + |
| 5 | +# Template Variables |
| 6 | + |
| 7 | +[[API Docs](/api/template-variables)] |
| 8 | +[[SDK](https://www.npmjs.com/package/@epilot/template-variables-client)] |
| 9 | + |
| 10 | +:::note |
| 11 | +This article is missing content (TODO) |
| 12 | +::: |
| 13 | + |
| 14 | +The Template Variables API provides variable discovery and substitution email and document templates using [Handlebars](https://handlebarsjs.com/). |
| 15 | + |
| 16 | +## Template Variables API |
| 17 | + |
| 18 | +This API is called to both discover available variables as well as execute the variable substitution using handlebars. |
| 19 | + |
| 20 | +Each time an email or document template is used, the Template Variable API is called with the appropriate standardised parameters. |
| 21 | + |
| 22 | +The Template Variable API uses the Entity API and others to fetch the correct values for each variable when compiling the template. |
| 23 | + |
| 24 | +## Variable Picker |
| 25 | + |
| 26 | +We provide a picker UI for users to search and explore available variables. |
| 27 | + |
| 28 | + |
| 29 | + |
| 30 | +## Variable Builder |
| 31 | + |
| 32 | +Custom variables can be created using the Variable Builder under Configuration > Templates > Variable Builder, or by going directly to [https://portal.epilot.cloud/app/variable-builder](https://portal.epilot.cloud/app/variable-builder) |
| 33 | + |
| 34 | + |
| 35 | + |
| 36 | +You can create the following types of variables: |
| 37 | + |
| 38 | +### Custom Variables |
| 39 | + |
| 40 | + |
| 41 | + |
| 42 | +Custom variables can be composed of any text, and, make use of any of the [Handlebars Helpers](#custom-handlebars-helpers). |
| 43 | + |
| 44 | +To use a custom variable on your document template, use this syntax: |
| 45 | + |
| 46 | +```handlebars |
| 47 | +{{custom_variable_name}} |
| 48 | +``` |
| 49 | + |
| 50 | +**Note:** The handlebars helpers can be directly used on document templates. Custom variables are helpful to contain and reuse complex logics or data. |
| 51 | + |
| 52 | +### Order Table Variable |
| 53 | + |
| 54 | + |
| 55 | + |
| 56 | +Order tables are used to display a table of items of a given [Order](https://docs.epilot.io/docs/pricing/orders). |
| 57 | + |
| 58 | +They are extremely customizable and can also make use of [Custom Variables](#custom-variables) or [Handlebars Helpers](#custom-handlebars-helpers). |
| 59 | + |
| 60 | + |
| 61 | + |
| 62 | + |
| 63 | +For example, customizing it's columns order, style, removing or adding columns, etc. |
| 64 | + |
| 65 | + |
| 66 | + |
| 67 | +Or even completely changing how the table should be rendered, adding a custom header, footer, etc. |
| 68 | + |
| 69 | +To use a custom order table variable on your document template, use this syntax: |
| 70 | + |
| 71 | +```handlebars |
| 72 | +{{~~custom_table_key}} |
| 73 | +``` |
| 74 | + |
| 75 | +## Custom Handlebars Helpers |
| 76 | + |
| 77 | +These are handlebars helpers you can use to further customize your templates. |
| 78 | + |
| 79 | +### Standard Handlebars Helpers |
| 80 | + |
| 81 | +Registers utility helpers from the `handlebars-helpers` library for categories like `math`, `number`, `date`, `comparison`, `match`, `array`, `regex`, `collection`, `object`, `string`, `html`, `markdown`, `url`, and `moment`. Examples include arithmetic operations (`{{add 1 2}}` → `3`), number formatting (`{{formatNumber 1000}}`), date manipulation, conditional logic (`{{ifEq a b}}`), array operations (`{{first arr}}`), and string manipulation (`{{uppercase str}}`). |
| 82 | + |
| 83 | +```handlebars |
| 84 | +{{add 1 2}} |
| 85 | +``` |
| 86 | + |
| 87 | +### formatAddress |
| 88 | + |
| 89 | +This helper formats an address object into a string using `buildFullAddress`. Returns an empty string if the input is not a valid address object. |
| 90 | + |
| 91 | +```handlebars |
| 92 | +{{formatAddress 'billing_address.0'}} |
| 93 | +``` |
| 94 | + |
| 95 | +### calculateColspan |
| 96 | + |
| 97 | +Calculates the colspan for table cells based on the table configuration. Starts with the total number of columns minus 3, adjusts for disabled columns, the presence of an `amount_tax` column, and whether `net_total` is enabled in the footer. Ensures the result is non-negative. Used on [Order Table Variables](#order-table-variable). |
| 98 | + |
| 99 | +```handlebars |
| 100 | +{{calculateColspan table_config}} |
| 101 | +``` |
| 102 | + |
| 103 | +### calculatePeriodColspan |
| 104 | + |
| 105 | +Determines the colspan for period-related table columns. Returns 2 if there are more than 3 enabled columns, 1 if exactly 3 enabled columns and `net_total` is enabled in the footer, or 1 for fewer than 3 enabled columns. Used on [Order Table Variables](#order-table-variable). |
| 106 | + |
| 107 | +```handlebars |
| 108 | +{{calculatePeriodColspan table_config}} |
| 109 | +``` |
| 110 | + |
| 111 | +### calculateSummaryColspan |
| 112 | + |
| 113 | +Calculates the colspan for summary sections by counting the number of enabled and draggable columns in the table header. Returns 0 if no columns are defined. Used on [Order Table Variables](#order-table-variable). |
| 114 | + |
| 115 | +```handlebars |
| 116 | +{{calculateSummaryColspan table_config}} |
| 117 | +``` |
| 118 | + |
| 119 | +### isColumnEnabled |
| 120 | + |
| 121 | +Checks if a specific column is enabled in the table configuration by matching the column ID. Returns `true` if the column exists and is enabled, `false` otherwise. Used on [Order Table Variables](#order-table-variable). |
| 122 | + |
| 123 | +```handlebars |
| 124 | +{{isColumnEnabled table_config 'price'}} |
| 125 | +``` |
| 126 | + |
| 127 | +### shouldDisplayDetails |
| 128 | + |
| 129 | +Determines if detailed information for a specific column should be displayed based on the `showDetails` property of the column in the table configuration. Returns `false` if the column is not found or `showDetails` is not set. Used on [Order Table Variables](#order-table-variable). |
| 130 | + |
| 131 | +```handlebars |
| 132 | +{{shouldDisplayDetails table_config 'description'}} |
| 133 | +``` |
| 134 | + |
| 135 | +### isSummaryVisible |
| 136 | + |
| 137 | +Checks if the summary section is visible by determining if there is at least one enabled column that is not draggable in the table configuration. Used on [Order Table Variables](#order-table-variable). |
| 138 | + |
| 139 | +```handlebars |
| 140 | +{{isSummaryVisible table_config}} |
| 141 | +``` |
| 142 | + |
| 143 | +### isExternalFeesMetadataVisible |
| 144 | + |
| 145 | +Determines if external fees metadata is visible based on the `enable` property of `external_fees_metadata` in the table footer configuration. Used on [Order Table Variables](#order-table-variable). |
| 146 | + |
| 147 | +```handlebars |
| 148 | +{{isExternalFeesMetadataVisible table_config}} |
| 149 | +``` |
| 150 | + |
| 151 | +### gt |
| 152 | + |
| 153 | +Compares two numbers and returns `true` if the first is greater than the second. |
| 154 | + |
| 155 | +```handlebars |
| 156 | +{{gt 5 3}} |
| 157 | +``` |
| 158 | + |
| 159 | +### lt |
| 160 | + |
| 161 | +Compares two numbers and returns `true` if the first is less than the second. |
| 162 | + |
| 163 | +```handlebars |
| 164 | +{{lt 3 5}} |
| 165 | +``` |
| 166 | + |
| 167 | +### eq |
| 168 | + |
| 169 | +Compares two numbers and returns `true` if they are equal. |
| 170 | + |
| 171 | +```handlebars |
| 172 | +{{eq 5 5}} |
| 173 | +``` |
| 174 | + |
| 175 | +### blockHelperMissing |
| 176 | + |
| 177 | +Returns an empty string when a block helper is missing, ensuring no output is rendered. |
| 178 | + |
| 179 | +```handlebars |
| 180 | +{{#missingBlock}}content{{/missingBlock}} |
| 181 | +``` |
| 182 | + |
| 183 | +### helperMissing |
| 184 | + |
| 185 | +Returns an empty string when a helper is not found, preventing errors in the template. |
| 186 | + |
| 187 | +### makeStyle |
| 188 | + |
| 189 | +Converts a table configuration object into a CSS style string by mapping non-object properties to `key: value` pairs, joined with semicolons. Ignores object values and falsy values. Used on [Order Table Variables](#order-table-variable). |
| 190 | + |
| 191 | +```handlebars |
| 192 | +{{makeStyle table_config.style}} |
| 193 | +``` |
| 194 | + |
| 195 | +### <schema>.<property> |
| 196 | + |
| 197 | +Dynamically registered based on schema attributes (e.g., `main.email`, `contact.name`). Retrieves a specific property value from the context data, prioritizing items tagged as "primary" or the first item in an array. If the property is an address identifier (e.g., `street`, `city`), it formats it as a full address using `buildFullAddress`. Supports nested attributes for repeatable or relational schemas. |
| 198 | + |
| 199 | +```handlebars |
| 200 | +{{main.email}} |
| 201 | +``` |
| 202 | + |
| 203 | +### email |
| 204 | + |
| 205 | +Retrieves email data from the context, prioritizing `email` or `billing_email` identifiers. If the data is an array, it takes the first element. Returns the matched value or an empty string if not found. |
| 206 | + |
| 207 | +```handlebars |
| 208 | +{{email "contact"}} |
| 209 | +``` |
| 210 | + |
| 211 | +### billing_email |
| 212 | + |
| 213 | +Retrieves billing email data from the context, prioritizing `billing_email` or `email` identifiers. If the data is an array, it takes the first element. Returns the matched value or an empty string if not found. |
| 214 | + |
| 215 | +```handlebars |
| 216 | +{{billing_email "contact"}} |
| 217 | +``` |
| 218 | + |
| 219 | +### phone |
| 220 | + |
| 221 | +Retrieves phone data from the context, prioritizing `phone` or `billing_phone` identifiers. If the data is an array, it takes the first element. Returns the matched value or an empty string if not found. |
| 222 | + |
| 223 | +```handlebars |
| 224 | +{{phone "contact"}} |
| 225 | +``` |
| 226 | + |
| 227 | +### billing_phone |
| 228 | + |
| 229 | +Retrieves billing phone data from the context, prioritizing `billing_phone` or `phone` identifiers. If the data is an array, it takes the first element. Returns the matched value or an empty string if not found. |
| 230 | + |
| 231 | +```handlebars |
| 232 | +{{billing_phone "contact"}} |
| 233 | +``` |
| 234 | + |
| 235 | +### address |
| 236 | + |
| 237 | +Formats an address from the context data (e.g., `this`, `this.order`, `this.contact`) by searching for addresses with `billing` or `primary` tags. Uses `buildFullAddress` to format the address. Falls back to the first address if no tagged address is found. |
| 238 | + |
| 239 | +```handlebars |
| 240 | +{{address}} |
| 241 | +``` |
| 242 | + |
| 243 | +### billing_address |
| 244 | + |
| 245 | +Formats an address from the context data by searching for addresses with `billing`, `shipping`, or `primary` tags. Uses `buildFullAddress` to format the address. Falls back to the first address if no tagged address is found. |
| 246 | + |
| 247 | +```handlebars |
| 248 | +{{billing_address}} |
| 249 | +``` |
| 250 | + |
| 251 | +### shipping_address |
| 252 | + |
| 253 | +Formats an address from the context data by searching for addresses with `shipping`, `billing`, or `primary` tags. Uses `buildFullAddress` to format the address. Falls back to the first address if no tagged address is found. |
| 254 | + |
| 255 | +```handlebars |
| 256 | +{{shipping_address}} |
| 257 | +``` |
| 258 | + |
| 259 | +### delivery_address |
| 260 | + |
| 261 | +Formats an address from the context data by searching for addresses with `delivery` or `primary` tags. Uses `buildFullAddress` to format the address. Falls back to the first delivery address if no tagged address is found. |
| 262 | + |
| 263 | +```handlebars |
| 264 | +{{delivery_address}} |
| 265 | +``` |
| 266 | + |
| 267 | +### additional_address |
| 268 | + |
| 269 | +Formats an address from the context data by searching for addresses with `primary` tags. Uses `buildFullAddress` to format the address. |
| 270 | + |
| 271 | +```handlebars |
| 272 | +{{additional_address}} |
| 273 | +``` |
| 274 | + |
| 275 | +### withTag |
| 276 | + |
| 277 | +Retrieves a value from an array of items based on a specified tag (defaults to `primary`) and optional attribute. Uses `getValueByTag` to find the matching item and return the attribute value or a formatted address. |
| 278 | + |
| 279 | +```handlebars |
| 280 | +{{withTag items tag="primary" attribute="email"}} |
| 281 | +``` |
| 282 | + |
| 283 | +### yn |
| 284 | + |
| 285 | +Converts a boolean-like value (using the `yn` library) to a translated "Yes" or "No" string (via `i18n.t`). Optionally returns custom `success` or `failure` values if provided. |
| 286 | + |
| 287 | +```handlebars |
| 288 | +{{yn true}} |
| 289 | +``` |
| 290 | + |
| 291 | +### xif |
| 292 | + |
| 293 | +Returns an "x" if the input evaluates to true (via `yn`), otherwise an empty string. |
| 294 | + |
| 295 | +```handlebars |
| 296 | +{{xif true}} |
| 297 | +``` |
| 298 | + |
| 299 | +### customOrderTableVariable |
| 300 | + |
| 301 | +Renders a [Order Table Variable](#order-table-variable). |
| 302 | + |
| 303 | +```handlebars |
| 304 | +{{~~custom_table_key}} |
| 305 | +``` |
| 306 | + |
| 307 | +### formatDateTime |
| 308 | + |
| 309 | +Formats a date/time string using `formatDateTimeIfPossible` with a specified pattern (defaults to `JODA_SHORT_DATE_TIME_FORMAT`). |
| 310 | + |
| 311 | +```handlebars |
| 312 | +{{formatDateTime "2025-05-13" "yyyy-MM-dd HH:mm"}} |
| 313 | +``` |
| 314 | + |
| 315 | +### formatDate |
| 316 | + |
| 317 | +Formats a date string using `formatDateTimeIfPossible` with a specified pattern (defaults to `JODA_DATE_FORMAT`). |
| 318 | + |
| 319 | +```handlebars |
| 320 | +{{formatDate "2025-05-13" "yyyy-MM-dd"}} |
| 321 | +``` |
| 322 | + |
| 323 | +### dateMath |
| 324 | + |
| 325 | +Performs date arithmetic (e.g., adding/subtracting days) using `calculateDate`. Accepts parameters like `inputDate`, `expression`, `inputFormat`, and `format`. Logs errors if processing fails. |
| 326 | + |
| 327 | +```handlebars |
| 328 | +{{dateMath "2025-05-13" "+1d"}} |
| 329 | +``` |
| 330 | + |
| 331 | +### padStart |
| 332 | + |
| 333 | +Pads a string to a target length with a specified pad string (defaults to space) using `padStartHelper`. |
| 334 | + |
| 335 | +```handlebars |
| 336 | +{{padStart "5" 3 "0"}} |
| 337 | +``` |
| 338 | + |
| 339 | +### generateJourneyLink |
| 340 | + |
| 341 | +Generates a journey link based on provided options using `generateJourneyLink`. Logs errors if processing fails. |
| 342 | + |
| 343 | +The helper accepts space separated key-value pairs as arguments (example: param1=value1), which end up in options.hash |
| 344 | + |
| 345 | +It requires journey_id to be passed as a parameter and can have the following manually parsed parameters: |
| 346 | + |
| 347 | +- custom_url: Custom domain to be used in the URL |
| 348 | +- expires_in: Expiration time of the token ([ms](https://github.com/vercel/ms)) |
| 349 | +- nonce: Boolean to add a nonce to the payload |
| 350 | + |
| 351 | +The helper will add the initial_submission_id to the payload if it's available in the context |
| 352 | + |
| 353 | +```handlebars |
| 354 | +{{generateJourneyLink hash.journeyId="123"}} |
| 355 | +``` |
| 356 | + |
| 357 | +### asCurrency |
| 358 | + |
| 359 | +Uses [@epilot/pricing](https://github.com/epilot-dev/pricing) to format the amount using `formatAmount` or `formatAmountFromString`. Accepts `currency` (defaults to `DEFAULT_CURRENCY`), `locale` (defaults to `de`), and `displayZeroAmount` (defaults to `false`). Returns an empty string for invalid or zero amounts unless `displayZeroAmount` is true. |
| 360 | + |
| 361 | +```handlebars |
| 362 | +{{asCurrency 100.50 "EUR"}} |
| 363 | +``` |
0 commit comments