> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getcollate.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom Helpers Reference

> Complete reference for all 24 Collate custom Handlebars helpers and the standard lookup helper.

# Custom Helpers Reference

Collate provides 24 custom helpers to format and manipulate event data. This page also covers the standard Handlebars `lookup` helper. Use these helpers to transform data in your notification templates.

<Tip>
  Combine multiple helpers to create powerful template logic. For example, use `filter` to show only failed tests, then `limit` to display only the first 5 items.
</Tip>

## Data Extraction

### `pluck` - Extract properties from objects

Extracts a specific property from each object in an array.

**Syntax:**

```handlebars theme={null}
{{#each (pluck array 'propertyName')}}
  {{this}}
{{/each}}
```

**Example:**

```handlebars theme={null}
{{#each (pluck entity.tags 'tagFQN')}}
  <li>{{this}}</li>
{{/each}}
```

Extracts the `tagFQN` property from each tag object, resulting in a simple list of tag names.

### `filter` - Filter lists by property value

Filters array items based on property values.

**Syntax:**

```handlebars theme={null}
{{#with (filter array propertyName="value") as |filtered|}}
  {{#each filtered}}
    {{this}}
  {{/each}}
{{/with}}
```

**Example:**

```handlebars theme={null}
{{#with (filter entity.testCaseResultSummary status="Failed") as |failedTests|}}
  <p>Failed tests: {{length failedTests}}</p>
  <ul>
    {{#each failedTests}}
      <li>{{testCaseName}}</li>
    {{/each}}
  </ul>
{{/with}}
```

Filters test results to show only failed items.

### `split` - Split strings into arrays

Splits a string by a delimiter into an array of parts.

**Syntax:**

```handlebars theme={null}
{{#each (split string "delimiter")}}
  {{this}}
{{/each}}
```

**Example:**

```handlebars theme={null}
{{#each (split entity.fullyQualifiedName ".")}}
  <span class="breadcrumb">{{this}}</span>
{{/each}}
```

Splits a qualified name like `database.schema.table` into individual parts for display.

**Advanced Example - Nested Field Parsing:**

When parsing hierarchical field names like `columns.columnName.tags`, combine with `lookup`:

```handlebars theme={null}
{{#with (split name '.') as |parts|}}
  {{#if (endsWith name '.tags')}}
    Tags for column {{lookup parts 1}}
  {{else}}
    Property {{lookup parts 2}} of column {{lookup parts 1}}
  {{/if}}
{{/with}}
```

### `limit` - Limit array items

Limits the number of items displayed from an array.

**Syntax:**

```handlebars theme={null}
{{#each (limit array maxItems)}}
  {{this}}
{{/each}}
```

**Example:**

```handlebars theme={null}
{{#each (limit failedTests 5)}}
  <li>{{testCaseName}}</li>
{{/each}}
{{#if (gt (length failedTests) 5)}}
  <li>... and {{math (length failedTests) '-' 5}} more</li>
{{/if}}
```

Shows first 5 items and mentions count of remaining items.

<Tip>
  Combine `limit` with other helpers to prevent large notifications:

  ```handlebars theme={null}
  {{#each (limit (filter testResults status="Failed") 10)}}
    {{name}}
  {{/each}}
  ```
</Tip>

### `lookup` - Access array element by index

Accesses a specific element in an array by its index (0-based).

**Syntax:**

```handlebars theme={null}
{{lookup array index}}
```

**Example:**

```handlebars theme={null}
{{#with (split entity.fullyQualifiedName ".") as |parts|}}
  Database: {{lookup parts 0}}
  Schema: {{lookup parts 1}}
  Table: {{lookup parts 2}}
{{/with}}
```

Useful for accessing specific parts after using `split` helper to parse hierarchical names.

## String Operations

### `camelCaseToTitle` - Convert camelCase to Title Case

Converts camelCase strings to Title Case format.

**Syntax:**

```handlebars theme={null}
{{camelCaseToTitle string}}
```

**Example:**

```handlebars theme={null}
Type: {{camelCaseToTitle event.entityType}}
```

Converts `testCase` to `Test Case`, `dataAsset` to `Data Asset`.

### `startsWith` - Check string prefix

Checks if a string starts with a specific prefix.

**Syntax:**

```handlebars theme={null}
{{#if (startsWith string "prefix")}}
  Content shown if true
{{/if}}
```

**Example:**

```handlebars theme={null}
{{#if (startsWith name "columns.")}}
  <p>Column property changed</p>
{{/if}}
```

