Example 8: Salesforce -> email digest with Router
Why this example
Each Monday morning, the customer-success leadership wants a single email listing all open Salesforce Cases grouped by priority. The trick: each priority bucket gets its own table inside one email, and the recipient list differs by region. Router splits the rows by priority, Reshape stitches them into HTML blocks, and Notification sends one email per region.
Helix Beverages context: the customer-success leadership at Helix runs a Monday-morning case digest sliced by region and priority. This recipe is what they replaced their hand-curated email with (see the Helix overview for the CS team backdrop).
At a glance
- Connectors used: Salesforce, SMTP
- Nodes used: Start, Source, Filter, Router, Reshape, Notification
- Schedule: weekly, Monday 07:00 local time per region
- Direction: One-way (Salesforce -> SMTP)
Canvas
The Router emits each row to ONE of its five outputs depending on the priority value; rows that don't match any explicit branch fall through to default. Each priority branch reshapes the row into an HTML table-row fragment, and a final Reshape gathers all fragments into one email body keyed by recipient region.
Step-by-step
| # | Node | Action | Key configuration | Output shape |
|---|---|---|---|---|
| 1 | Start | -- | -- | -- |
| 2 | Source | Salesforce: query Case | SELECT Id, Subject, Priority, Status, CaseNumber, Account.Name, OwnerName, CreatedDate, Region__c FROM Case WHERE Status = 'Open'. | Case row |
| 3 | Filter | -- | Predicate: row.Status === 'Open' (belt-and-braces; the SOQL already filters). | Same shape |
| 4 | Router | -- | Five outputs: r1 when row.Priority === 'P0', r2 for P1, r3 for P2, r4 for P3, default for anything else. | Same row, routed |
| 5 | Reshape (x4) | -- | Each branch emits { priority, htmlRow } where htmlRow is a small <tr><td>…</td>…</tr> string built from the case fields. | { priority, htmlRow, Region__c } |
| 6 | Reshape (gather) | -- | Aggregate by Region__c. For each region build { region, recipients, subject, body } where body interleaves a <table> block per priority. | One row per region |
| 7 | Notification | SMTP | Recipients: row.recipients (resolved from a per-region Variable). Subject: row.subject. HTML body: row.body. Use a saved Message Template for the wrapper. | -- |
Variations
- Daily instead of weekly -- bump the schedule. The query and the routing stay identical.
- Different breakdown axis -- swap the Router predicate from
PrioritytoStatusto get an "open vs in-progress" cut. - Replace SMTP with Slack -- the Generic API connector calls Slack's
chat.postMessageendpoint with a Block Kit payload. Build the blocks in the second Reshape instead of HTML. - Include trend graph -- precompute a 4-week priority count with a Cache node and embed it as a base64 PNG in the email.