The Reporting Trap

Every agency knows this pain. Friday afternoon, someone is manually pulling numbers from five different places, pasting them into a spreadsheet, formatting a summary, and emailing it to a list of clients who may or may not read it. Three hours of work that produces a PDF nobody asked for.

We've seen this at every scale โ€” solo consultants, 10-person agencies, in-house marketing teams. The problem isn't the data. It's the assembly. And assembly is exactly what automation is built for.

The Three Tools

We didn't introduce any new software. The client already had all three tools โ€” they were just using them in isolation:

How the Workflow Runs

Every Monday at 8:00 AM, a cron trigger fires in n8n. It reads the previous week's data range from Google Sheets โ€” traffic, conversions, revenue, tasks completed, whatever the client tracks. A few JavaScript nodes clean and format the numbers. Then it builds two outputs: a Slack block message for the internal team, and an HTML email for the client.

Trigger: Cron โ€” every Monday 08:00
โ†’ Google Sheets: Read KPI range for last 7 days
โ†’ n8n (JS node): Format numbers, calculate deltas, flag anomalies
โ†’ Slack: Post formatted summary to #weekly-report channel
โ†’ Gmail: Send branded HTML report to client distribution list
โ†’ Google Sheets: Log delivery timestamp + status

The Formatting Layer

This is where most people give up. Raw Sheets data looks awful in an email. The n8n JavaScript node does the heavy lifting: it rounds numbers, adds % deltas vs the prior week, highlights anything that moved more than 15% in either direction, and injects everything into an HTML template string.

The Slack message uses Block Kit โ€” a structured JSON format that renders as a clean card with bold metrics and colour-coded arrows. The whole formatting step is under 40 lines of JavaScript. No external libraries, no separate templating engine.

Handling Edge Cases

What if the Sheets data is incomplete? What if a metric column is blank? We added a validation node that checks for empty cells before formatting. If anything looks wrong, it pings a Slack alert to the internal ops channel instead of sending a broken report to the client. The delivery is suppressed until someone manually approves it.

This single safeguard has prevented exactly three embarrassing client emails since we deployed it.

The Result

// outcome

What It Actually Cost to Build

Seven hours total. Three hours designing the Sheets schema and agreeing on which metrics mattered. Two hours building the n8n workflow. Two hours refining the email template and testing delivery. The tools are all free or already in the client's stack โ€” the only cost was the build time.

If you want this running before your next client call, get in touch. It's one of our most common fixed-price builds.