Useful for identifying specific field types in change descriptions.

### `endsWith` - Check string suffix

Checks if a string ends with a specific suffix.

**Syntax:**

```handlebars theme={null}
{{#if (endsWith string "suffix")}}
  Content shown if true
{{/if}}
```

**Example:**

```handlebars theme={null}
{{#if (endsWith name ".tags")}}
  <p>Tags were modified</p>
{{/if}}
```

Useful for identifying specific field types in change descriptions.

### `textDiff` - Show text differences

Displays the difference between old and new text with strikethrough and highlighting.

**Syntax:**

```handlebars theme={null}
{{textDiff oldText newText}}
```

**Example:**

```handlebars theme={null}
{{#each changes.updates}}
  {{#if (eq name 'description')}}
    Description change: {{textDiff oldValue newValue}}
  {{/if}}
{{/each}}
```

Renders old text with strikethrough and new text highlighted, making changes easy to spot.

**Optional Parameters:**

You can customize the HTML tags used for insertions and deletions:

```handlebars theme={null}
{{textDiff oldValue newValue insTag="mark" delTag="del"}}
```

* `insTag`: HTML tag for inserted text (default: `"b"`)
* `delTag`: HTML tag for deleted text (default: `"s"`)

### `truncate` - Shorten text

Shortens text to a maximum length. When the text exceeds the limit, the helper replaces the final character with an ellipsis (`…`) so the result remains within the requested length.

**Syntax:**

```handlebars theme={null}
{{truncate text maxLength}}
```

**Example:**

```handlebars theme={null}
{{truncate entity.description 100}}
```

Returns the original text when it is within the limit. A missing or invalid limit also returns the original text.

## Comparison & Logic

### `eq` - Equality check

Checks if two values are equal.

**Syntax:**

```handlebars theme={null}
{{#if (eq value1 value2)}}
  Content shown if equal
{{/if}}
```

**Example:**

```handlebars theme={null}
{{#if (eq event.entityType "testCase")}}
  <p>This is a test case</p>
{{/if}}
```

### `gt` - Greater than

Checks if first value is greater than the second.

**Syntax:**

```handlebars theme={null}
{{#if (gt value1 value2)}}
  Content shown if greater
{{/if}}
```

**Example:**

```handlebars theme={null}
{{#if (gt (length failedTests) 0)}}
  <p>Some tests failed</p>
{{/if}}
```

### `and` - Logical AND

Combines multiple conditions with logical AND.

**Syntax:**

```handlebars theme={null}
{{#if (and condition1 condition2)}}
  Content shown if all conditions true
{{/if}}
```

**Example:**

```handlebars theme={null}
{{#if (and (eq event.entityType "table") changes.updates)}}
  <p>Table was updated</p>
{{/if}}
```

Shows content only if both conditions are true.

### `or` - Logical OR

Combines multiple conditions with logical OR.

**Syntax:**

```handlebars theme={null}
{{#if (or condition1 condition2)}}
  Content shown if any condition true
{{/if}}
```

**Example:**

```handlebars theme={null}
{{#if (or (eq status "Failed") (eq status "Aborted"))}}
  <p>Execution had issues</p>
{{/if}}
```

Shows content if any condition is true.

### `not` - Logical NOT

Inverts a condition.

**Syntax:**

```handlebars theme={null}
{{#if (not condition)}}
  Content shown if condition false
{{/if}}
```

**Example:**

```handlebars theme={null}
{{#if (not entity.owner)}}
  <p>This entity has no owner assigned</p>
{{/if}}
```

## Collection Operations

### `groupEventChanges` - Group changes into categories

Organizes field changes into separate categories: updates, additions, and deletions.

**Syntax:**

```handlebars theme={null}
{{#with (groupEventChanges event.changeDescription) as |changes|}}
  {{#each changes.updates}}...{{/each}}
  {{#each changes.adds}}...{{/each}}
  {{#each changes.deletes}}...{{/each}}
{{/with}}
```

**Example:**

