Creating Notification Templates
Template System: RunReveal uses Handlebars-style templating (via Raymond) to create dynamic notifications that adapt to your detection data.

Template Syntax Guide
Use fieldName syntax to insert dynamic values. Most fields are under detection for both scheduled and streaming detections.
Full markdown support including:
Overview
Notification templates allow you to customize how alerts are formatted and delivered across different channels. Templates support conditional logic, data iteration, markdown rendering, and channel-specific formatting.
Using the Template Builder
RunReveal provides a visual template builder in the dashboard to create and manage your notification templates.
๐ ๏ธ Quick Start: Creating Your First Template
Step-by-Step Guide
Navigate to Notification Channels in the RunReveal dashboard, then click on the Templates tab.
Path: Dashboard โ Notification Channels โ Templates
Click the Create Template button. Give your template a descriptive name that reflects its purpose (e.g., โCritical Security Alertโ, โDaily Digest Summaryโ).
Enter your title template in the Title field. This appears as the email subject line or message header. Keep it concise and include key information like severity and detection name.
[{{detection.severity}}] {{detection.displayName}} - {{detection.resultCount}} results
Enter your body template in the Body field. This is the main content of your notification. Use Handlebars syntax for dynamic content, markdown for formatting, and helpers for advanced features.
{{detection.name}}{{#ifEqualsโฆ}}{{table results}}The template editor shows a Preview of how your markdown and formatting will render. Note that the preview displays your template structure with placeholder valuesโit does not use real detection data.
Testing with Real Data: To see your template with actual detection data, use the Send Test button on your notification channel after saving the template. This sends a test notification using sample detection data to your configured destination (Slack, email, etc.).
- โ Markdown rendering
- โ Template structure
- โ Formatting validation
- โ Real variable substitution
- โ Conditional logic evaluation
- โ Channel-specific formatting
Click Save Template to create your template. Then assign it to detections by editing the detection and selecting your template from the Notification Template dropdown.
๐ก Tip: You can also specify templates in Detection-as-Code using the notificationTemplate field.
Assigning Templates to Detections
- Go to Detections โ Detection Queries
- Edit the detection you want to customize
- Find the โNotification Templateโ dropdown
- Select your custom template
- Save the detection
Template Structure
Templates consist of two parts:
๐ Title Template
๐ Body Template
Core Concepts
Inserting Dynamic Values
Access detection properties using dot notation. Variables are wrapped in double curly braces.
Basic Syntax
detection.displayNamedetection.severitydetection.riskScoredetection.resultLink2. Conditional Logic
Conditional helpers allow you to show or hide content based on detection properties.
Comparison Helpers
Equality Checks
ifEquals- Check if values are equalifNotEquals- Check if values differ
Numeric Comparisons
ifGreaterThan- Greater thanifLessThan- Less thanifGreaterThanOrEqual- Greater or equal
String Operations
ifContains- String containsifStartsWith- String starts withifEndsWith- String ends with
Empty Checks
ifNotEmpty- Value existsifEmpty- Value is empty
๐ก Example Use Cases
- โข Show critical alert banner only when severity equals โCriticalโ
- โข Display high-risk warning when risk score is greater than 80
- โข Show error message only when detection.error is not empty
- โข Customize content based on channel type (email vs Slack)
3. Data Iteration
Loop through detection results and arrays to display multiple items.
Loop Helper
Basic Loop Structure
Common Patterns
- โข Loop through detection results
- โข Iterate over categories array
- โข Process MITRE techniques
- โข Display extracted fields
Best Practices
- โข Always check ifNotEmpty before looping
- โข Use index for numbering items
- โข Use first/last for special formatting
- โข Limit display to first N items if needed
4. Table Generation
Automatically format detection results as tables for better readability.
Auto-Detect Columns
table detection.resultsSpecify Columns
tableWithColumns detection.results โcol1โ โcol2โ5. Markdown Rendering
Convert markdown content to HTML for rich formatting in your notifications.
๐ Markdown Support
Supported Markdown Features
Template Organization Patterns
Pattern 1: Severity-Based Styling
Organize content based on detection severity levels.
Pattern 2: Risk Score Visualization
Display risk scores with visual indicators.
Risk Score Ranges
Pattern 3: Result Organization
Structure detection results for clarity.
Recommended Structure
- 1Summary SectionDetection name, severity, risk score, result count
- 2Results TableFormatted table of detection results
- 3Detailed AnalysisLoop through results for detailed view
- 4Action ItemsInvestigation steps and quick links
Template Variables Reference
Detection Object Properties
| Property | Type | Description |
|---|---|---|
| detection.id | string | Unique execution ID |
| detection.displayName | string | Human-readable detection name |
| detection.severity | string | Severity level (Critical, High, Medium, Low) |
| detection.riskScore | number | Risk score (0-100) |
| detection.resultCount | number | Number of results found |
| detection.results | array | Query results (array of objects) |
| detection.resultLink | string | URL to view full results |
| detection.categories | array | Category tags |
| detection.error | string | Error message if execution failed |
Channel Variable
channel - The notification channel type (email, slack, discord, webhook, jira, pagerduty, linear, google-chat)
Best Practices
โ Do
- โข Keep titles concise (50-100 characters)
- โข Always check ifNotEmpty before iterating
- โข Include error handling sections
- โข Provide investigation steps
- โข Link to full results
- โข Test with empty results
- โข Use markdown for rich formatting
โ Donโt
- โข Assume results always exist
- โข Create overly long titles
- โข Skip error handling
- โข Hard-code values that should be dynamic
- โข Forget to test edge cases
- โข Use complex nested conditionals unnecessarily
- โข Ignore channel-specific formatting needs
Ready-to-Use Templates
Copy & Paste Ready: Each template below can be copied directly into RunRevealโs notification template editor. Templates demonstrate different features of the Handlebars templating system.
A simple template demonstrating basic variable substitution. Use double curly braces to insert detection properties like name, severity, and risk score.
[{{detection.severity}}] {{detection.displayName}}- โ Simple variable syntax
- โ Dot notation for nested properties
- โ Markdown formatting support
Title:
[{{detection.severity}}] {{detection.displayName}} - {{detection.resultCount}} resultsBody:
## {{detection.displayName}}
**Severity:** {{detection.severity}}
**Risk Score:** {{detection.riskScore}}
**Results Found:** {{detection.resultCount}}
[View Full Results]({{detection.resultLink}})Use ifEquals to show different content based on severity level. Great for adding visual indicators and urgency messaging.
Title:
{{#ifEquals detection.severity "Critical"}}๐จ CRITICAL: {{/ifEquals}}{{#ifEquals detection.severity "High"}}โ ๏ธ HIGH: {{/ifEquals}}{{#ifEquals detection.severity "Medium"}}๐ MEDIUM: {{/ifEquals}}{{#ifEquals detection.severity "Low"}}โน๏ธ LOW: {{/ifEquals}}{{detection.displayName}}Body:
# {{detection.displayName}}
{{#ifEquals detection.severity "Critical"}}
> ๐จ **CRITICAL ALERT** - Immediate action required!
{{/ifEquals}}
{{#ifEquals detection.severity "High"}}
> โ ๏ธ **High Priority** - Review within 1 hour
{{/ifEquals}}
{{#ifEquals detection.severity "Medium"}}
> ๐ **Medium Priority** - Review within 24 hours
{{/ifEquals}}
{{#ifEquals detection.severity "Low"}}
> โน๏ธ **Low Priority** - Review when convenient
{{/ifEquals}}
| Property | Value |
|----------|-------|
| Severity | {{detection.severity}} |
| Risk Score | {{detection.riskScore}} |
| Results | {{detection.resultCount}} |
[View Details]({{detection.resultLink}})The table helper automatically formats detection results as a markdown table. Use tableWithColumns to specify which columns to display.
table detection.resultstableWithColumns detection.results โuserโ โactionโTitle:
{{detection.displayName}} ({{detection.resultCount}} matches)Body:
## {{detection.displayName}}
**{{detection.resultCount}}** results found | **Risk Score:** {{detection.riskScore}}
{{#ifNotEmpty detection.results}}
### Detection Results
{{table detection.results}}
{{/ifNotEmpty}}
{{#ifEmpty detection.results}}
_No results to display._
{{/ifEmpty}}
[Open in RunReveal]({{detection.resultLink}})Use #each to iterate through arrays. Access the current item with this, index with @index, and object keys with @key.
Title:
{{detection.displayName}} - {{detection.resultCount}} events detectedBody:
# {{detection.displayName}}
{{detection.resultCount}} events require your attention.
{{#ifNotEmpty detection.results}}
## Event Details
{{#each detection.results}}
### Event {{@index}}
{{#each this}}
- **{{@key}}**: {{this}}
{{/each}}
---
{{/each}}
{{/ifNotEmpty}}
{{#ifEmpty detection.results}}
_No events to display._
{{/ifEmpty}}
[View Full Analysis]({{detection.resultLink}})Use numeric comparison helpers to create threshold-based messaging. Combine ifGreaterThan and ifLessThan for range checks.
Low Risk
Elevated
High Risk
Title:
{{#ifGreaterThan detection.riskScore 80}}๐ด{{/ifGreaterThan}}{{#ifGreaterThan detection.riskScore 60}}{{#ifLessThan detection.riskScore 81}}๐ {{/ifLessThan}}{{/ifGreaterThan}}{{#ifLessThan detection.riskScore 61}}๐ข{{/ifLessThan}} {{detection.displayName}}Body:
## {{detection.displayName}}
{{#ifGreaterThan detection.riskScore 80}}
### ๐ด Very High Risk ({{detection.riskScore}}/100)
This detection requires immediate attention.
{{/ifGreaterThan}}
{{#ifGreaterThan detection.riskScore 60}}
{{#ifLessThan detection.riskScore 81}}
### ๐ Elevated Risk ({{detection.riskScore}}/100)
This detection should be reviewed soon.
{{/ifLessThan}}
{{/ifGreaterThan}}
{{#ifLessThan detection.riskScore 61}}
### ๐ข Normal Risk ({{detection.riskScore}}/100)
This detection has a normal risk level.
{{/ifLessThan}}
**Results Found:** {{detection.resultCount}}
[Investigate Now]({{detection.resultLink}})The channel variable indicates the notification destination. Use it to format messages appropriately for each platform.
Title:
{{detection.displayName}}Body:
{{#ifEquals channel "slack"}}
*{{detection.displayName}}*
Severity: `{{detection.severity}}` | Risk: `{{detection.riskScore}}`
Results: {{detection.resultCount}}
<{{detection.resultLink}}|View in RunReveal>
{{/ifEquals}}
{{#ifEquals channel "email"}}
# {{detection.displayName}}
| Property | Value |
|----------|-------|
| Severity | {{detection.severity}} |
| Risk Score | {{detection.riskScore}} |
| Results | {{detection.resultCount}} |
[View Full Results]({{detection.resultLink}})
{{/ifEquals}}
{{#ifEquals channel "discord"}}
**{{detection.displayName}}**
> Severity: {{detection.severity}}
> Risk Score: {{detection.riskScore}}
> Results: {{detection.resultCount}}
{{detection.resultLink}}
{{/ifEquals}}
{{#ifEquals channel "webhook"}}
Detection: {{detection.displayName}}
Severity: {{detection.severity}}
Risk: {{detection.riskScore}}
Count: {{detection.resultCount}}
Link: {{detection.resultLink}}
{{/ifEquals}}Always check for errors using ifNotEmpty detection.error. This ensures users are notified when detections fail and provides clear troubleshooting guidance.
Title:
{{#ifNotEmpty detection.error}}โ Error: {{/ifNotEmpty}}{{detection.displayName}}Body:
## {{detection.displayName}}
{{#ifNotEmpty detection.error}}
### โ Detection Error
An error occurred while running this detection:
> {{detection.error}}
Please review the detection configuration and try again.
{{/ifNotEmpty}}
{{#ifEmpty detection.error}}
### โ
Detection Successful
**Severity:** {{detection.severity}}
**Risk Score:** {{detection.riskScore}}
**Results Found:** {{detection.resultCount}}
{{#ifNotEmpty detection.results}}
{{table detection.results}}
{{/ifNotEmpty}}
[View Results]({{detection.resultLink}})
{{/ifEmpty}}Testing Your Templates
Test Scenarios
Data Variations
- โข Empty results (resultCount = 0)
- โข Single result
- โข Multiple results (10+)
- โข Missing optional fields
Severity & Risk
- โข High risk scores (above 80)
- โข Low risk scores (below 20)
- โข Different severity levels
- โข Error conditions
Related Documentation
- Notification Channels - Configure and manage notification channels
- Detections - Create and manage detection rules
- Writing Detections - Learn how to write effective detections
- Detection as Code - Manage detections with version control