This workflow follows the Gmail → Google Sheets recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "AI LeadOps Daily Summary",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "days",
"triggerAtHour": 9
}
]
}
},
"id": "schedule-trigger",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [
0,
0
]
},
{
"parameters": {
"operation": "read",
"documentId": {
"__rl": true,
"value": "={{ $env.GOOGLE_SHEETS_DOCUMENT_ID }}",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "Leads",
"mode": "name"
},
"options": {}
},
"id": "read-leads",
"name": "Read Leads",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [
220,
0
],
"alwaysOutputData": true
},
{
"parameters": {
"operation": "read",
"documentId": {
"__rl": true,
"value": "={{ $env.GOOGLE_SHEETS_DOCUMENT_ID }}",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "ErrorLogs",
"mode": "name"
},
"options": {}
},
"id": "read-errorlogs",
"name": "Read ErrorLogs",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [
440,
0
],
"alwaysOutputData": true
},
{
"parameters": {
"jsCode": "const leads = $('Read Leads').all().map((item) => item.json).filter((row) => Object.keys(row).length > 0);\nconst errors = $('Read ErrorLogs').all().map((item) => item.json).filter((row) => Object.keys(row).length > 0);\nconst now = new Date();\nconst reportDate = now.toISOString().slice(0, 10);\nconst dayStart = new Date(reportDate + 'T00:00:00.000Z');\nfunction parseDate(value) {\n const date = new Date(value);\n return Number.isNaN(date.getTime()) ? null : date;\n}\nfunction isToday(value) {\n const date = parseDate(value);\n return Boolean(date && date >= dayStart && date <= now);\n}\nconst todayLeads = leads.filter((lead) => isToday(lead.received_at));\nconst todayErrors = errors.filter((error) => isToday(error.timestamp));\nconst priority_breakdown = { High: 0, Medium: 0, Low: 0 };\nconst source_counts = {};\nlet pending_followups = 0;\nfor (const lead of todayLeads) {\n if (priority_breakdown[lead.priority] !== undefined) {\n priority_breakdown[lead.priority] += 1;\n }\n const source = lead.source || 'unknown';\n source_counts[source] = (source_counts[source] ?? 0) + 1;\n if (['Draft Created', 'Needs Review'].includes(lead.follow_up_status)) {\n pending_followups += 1;\n }\n}\nconst top_sources = Object.entries(source_counts)\n .sort(([, left], [, right]) => right - left)\n .slice(0, 5)\n .map(([source, count]) => ({ source, count }));\nconst error_breakdown = todayErrors.reduce((acc, error) => {\n const code = error.error_code || 'UNKNOWN_ERROR';\n acc[code] = (acc[code] ?? 0) + 1;\n return acc;\n}, {});\nconst summary = {\n date: reportDate,\n generated_at: now.toISOString(),\n total_leads: todayLeads.length,\n priority_breakdown,\n error_count: todayErrors.length,\n error_breakdown,\n pending_followups,\n top_sources,\n high_priority_leads: todayLeads.filter((lead) => lead.priority === 'High').map((lead) => ({\n lead_id: lead.lead_id,\n name: lead.name,\n company: lead.company,\n source: lead.source,\n lead_score: Number(lead.lead_score ?? 0),\n recommended_next_step: lead.recommended_next_step\n }))\n};\nreturn [{ json: { summary } }];"
},
"id": "calculate-metrics",
"name": "Calculate Metrics",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
660,
0
]
},
{
"parameters": {
"jsCode": "const summary = $input.first().json.summary;\nconst recipient = $env.DAILY_SUMMARY_RECIPIENT;\nif (!recipient) {\n throw new Error('UNKNOWN_ERROR: DAILY_SUMMARY_RECIPIENT is required.');\n}\nfunction linesFromBreakdown(breakdown) {\n const entries = Object.entries(breakdown);\n return entries.length > 0 ? entries.map(([key, value]) => `- ${key}: ${value}`).join('\\n') : '- none';\n}\nconst topSources = summary.top_sources.length > 0 ? summary.top_sources.map((item) => `- ${item.source}: ${item.count}`).join('\\n') : '- none';\nconst highPriority = summary.high_priority_leads.length > 0 ? summary.high_priority_leads.map((lead) => `- ${lead.lead_id}: ${lead.name ?? lead.company ?? 'unknown'} (${lead.lead_score}) - ${lead.recommended_next_step}`).join('\\n') : '- none';\nconst text = `Daily LeadOps Summary - ${summary.date}\\n\\nTotals\\n- leads: ${summary.total_leads}\\n- errors: ${summary.error_count}\\n- pending follow-ups: ${summary.pending_followups}\\n\\nPriority breakdown\\n${linesFromBreakdown(summary.priority_breakdown)}\\n\\nError breakdown\\n${linesFromBreakdown(summary.error_breakdown)}\\n\\nTop sources\\n${topSources}\\n\\nHigh-priority leads\\n${highPriority}\\n\\nGenerated at: ${summary.generated_at}`;\nreturn [{\n json: {\n summary,\n email: {\n to: recipient,\n subject: `Daily LeadOps Summary - ${summary.date}`,\n body: text\n }\n }\n}];"
},
"id": "build-summary-email",
"name": "Build Summary Email",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
880,
0
]
},
{
"parameters": {
"resource": "message",
"operation": "send",
"sendTo": "={{ $json.email.to }}",
"subject": "={{ $json.email.subject }}",
"message": "={{ $json.email.body }}",
"options": {}
},
"id": "send-summary-email",
"name": "Send Summary Email",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2.1,
"position": [
1100,
0
]
}
],
"connections": {
"Schedule Trigger": {
"main": [
[
{
"node": "Read Leads",
"type": "main",
"index": 0
}
]
]
},
"Read Leads": {
"main": [
[
{
"node": "Read ErrorLogs",
"type": "main",
"index": 0
}
]
]
},
"Read ErrorLogs": {
"main": [
[
{
"node": "Calculate Metrics",
"type": "main",
"index": 0
}
]
]
},
"Calculate Metrics": {
"main": [
[
{
"node": "Build Summary Email",
"type": "main",
"index": 0
}
]
]
},
"Build Summary Email": {
"main": [
[
{
"node": "Send Summary Email",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"tags": [],
"triggerCount": 1,
"updatedAt": "2026-06-30T00:00:00.000Z",
"versionId": "leadops-daily-summary-v1"
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
AI LeadOps Daily Summary. Uses googleSheets, gmail. Scheduled trigger; 6 nodes.
Source: https://github.com/ia319/ai-leadops-automation/blob/main/workflows/n8n/leadops-daily-summary.workflow.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow runs on scheduled weekly and monthly triggers to generate unified marketing performance reports. It processes multiple websites by collecting analytics data, paid ads performance, and CR
Watch target companies for C-level and VP hiring signals, then send AI-personalized outreach emails when leadership roles are posted.
Boost your meeting conversion rates with this Automated Meeting Booking Sequence! This workflow automatically follows up with unbooked leads after 24 hours, sends personalized emails with calendar lin
Monitor customers for competitor tech adoption via PredictLeads and alert CSMs to prevent churn.
Three scheduled triggers fire on weekdays at region-appropriate working hours: EU/UK at 10:00 UTC, North America at 18:00 UTC, and Australia at 01:00 UTC All three feed one shared pipeline, so there i