AutomationFlowsEmail & Gmail › Executive KPI Dashboard - Automated Weekly Report

Executive KPI Dashboard - Automated Weekly Report

Executive KPI Dashboard - Automated Weekly Report. Uses googleSheets, httpRequest, sendGrid, slack. Scheduled trigger; 21 nodes.

Cron / scheduled trigger★★★★☆ complexity21 nodesGoogle SheetsHTTP RequestSendGridSlack
Email & Gmail Trigger: Cron / scheduled Nodes: 21 Complexity: ★★★★☆ Added:

This workflow follows the Google Sheets → HTTP Request 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 →

Download .json
{
  "name": "Executive KPI Dashboard - Automated Weekly Report",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 8 * * 1"
            }
          ]
        }
      },
      "id": "schedule-trigger",
      "name": "Weekly Monday 8AM",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        250,
        500
      ]
    },
    {
      "parameters": {
        "jsCode": "// Initialize report context\nconst reportDate = new Date();\nconst weekStart = new Date(reportDate);\nweekStart.setDate(reportDate.getDate() - 7);\n\nreturn {\n  report_id: `RPT-${Date.now()}`,\n  report_date: reportDate.toISOString(),\n  period_start: weekStart.toISOString(),\n  period_end: reportDate.toISOString(),\n  report_type: 'Weekly Executive Summary',\n  generated_by: 'Automated n8n Workflow',\n  timestamp: Date.now()\n};"
      },
      "id": "init-report",
      "name": "Initialize Report",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        470,
        500
      ]
    },
    {
      "parameters": {
        "authentication": "serviceAccount",
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "options": {}
      },
      "id": "get-revenue-data",
      "name": "Get Revenue Data (Sheets)",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.4,
      "position": [
        690,
        200
      ]
    },
    {
      "parameters": {
        "url": "https://api.stripe.com/v1/charges",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "stripeApi",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "created[gte]",
              "value": "={{ Math.floor(new Date($('Initialize Report').item.json.period_start).getTime() / 1000) }}"
            },
            {
              "name": "limit",
              "value": "100"
            }
          ]
        },
        "options": {}
      },
      "id": "get-stripe-payments",
      "name": "Get Stripe Payments",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        690,
        300
      ]
    },
    {
      "parameters": {
        "url": "https://www.googleapis.com/analytics/v3/data/ga",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "ids",
              "value": "ga:YOUR_VIEW_ID"
            },
            {
              "name": "start-date",
              "value": "7daysAgo"
            },
            {
              "name": "end-date",
              "value": "today"
            },
            {
              "name": "metrics",
              "value": "ga:sessions,ga:users,ga:pageviews,ga:bounceRate"
            }
          ]
        },
        "options": {}
      },
      "id": "get-analytics",
      "name": "Get Google Analytics",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        690,
        400
      ]
    },
    {
      "parameters": {
        "url": "https://api.hubspot.com/crm/v3/objects/deals",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "limit",
              "value": "100"
            }
          ]
        },
        "options": {}
      },
      "id": "get-crm-deals",
      "name": "Get CRM Pipeline (HubSpot)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        690,
        500
      ]
    },
    {
      "parameters": {
        "url": "https://graph.facebook.com/v18.0/act_YOUR_AD_ACCOUNT/insights",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "time_range",
              "value": "{\"since\":\"{{ $('Initialize Report').item.json.period_start }}\",\"until\":\"{{ $('Initialize Report').item.json.period_end }}\"}"
            },
            {
              "name": "fields",
              "value": "spend,impressions,clicks,ctr,cpc,conversions"
            }
          ]
        },
        "options": {}
      },
      "id": "get-ad-performance",
      "name": "Get Ad Spend (Meta)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        690,
        600
      ]
    },
    {
      "parameters": {
        "url": "https://api.quickbooks.com/v3/company/YOUR_COMPANY_ID/query",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "query",
              "value": "SELECT * FROM Invoice WHERE TxnDate >= '{{ $('Initialize Report').item.json.period_start }}'"
            }
          ]
        },
        "options": {}
      },
      "id": "get-accounting",
      "name": "Get Financials (QuickBooks)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        690,
        700
      ]
    },
    {
      "parameters": {
        "url": "https://api.shopify.com/admin/api/2024-01/orders.json",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "status",
              "value": "any"
            },
            {
              "name": "created_at_min",
              "value": "={{ $('Initialize Report').item.json.period_start }}"
            },
            {
              "name": "limit",
              "value": "250"
            }
          ]
        },
        "options": {}
      },
      "id": "get-ecommerce",
      "name": "Get E-commerce Orders (Shopify)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        690,
        800
      ]
    },
    {
      "parameters": {
        "jsCode": "// Calculate revenue KPIs from all sources\nconst stripeData = $input.all().find(item => item.json.data && item.json.data.find);\nconst revenueData = $input.all().find(item => item.json.values);\nconst shopifyData = $input.all().find(item => item.json.orders);\n\nlet totalRevenue = 0;\nlet transactionCount = 0;\nlet avgOrderValue = 0;\n\n// Process Stripe payments\nif (stripeData?.json?.data) {\n  const charges = stripeData.json.data;\n  totalRevenue += charges.reduce((sum, charge) => sum + (charge.amount / 100), 0);\n  transactionCount += charges.length;\n}\n\n// Process Shopify orders\nif (shopifyData?.json?.orders) {\n  const orders = shopifyData.json.orders;\n  totalRevenue += orders.reduce((sum, order) => sum + parseFloat(order.total_price || 0), 0);\n  transactionCount += orders.length;\n}\n\navgOrderValue = transactionCount > 0 ? totalRevenue / transactionCount : 0;\n\n// Calculate growth vs previous period (simulated)\nconst prevPeriodRevenue = totalRevenue * 0.92; // Assume 8% growth\nconst revenueGrowth = ((totalRevenue - prevPeriodRevenue) / prevPeriodRevenue) * 100;\n\nreturn {\n  kpi_category: 'Revenue',\n  total_revenue: Math.round(totalRevenue * 100) / 100,\n  transaction_count: transactionCount,\n  avg_order_value: Math.round(avgOrderValue * 100) / 100,\n  revenue_growth_pct: Math.round(revenueGrowth * 100) / 100,\n  currency: 'USD',\n  period: $('Initialize Report').item.json.report_type\n};"
      },
      "id": "calc-revenue-kpis",
      "name": "Calculate Revenue KPIs",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        910,
        250
      ]
    },
    {
      "parameters": {
        "jsCode": "// Calculate marketing & traffic KPIs\nconst analyticsData = $input.all().find(item => item.json.rows || item.json.totalsForAllResults);\nconst adData = $input.all().find(item => item.json.data && item.json.data[0]?.spend);\n\nlet sessions = 0;\nlet users = 0;\nlet pageviews = 0;\nlet bounceRate = 0;\nlet adSpend = 0;\nlet adClicks = 0;\nlet adImpressions = 0;\n\n// Process Google Analytics\nif (analyticsData?.json?.totalsForAllResults) {\n  const totals = analyticsData.json.totalsForAllResults;\n  sessions = parseInt(totals['ga:sessions']) || 0;\n  users = parseInt(totals['ga:users']) || 0;\n  pageviews = parseInt(totals['ga:pageviews']) || 0;\n  bounceRate = parseFloat(totals['ga:bounceRate']) || 0;\n}\n\n// Process Ad data\nif (adData?.json?.data?.[0]) {\n  const ads = adData.json.data[0];\n  adSpend = parseFloat(ads.spend) || 0;\n  adClicks = parseInt(ads.clicks) || 0;\n  adImpressions = parseInt(ads.impressions) || 0;\n}\n\nconst ctr = adImpressions > 0 ? (adClicks / adImpressions) * 100 : 0;\nconst cpc = adClicks > 0 ? adSpend / adClicks : 0;\nconst costPerSession = sessions > 0 ? adSpend / sessions : 0;\n\nreturn {\n  kpi_category: 'Marketing',\n  sessions: sessions,\n  users: users,\n  pageviews: pageviews,\n  bounce_rate_pct: Math.round(bounceRate * 100) / 100,\n  ad_spend: Math.round(adSpend * 100) / 100,\n  ad_clicks: adClicks,\n  ad_impressions: adImpressions,\n  ctr_pct: Math.round(ctr * 100) / 100,\n  cpc: Math.round(cpc * 100) / 100,\n  cost_per_session: Math.round(costPerSession * 100) / 100\n};"
      },
      "id": "calc-marketing-kpis",
      "name": "Calculate Marketing KPIs",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        910,
        450
      ]
    },
    {
      "parameters": {
        "jsCode": "// Calculate sales pipeline KPIs\nconst crmData = $input.all().find(item => item.json.results || item.json.deals);\n\nlet pipelineValue = 0;\nlet dealCount = 0;\nlet wonDeals = 0;\nlet lostDeals = 0;\nlet avgDealSize = 0;\n\nif (crmData?.json?.results) {\n  const deals = crmData.json.results;\n  dealCount = deals.length;\n  \n  deals.forEach(deal => {\n    const value = parseFloat(deal.properties?.amount || 0);\n    pipelineValue += value;\n    \n    if (deal.properties?.dealstage === 'closedwon') wonDeals++;\n    if (deal.properties?.dealstage === 'closedlost') lostDeals++;\n  });\n  \n  avgDealSize = dealCount > 0 ? pipelineValue / dealCount : 0;\n}\n\nconst winRate = (wonDeals + lostDeals) > 0 ? (wonDeals / (wonDeals + lostDeals)) * 100 : 0;\n\nreturn {\n  kpi_category: 'Sales',\n  pipeline_value: Math.round(pipelineValue * 100) / 100,\n  deal_count: dealCount,\n  won_deals: wonDeals,\n  lost_deals: lostDeals,\n  avg_deal_size: Math.round(avgDealSize * 100) / 100,\n  win_rate_pct: Math.round(winRate * 100) / 100,\n  active_opportunities: dealCount - wonDeals - lostDeals\n};"
      },
      "id": "calc-sales-kpis",
      "name": "Calculate Sales Pipeline KPIs",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        910,
        650
      ]
    },
    {
      "parameters": {
        "mode": "combine",
        "combinationMode": "mergeByPosition",
        "options": {}
      },
      "id": "merge-all-kpis",
      "name": "Merge All KPIs",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3,
      "position": [
        1130,
        450
      ]
    },
    {
      "parameters": {
        "jsCode": "// Format KPIs for AI analysis\nconst allData = $input.all();\n\nconst revenue = allData.find(item => item.json.kpi_category === 'Revenue')?.json || {};\nconst marketing = allData.find(item => item.json.kpi_category === 'Marketing')?.json || {};\nconst sales = allData.find(item => item.json.kpi_category === 'Sales')?.json || {};\n\nconst kpiSummary = `\n### Revenue Metrics\n- Total Revenue: $${revenue.total_revenue?.toLocaleString() || 0}\n- Growth vs Last Period: ${revenue.revenue_growth_pct >= 0 ? '+' : ''}${revenue.revenue_growth_pct}%\n- Transactions: ${revenue.transaction_count || 0}\n- Average Order Value: $${revenue.avg_order_value || 0}\n\n### Marketing Performance\n- Website Sessions: ${marketing.sessions?.toLocaleString() || 0}\n- Unique Users: ${marketing.users?.toLocaleString() || 0}\n- Bounce Rate: ${marketing.bounce_rate_pct}%\n- Ad Spend: $${marketing.ad_spend?.toLocaleString() || 0}\n- Cost Per Click: $${marketing.cpc}\n- Click-Through Rate: ${marketing.ctr_pct}%\n- Cost Per Session: $${marketing.cost_per_session}\n\n### Sales Pipeline\n- Pipeline Value: $${sales.pipeline_value?.toLocaleString() || 0}\n- Active Opportunities: ${sales.active_opportunities || 0}\n- Average Deal Size: $${sales.avg_deal_size?.toLocaleString() || 0}\n- Win Rate: ${sales.win_rate_pct}%\n- Deals Won This Period: ${sales.won_deals || 0}\n- Deals Lost This Period: ${sales.lost_deals || 0}\n`;\n\nreturn {\n  kpi_summary: kpiSummary,\n  revenue_data: revenue,\n  marketing_data: marketing,\n  sales_data: sales,\n  report_period: $('Initialize Report').item.json.report_type\n};"
      },
      "id": "format-for-ai",
      "name": "Format KPIs for AI",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1350,
        450
      ]
    },
    {
      "parameters": {
        "url": "https://api.anthropic.com/v1/messages",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "anthropic-version",
              "value": "2023-06-01"
            },
            {
              "name": "content-type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "contentType": "json",
        "body": "={\n  \"model\": \"claude-3-5-sonnet-20241022\",\n  \"max_tokens\": 2048,\n  \"messages\": [\n    {\n      \"role\": \"user\",\n      \"content\": \"You are a business analyst creating an executive summary. Analyze these weekly KPIs and provide:\\n\\n1. Key Highlights (3-4 bullet points of what's working well)\\n2. Areas of Concern (2-3 items that need attention)\\n3. Strategic Recommendations (3-4 actionable next steps)\\n4. Week-over-Week Trends (what changed and why it matters)\\n\\nBe concise, data-driven, and focus on insights that drive decisions. Use a professional but conversational tone.\\n\\n{{ $json.kpi_summary }}\"\n    }\n  ]\n}",
        "options": {}
      },
      "id": "ai-analysis",
      "name": "AI Analysis (Claude)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1570,
        450
      ]
    },
    {
      "parameters": {
        "jsCode": "// Parse AI response and create formatted report\nconst aiResponse = $input.item.json;\nconst kpiData = $('Format KPIs for AI').item.json;\nconst reportMeta = $('Initialize Report').item.json;\n\nconst aiInsights = aiResponse.content?.[0]?.text || 'AI analysis unavailable';\n\nconst htmlReport = `\n<!DOCTYPE html>\n<html>\n<head>\n  <style>\n    body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }\n    h1 { color: #2c3e50; border-bottom: 3px solid #3498db; padding-bottom: 10px; }\n    h2 { color: #34495e; margin-top: 30px; }\n    .kpi-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 15px; margin: 20px 0; }\n    .kpi-card { background: #f8f9fa; padding: 15px; border-radius: 8px; border-left: 4px solid #3498db; }\n    .kpi-value { font-size: 24px; font-weight: bold; color: #2c3e50; }\n    .kpi-label { font-size: 12px; color: #7f8c8d; text-transform: uppercase; }\n    .ai-section { background: #e8f4f8; padding: 20px; border-radius: 8px; margin: 20px 0; }\n    .positive { color: #27ae60; }\n    .negative { color: #e74c3c; }\n    .footer { margin-top: 40px; padding-top: 20px; border-top: 1px solid #ddd; color: #7f8c8d; font-size: 12px; }\n  </style>\n</head>\n<body>\n  <h1>\ud83d\udcca Executive Weekly Report</h1>\n  <p><strong>Period:</strong> ${new Date(reportMeta.period_start).toLocaleDateString()} - ${new Date(reportMeta.period_end).toLocaleDateString()}</p>\n  <p><strong>Generated:</strong> ${new Date(reportMeta.report_date).toLocaleString()}</p>\n  \n  <h2>\ud83d\udcb0 Revenue Overview</h2>\n  <div class=\"kpi-grid\">\n    <div class=\"kpi-card\">\n      <div class=\"kpi-label\">Total Revenue</div>\n      <div class=\"kpi-value\">$${kpiData.revenue_data.total_revenue?.toLocaleString() || 0}</div>\n    </div>\n    <div class=\"kpi-card\">\n      <div class=\"kpi-label\">Growth</div>\n      <div class=\"kpi-value ${kpiData.revenue_data.revenue_growth_pct >= 0 ? 'positive' : 'negative'}\">\n        ${kpiData.revenue_data.revenue_growth_pct >= 0 ? '+' : ''}${kpiData.revenue_data.revenue_growth_pct}%\n      </div>\n    </div>\n    <div class=\"kpi-card\">\n      <div class=\"kpi-label\">Avg Order Value</div>\n      <div class=\"kpi-value\">$${kpiData.revenue_data.avg_order_value || 0}</div>\n    </div>\n  </div>\n  \n  <h2>\ud83d\udcc8 Marketing Performance</h2>\n  <div class=\"kpi-grid\">\n    <div class=\"kpi-card\">\n      <div class=\"kpi-label\">Sessions</div>\n      <div class=\"kpi-value\">${kpiData.marketing_data.sessions?.toLocaleString() || 0}</div>\n    </div>\n    <div class=\"kpi-card\">\n      <div class=\"kpi-label\">Ad Spend</div>\n      <div class=\"kpi-value\">$${kpiData.marketing_data.ad_spend?.toLocaleString() || 0}</div>\n    </div>\n    <div class=\"kpi-card\">\n      <div class=\"kpi-label\">Cost Per Session</div>\n      <div class=\"kpi-value\">$${kpiData.marketing_data.cost_per_session || 0}</div>\n    </div>\n  </div>\n  \n  <h2>\ud83e\udd1d Sales Pipeline</h2>\n  <div class=\"kpi-grid\">\n    <div class=\"kpi-card\">\n      <div class=\"kpi-label\">Pipeline Value</div>\n      <div class=\"kpi-value\">$${kpiData.sales_data.pipeline_value?.toLocaleString() || 0}</div>\n    </div>\n    <div class=\"kpi-card\">\n      <div class=\"kpi-label\">Win Rate</div>\n      <div class=\"kpi-value\">${kpiData.sales_data.win_rate_pct}%</div>\n    </div>\n    <div class=\"kpi-card\">\n      <div class=\"kpi-label\">Active Opps</div>\n      <div class=\"kpi-value\">${kpiData.sales_data.active_opportunities || 0}</div>\n    </div>\n  </div>\n  \n  <div class=\"ai-section\">\n    <h2>\ud83e\udd16 AI-Generated Insights</h2>\n    <div style=\"white-space: pre-wrap;\">${aiInsights}</div>\n  </div>\n  \n  <div class=\"footer\">\n    <p>Report ID: ${reportMeta.report_id} | Generated by: ${reportMeta.generated_by}</p>\n    <p>This report was automatically generated and analyzed by AI. For questions, contact your operations team.</p>\n  </div>\n</body>\n</html>\n`;\n\nreturn {\n  report_html: htmlReport,\n  report_subject: `\ud83d\udcca Weekly Executive Report - ${new Date(reportMeta.period_end).toLocaleDateString()}`,\n  report_summary: aiInsights,\n  report_id: reportMeta.report_id\n};"
      },
      "id": "generate-report",
      "name": "Generate HTML Report",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1790,
        450
      ]
    },
    {
      "parameters": {
        "fromEmail": "reports@company.com",
        "toEmail": "leadership@company.com",
        "subject": "={{ $json.report_subject }}",
        "emailFormat": "html",
        "html": "={{ $json.report_html }}",
        "options": {
          "senderName": "Automated Reports"
        }
      },
      "id": "send-email",
      "name": "Send Email Report",
      "type": "n8n-nodes-base.sendGrid",
      "typeVersion": 1,
      "position": [
        2010,
        350
      ]
    },
    {
      "parameters": {
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "text": "=\ud83d\udcca **Weekly Executive Report**\n\n*Period:* {{ new Date($('Initialize Report').item.json.period_end).toLocaleDateString() }}\n\n{{ $('Generate HTML Report').item.json.report_summary.substring(0, 2000) }}\n\n_Full detailed report sent via email._",
        "otherOptions": {}
      },
      "id": "send-slack",
      "name": "Post to Slack",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.2,
      "position": [
        2010,
        550
      ]
    },
    {
      "parameters": {
        "operation": "appendOrUpdate",
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Report Date": "={{ $('Initialize Report').item.json.report_date }}",
            "Total Revenue": "={{ $('Format KPIs for AI').item.json.revenue_data.total_revenue }}",
            "Revenue Growth %": "={{ $('Format KPIs for AI').item.json.revenue_data.revenue_growth_pct }}",
            "Sessions": "={{ $('Format KPIs for AI').item.json.marketing_data.sessions }}",
            "Ad Spend": "={{ $('Format KPIs for AI').item.json.marketing_data.ad_spend }}",
            "Pipeline Value": "={{ $('Format KPIs for AI').item.json.sales_data.pipeline_value }}",
            "Win Rate %": "={{ $('Format KPIs for AI').item.json.sales_data.win_rate_pct }}"
          }
        },
        "options": {}
      },
      "id": "log-to-sheets",
      "name": "Log to Historical Tracking Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.4,
      "position": [
        2010,
        750
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "anomaly-check",
              "leftValue": "={{ $('Format KPIs for AI').item.json.revenue_data.revenue_growth_pct }}",
              "rightValue": -10,
              "operator": {
                "type": "number",
                "operation": "lt"
              }
            }
          ],
          "combinator": "or"
        },
        "options": {}
      },
      "id": "check-anomalies",
      "name": "Check for Anomalies",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1570,
        650
      ]
    },
    {
      "parameters": {
        "fromEmail": "alerts@company.com",
        "toEmail": "leadership@company.com",
        "subject": "\u26a0\ufe0f ALERT: Significant Revenue Drop Detected",
        "text": "=\ud83d\udea8 **Anomaly Detected in Weekly Report**\n\nRevenue Growth: {{ $('Format KPIs for AI').item.json.revenue_data.revenue_growth_pct }}%\n\nThis represents a significant deviation from normal patterns. Immediate review recommended.\n\nFull report: {{ $('Generate HTML Report').item.json.report_id }}",
        "options": {
          "senderName": "Automated Alerts"
        }
      },
      "id": "send-alert",
      "name": "Send Alert Email",
      "type": "n8n-nodes-base.sendGrid",
      "typeVersion": 1,
      "position": [
        1790,
        750
      ]
    }
  ],
  "connections": {
    "Weekly Monday 8AM": {
      "main": [
        [
          {
            "node": "Initialize Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Initialize Report": {
      "main": [
        [
          {
            "node": "Get Revenue Data (Sheets)",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get Stripe Payments",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get Google Analytics",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get CRM Pipeline (HubSpot)",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get Ad Spend (Meta)",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get Financials (QuickBooks)",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get E-commerce Orders (Shopify)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Revenue Data (Sheets)": {
      "main": [
        [
          {
            "node": "Calculate Revenue KPIs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Stripe Payments": {
      "main": [
        [
          {
            "node": "Calculate Revenue KPIs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get E-commerce Orders (Shopify)": {
      "main": [
        [
          {
            "node": "Calculate Revenue KPIs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Google Analytics": {
      "main": [
        [
          {
            "node": "Calculate Marketing KPIs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Ad Spend (Meta)": {
      "main": [
        [
          {
            "node": "Calculate Marketing KPIs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get CRM Pipeline (HubSpot)": {
      "main": [
        [
          {
            "node": "Calculate Sales Pipeline KPIs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate Revenue KPIs": {
      "main": [
        [
          {
            "node": "Merge All KPIs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate Marketing KPIs": {
      "main": [
        [
          {
            "node": "Merge All KPIs",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Calculate Sales Pipeline KPIs": {
      "main": [
        [
          {
            "node": "Merge All KPIs",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Merge All KPIs": {
      "main": [
        [
          {
            "node": "Format KPIs for AI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format KPIs for AI": {
      "main": [
        [
          {
            "node": "AI Analysis (Claude)",
            "type": "main",
            "index": 0
          },
          {
            "node": "Check for Anomalies",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Analysis (Claude)": {
      "main": [
        [
          {
            "node": "Generate HTML Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate HTML Report": {
      "main": [
        [
          {
            "node": "Send Email Report",
            "type": "main",
            "index": 0
          },
          {
            "node": "Post to Slack",
            "type": "main",
            "index": 0
          },
          {
            "node": "Log to Historical Tracking Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check for Anomalies": {
      "main": [
        [
          {
            "node": "Send Alert Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": null,
  "tags": [],
  "triggerCount": 1,
  "versionId": null
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Executive KPI Dashboard - Automated Weekly Report. Uses googleSheets, httpRequest, sendGrid, slack. Scheduled trigger; 21 nodes.

Source: https://gist.github.com/gridrelay-max/6a0a23406c33633ed880b0a297905424 — original creator credit. Request a take-down →

More Email & Gmail workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Email & Gmail

E-commerce store owners, product managers, marketplace sellers, and pricing analysts who want to automatically track competitor pricing and get actionable alerts when their products are overpriced or

Google Sheets, HTTP Request, Slack +1
Email & Gmail

AI Document Processor - Intelligent Data Extraction. Uses httpRequest, readPDF, googleSheets, slack. Webhook trigger; 20 nodes.

HTTP Request, Read Pdf, Google Sheets +3
Email & Gmail

This template is ideal for developers, agencies, hosting providers, and website owners who need real-time alerts when a website goes down. It helps teams react quickly to downtime by sending multi-cha

Slack, HTTP Request, Gmail +1
Email & Gmail

This workflow runs daily to check SSL certificate expiry for domains listed in Google Sheets, using ssl-checker.io to fetch certificate details, then creating Jira issues and sending Slack and Gmail a

Google Sheets, HTTP Request, Jira +2
Email & Gmail

Schedule Slack. Uses scheduleTrigger, googleSheets, slack, gmail. Scheduled trigger; 15 nodes.

Google Sheets, Slack, Gmail +1