```handlebars theme={null}
  {{#with (groupEventChanges event.changeDescription) as |changes|}}
    {{#if changes.updates}}
      <h3>Updated Fields:</h3>
      {{#each changes.updates}}
        {{#if (eq name 'description')}}
          <li><strong>Description:</strong> {{oldValue}} → {{newValue}}</li>
        {{else if (eq name 'tags')}}
          <li><strong>Tags:</strong> {{#each oldValue}}{{this}}{{#unless @last}}, {{/unless}}{{/each}} → {{#each newValue}}{{this}}{{#unless @last}},
  {{/unless}}{{/each}}</li>
        {{else if (eq name 'owner')}}
          <li><strong>Owner:</strong> {{oldValue.displayName}} → {{newValue.displayName}}</li>
        {{else if (eq name 'owners')}}
          <li><strong>Owners:</strong> {{#each oldValue}}{{displayName}}{{#unless @last}}, {{/unless}}{{/each}} → {{#each newValue}}{{displayName}}{{#unless @last}},
  {{/unless}}{{/each}}</li>
        {{else if (startsWith name 'columns.')}}
          {{#with (split name '.') as |parts|}}
          <li><strong>Column {{lookup parts 1}}:</strong> Updated {{lookup parts 2}}</li>
          {{/with}}
        {{else if (startsWith name 'extension.')}}
          {{#with (split name '.') as |parts|}}
          <li><strong>Custom Property '{{lookup parts 1}}':</strong> {{oldValue}} → {{newValue}}</li>
          {{/with}}
        {{else}}
          <li><strong>{{name}}:</strong> {{oldValue}} → {{newValue}}</li>
        {{/if}}
      {{/each}}
    {{/if}}

    {{#if changes.adds}}
      <h3>Added Fields:</h3>
      {{#each changes.adds}}
        {{#if (eq name 'tags')}}
          <li><strong>Tags:</strong> {{#each newValue}}{{this}}{{#unless @last}}, {{/unless}}{{/each}}</li>
        {{else if (eq name 'owner')}}
          <li><strong>Owner:</strong> {{newValue.displayName}}</li>
        {{else if (eq name 'owners')}}
          <li><strong>Owners:</strong> {{#each newValue}}{{displayName}}{{#unless @last}}, {{/unless}}{{/each}}</li>
        {{else if (startsWith name 'extension.')}}
          {{#with (split name '.') as |parts|}}
          <li><strong>Custom Property '{{lookup parts 1}}':</strong> {{newValue}}</li>
          {{/with}}
        {{else}}
          <li><strong>{{name}}:</strong> {{newValue}}</li>
        {{/if}}
      {{/each}}
    {{/if}}

    {{#if changes.deletes}}
      <h3>Deleted Fields:</h3>
      {{#each changes.deletes}}
        {{#if (eq name 'tags')}}
          <li><strong>Tags:</strong> <del>{{#each oldValue}}{{this}}{{#unless @last}}, {{/unless}}{{/each}}</del></li>
        {{else if (eq name 'owner')}}
          <li><strong>Owner:</strong> <del>{{oldValue.displayName}}</del></li>
        {{else if (eq name 'owners')}}
          <li><strong>Owners:</strong> <del>{{#each oldValue}}{{displayName}}{{#unless @last}}, {{/unless}}{{/each}}</del></li>
        {{else if (startsWith name 'extension.')}}
          {{#with (split name '.') as |parts|}}
          <li><strong>Custom Property '{{lookup parts 1}}':</strong> <del>{{oldValue}}</del></li>
          {{/with}}
        {{else}}
          <li><strong>{{name}}:</strong> <del>{{oldValue}}</del></li>
        {{/if}}
      {{/each}}
    {{/if}}
  {{/with}}
```

### `hasFieldInChanges` - Check if field was modified

Checks if a specific field was modified in the change description.

**Syntax:**

```handlebars theme={null}
{{#if (hasFieldInChanges changes "fieldName")}}
  Content shown if field changed
{{/if}}
```

**Example:**

```handlebars theme={null}
{{#with (groupEventChanges event.changeDescription) as |changes|}}
  {{#if (hasFieldInChanges changes "testCaseResult")}}
    <p>Test results changed</p>
  {{/if}}
{{/with}}
```

<Note>
  Must be used with changes from `groupEventChanges`
</Note>

### `length` - Get array/string length

Returns the number of items in an array or characters in a string.

**Syntax:**

```handlebars theme={null}
{{length array}}
```

**Example:**

```handlebars theme={null}
{{#if (gt (length entity.tags) 0)}}
  <p>Tags count: {{length entity.tags}}</p>
{{/if}}
```

## Formatting

### `formatDate` - Format timestamps

Converts timestamps to human-readable date and time format.

**Syntax:**

```handlebars theme={null}
{{formatDate timestamp}}
```

**Example:**

