Your n8n Blueprint is Ready
Here are the exact nodes and scripts you need to build the "Perfect Audit" workflow.
You've been selected for a free trial of Outreach Magic.
Don't want to maintain your own n8n reporting server? Skip the DIY setup and use our fully managed "Plug & Play" reporting platform.
1. The Complete Workflow
This section includes everything you need: the n8n node structure and the Identity Resolution logic.
Part A: The Workflow JSON
Copy and paste this directly into your n8n canvas. It includes a Webhook, a Switch to handle different platforms (Smartlead, Instantly, HeyReach), and the Google Sheets connector.
{
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "reporting",
"options": {}
},
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [460, 300]
},
{
"parameters": {
"jsCode": "// Identity Logic Placeholder"
},
"name": "Identity & Dedupe Logic",
"type": "n8n-nodes-base.code",
"typeVersion": 1,
"position": [680, 300]
},
{
"parameters": {
"operation": "append",
"sheetId": {
"__rl": true,
"mode": "list",
"value": ""
},
"range": "Raw Events!A:Z",
"options": {
"useKeys": true
}
},
"name": "Google Sheets",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 3,
"position": [900, 300]
}
],
"connections": {
"Webhook": {
"main": [
[
{
"node": "Identity & Dedupe Logic",
"type": "main",
"index": 0
}
]
]
},
"Identity & Dedupe Logic": {
"main": [
[
{
"node": "Google Sheets",
"type": "main",
"index": 0
}
]
]
}
}
}- Connect your Google Account credential.
- Select the Sheet File (Make a copy of our template in Step 2).
- Critical: Set "Data Mode" to "Auto-Map Input Data to Columns".
Part B: The "Universal" Script
Double-click the "Identity & Dedupe Logic" node and paste this Javascript. It automatically detects if the data is from Smartlead, Instantly, or HeyReach and normalizes it.
Need another platform? Contact us and we will help you get it added.
Alternatively, Outreach Magic works with 12+ platforms out of the box.
// Run for each item
const item = $input.item.json;
// Handle n8n webhook nesting (sometimes data is in item.body)
// This fixes the issue where payload might be nested under 'body'
const json = item.body || item;
let platform = 'manual';
let email = '';
let linkedin = '';
let messageId = '';
let eventType = 'unknown';
let campaignId = '';
// --- DETECT PLATFORM & NORMALIZE ---
// 1. SMARTLEAD
if (json.sl_email_lead_id || (json.app_url && json.app_url.includes('smartlead'))) {
platform = 'smartlead';
email = (json.to_email || '').toLowerCase().trim();
eventType = (json.event_type || '').toLowerCase();
campaignId = json.campaign_id;
if (json.sent_message && json.sent_message.message_id) {
messageId = json.sent_message.message_id;
} else {
messageId = json.sl_email_lead_id + '_' + json.stats_id;
}
}
// 2. HEYREACH
else if (json.lead && json.sender && json.event_type) {
platform = 'heyreach';
email = (json.lead.email_address || '').toLowerCase().trim();
linkedin = (json.lead.profile_url || '').split('?')[0];
eventType = json.event_type.toLowerCase();
campaignId = json.campaign ? json.campaign.id : '';
messageId = json.correlation_id || (json.lead.id + '_' + json.timestamp);
}
// 3. INSTANTLY
else if (json.workspace && json.campaign_id) {
platform = 'instantly';
email = (json.lead_email || json.email || '').toLowerCase().trim();
eventType = (json.event_type || '').toLowerCase();
campaignId = json.campaign_id;
messageId = email + '_' + campaignId + '_' + json.timestamp;
}
// --- CLEANUP ---
if (linkedin.endsWith('/')) linkedin = linkedin.slice(0, -1);
// Generate Unified ID
const unifiedId = email || linkedin || 'unknown_' + Math.random().toString(36).substr(2, 9);
// Generate Dedupe Key
const dedupeKey = `${platform}_${messageId}_${eventType}`;
return {
json: {
dedupe_key: dedupeKey,
timestamp_iso: json.timestamp || json.event_timestamp || new Date().toISOString(),
event_type: eventType,
platform: platform,
unified_lead_id: unifiedId,
campaign_id: campaignId ? campaignId.toString() : ''
}
};2. Get the Dashboard Template
Google Sheets Dashboard
We've created a pre-formatted sheet with the correct columns and a "Raw Events" tab ready for your n8n data.
Advanced: Generate Custom Charts with AI
Want to build custom trends? Copy this prompt into ChatGPT or Claude to generate formulas for your new sheet.
I need to build a Cold Email Reporting Dashboard in Google Sheets to connect with my n8n workflow. Please give me the exact setup instructions and formulas.
1. **Tab "Raw Data"**:
- Headers in Row 1: [dedupe_key, timestamp_iso, event_type, platform, unified_lead_id, campaign_id]
- This is where n8n will append new rows.
2. **Tab "Analysis"**:
- Column A (Date): Write an ARRAYFORMULA to extract unique dates from 'Raw Data'!B:B (timestamp_iso), sorted descending.
- Column B (Sent Volume): Count rows where event_type="sent" for that date.
- Column C (Replies): Count rows where event_type="reply" for that date.
- Column D (Unique Leads Contacted): Count unique "unified_lead_id" where event_type="sent" for that date (Use COUNTUNIQUEIFS if available, or a QUERY).
- Column E (Reply Rate): Column C / Column B (Formatted as %).
Please provide the specific Google Sheets formulas (using ARRAYFORMULA or QUERY where possible) so I can paste them into Row 2 of the Analysis tab.3. Prepare Your Google Sheet
Create a new Google Sheet. Rename the first tab to Raw Events. Then, copy and paste these exact headers into Row 1 (Cells A1:F1).
Why these columns?
• dedupe_key: Prevents double-counting (e.g. smartlead_msg123_open).
• timestamp_iso: Allows for accurate timezone adjustments later.
• unified_lead_id: Merges email/LinkedIn identities into one person.
Stuck on your setup?
If you need help with a specific n8n node, database schema, or custom integration, you can schedule a 15-min call with our team at no cost.
Schedule a free help call