```handlebars theme={null}
<p>Test executed at {{formatDate entity.testCaseResult.timestamp}}</p>
```

Converts timestamps to format like: `2025-11-13 14:30:00`

### `buildEntityUrl` - Generate UI links

Creates a clickable URL that opens the entity in Collate UI.

**Syntax:**

```handlebars theme={null}
{{buildEntityUrl entityType entity}}
```

**Example:**

```handlebars theme={null}
<a href="{{buildEntityUrl event.entityType entity}}">
  {{entity.fullyQualifiedName}}
</a>
```

Generates a link like: `https://your-Collate/entity/table/database.schema.table`

### `parseEntityLink` - Extract entity from link strings

Extracts entity information from entity link strings.

**Syntax:**

```handlebars theme={null}
{{#with (parseEntityLink linkString) as |link|}}
  {{link.entityFQN}}
{{/with}}
```

**Example:**

```handlebars theme={null}
{{#with (parseEntityLink entity.entityLink) as |link|}}
  Tested entity: {{link.entityFQN}}
  Tested column: {{link.arrayField}}
{{/with}}
```

The returned object contains `entityType`, `entityFQN`, `field`, `arrayField`, and `arrayValue`. For a column test, `arrayField` contains the column name.

### `renderTableSample` - Show a table of failed rows

Draws a small table with a sample of the rows that failed a data quality test. Use it in templates for test case alerts.

**Simple version**: Show up to 10 columns and 3 rows.

```handlebars theme={null}
{{{renderTableSample entity.failedRowsSample}}}
```

**Full version**: Show the tested column in bold and set the maximum number of columns and rows.

```handlebars theme={null}
{{#with (parseEntityLink entity.entityLink) as |link|}}
  {{{renderTableSample entity.failedRowsSample link.arrayField 10 3}}}
{{/with}}
```

* `10` is the maximum number of columns to show.
* `3` is the maximum number of rows to show.
* `link.arrayField` is the name of the column that the test checks.

When more data is available, the table adds `... and N more`. Use three curly braces (`{{{ }}}`). With two curly braces, the notification displays the table as raw code.

### `processMentions` - Convert mentions to links

Converts @mention syntax to clickable user profile links. Typically used with user-entered descriptions or comments that may contain @mentions to team members.

**Syntax:**

```handlebars theme={null}
{{{processMentions text}}}
```

**Example:**

```handlebars theme={null}
<p>{{{processMentions entity.description}}}</p>
```

Converts `@john.doe` in text to a link to that user's profile.

<Note>
  Use three curly braces `{{{` to render HTML output without escaping.
</Note>

### `resolveDomain` - Resolve domain references

Displays domain names even when passed as object references.

**Syntax:**

```handlebars theme={null}
{{resolveDomain domainReference}}
```

**Example:**

```handlebars theme={null}
{{#each entity.domains}}
  <li>Domain: {{resolveDomain this}}</li>
{{/each}}
```

<Note>
  This helper gracefully handles multiple input types:

  * Domain object references: `{{resolveDomain domain}}`
  * Already-resolved domain strings: `{{resolveDomain "domain-name"}}`
  * Null/undefined values: Returns empty string
</Note>

## Math Operations

### `math` - Perform calculations

Performs mathematical operations on numbers.

**Syntax:**

```handlebars theme={null}
{{math value1 "operator" value2 "round" decimalPlaces}}
```

**Supported Operators:**

* `+` - Addition
* `-` - Subtraction
* `*` - Multiplication
* `/` - Division
* `round` - Round to decimal places

**Example:**

```handlebars theme={null}
Success rate: {{math (math passedTests "/" totalTests) "*" 100 "round" 2}}%
```

Calculates: (passedTests ÷ totalTests) × 100, rounded to 2 decimal places.

**More Examples:**

```handlebars theme={null}
{{math 10 '+' 5}}              <!-- 15 -->
{{math 100 '-' 30}}            <!-- 70 -->
{{math 5 '*' 3}}               <!-- 15 -->
{{math 20 '/' 4}}              <!-- 5 -->
{{math 3.14159 'round' 2}}     <!-- 3.14 -->
```

## Next Steps

* **Learn Handlebars basics** → [Handlebars Templating Guide](/how-to-guides/data-quality-observability/alerts-notifications/notification-templates/handlebars-templating-guide)
* **Understand available data** → [Template Context Reference](/how-to-guides/data-quality-observability/alerts-notifications/notification-templates/template-context-reference)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.