{
  "name": "Generate AI weekly business performance digest from Google Sheets to Slack and email",
  "tags": [],
  "nodes": [
    {
      "id": "b2000001-0000-0000-0000-000000000001",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -480,
        -340
      ],
      "parameters": {
        "color": 6,
        "width": 540,
        "height": 480,
        "content": "## AI Weekly Business Digest \u2192 Slack & Email\n\nAutomatically generate a weekly performance report from your Google Sheets data and deliver it to Slack and email.\n\n### How it works\n1. **Schedule:** Triggers every Monday at 8am.\n2. **Fetch:** Pulls the last 14 days of metrics from Google Sheets.\n3. **Calculate:** Computes this-week vs. last-week comparisons, conversion rate, and ROAS.\n4. **AI:** OpenAI generates a narrative digest with wins, concerns, and priorities.\n5. **Deliver:** Posts the formatted report to Slack and sends an HTML email simultaneously.\n\n### Setup steps\n1. **Config:** Open the \"Set report config variables\" node \u2014 enter your Sheet ID, sheet name, Slack channel, email recipients, and company name.\n2. **Data:** Prepare your Google Sheet with columns: Date, Revenue, Leads, Conversions, Ad Spend, Support Tickets.\n3. **Credentials:** Connect Google Sheets, OpenAI, Slack, and Gmail in each node.\n4. **Test:** Activate the workflow or trigger it manually to verify."
      },
      "typeVersion": 1
    },
    {
      "id": "b2000001-0000-0000-0000-000000000002",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        40,
        60
      ],
      "parameters": {
        "color": 7,
        "width": 460,
        "height": 200,
        "content": "## 1. Schedule & Config\nTriggers every Monday at 8am. The config node holds your Sheet ID, Slack channel, and email recipients."
      },
      "typeVersion": 1
    },
    {
      "id": "b2000001-0000-0000-0000-000000000003",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        540,
        60
      ],
      "parameters": {
        "color": 7,
        "width": 460,
        "height": 200,
        "content": "## 2. Data Retrieval & Processing\nPulls the last 14 days of metrics from Sheets, then calculates this-week vs. last-week comparisons."
      },
      "typeVersion": 1
    },
    {
      "id": "b2000001-0000-0000-0000-000000000004",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1100,
        60
      ],
      "parameters": {
        "color": 7,
        "width": 620,
        "height": 200,
        "content": "## 3. AI Analysis & Delivery\nOpenAI generates a narrative digest with trends, wins, concerns, and priorities. Delivered to Slack and email simultaneously."
      },
      "typeVersion": 1
    },
    {
      "id": "b2000001-1000-0000-0000-000000000001",
      "name": "Trigger every Monday at 8am",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        80,
        300
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks",
              "triggerAtDay": 1,
              "triggerAtHour": 8
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "b2000001-1000-0000-0000-000000000002",
      "name": "Set report config variables",
      "type": "n8n-nodes-base.set",
      "position": [
        300,
        300
      ],
      "parameters": {
        "mode": "manual",
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "cfg-1",
              "name": "googleSheetId",
              "type": "string",
              "value": "YOUR_GOOGLE_SHEET_ID_HERE"
            },
            {
              "id": "cfg-2",
              "name": "sheetName",
              "type": "string",
              "value": "Weekly Metrics"
            },
            {
              "id": "cfg-3",
              "name": "slackChannel",
              "type": "string",
              "value": "#business-updates"
            },
            {
              "id": "cfg-4",
              "name": "emailRecipients",
              "type": "string",
              "value": "user@example.com"
            },
            {
              "id": "cfg-5",
              "name": "companyName",
              "type": "string",
              "value": "Your Company"
            }
          ]
        },
        "duplicateItem": false,
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "b2000001-1000-0000-0000-000000000003",
      "name": "Fetch metrics from Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        540,
        300
      ],
      "parameters": {
        "options": {},
        "operation": "read",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $json.sheetName }}"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.googleSheetId }}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "b2000001-1000-0000-0000-000000000004",
      "name": "Calculate weekly comparisons",
      "type": "n8n-nodes-base.code",
      "position": [
        780,
        300
      ],
      "parameters": {
        "jsCode": "// Calculate this week vs last week metrics\nconst items = $input.all().map(i => i.json);\nconst config = $('Set report config variables').first().json;\nconst sorted = items.sort((a, b) => new Date(b.Date || b.date) - new Date(a.Date || a.date));\nconst thisWeek = sorted.slice(0, 7);\nconst lastWeek = sorted.slice(7, 14);\nfunction sumField(arr, field) { return arr.reduce((sum, row) => sum + (parseFloat(row[field]) || 0), 0); }\nfunction pctChange(current, previous) { if (previous === 0) return current > 0 ? 100 : 0; return Math.round(((current - previous) / previous) * 100); }\nconst metrics = { thisWeek: { revenue: sumField(thisWeek, 'Revenue'), leads: sumField(thisWeek, 'Leads'), conversions: sumField(thisWeek, 'Conversions'), adSpend: sumField(thisWeek, 'Ad Spend'), supportTickets: sumField(thisWeek, 'Support Tickets') }, lastWeek: { revenue: sumField(lastWeek, 'Revenue'), leads: sumField(lastWeek, 'Leads'), conversions: sumField(lastWeek, 'Conversions'), adSpend: sumField(lastWeek, 'Ad Spend'), supportTickets: sumField(lastWeek, 'Support Tickets') } };\nmetrics.changes = { revenue: pctChange(metrics.thisWeek.revenue, metrics.lastWeek.revenue), leads: pctChange(metrics.thisWeek.leads, metrics.lastWeek.leads), conversions: pctChange(metrics.thisWeek.conversions, metrics.lastWeek.conversions), adSpend: pctChange(metrics.thisWeek.adSpend, metrics.lastWeek.adSpend), supportTickets: pctChange(metrics.thisWeek.supportTickets, metrics.lastWeek.supportTickets) };\nmetrics.thisWeek.conversionRate = metrics.thisWeek.leads > 0 ? Math.round((metrics.thisWeek.conversions / metrics.thisWeek.leads) * 100) : 0;\nmetrics.thisWeek.roas = metrics.thisWeek.adSpend > 0 ? Math.round((metrics.thisWeek.revenue / metrics.thisWeek.adSpend) * 100) / 100 : 0;\nreturn [{ json: { metrics, rawDataPoints: sorted.length, companyName: config.companyName, slackChannel: config.slackChannel, emailRecipients: config.emailRecipients, reportDate: new Date().toISOString().split('T')[0] } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "b2000001-1000-0000-0000-000000000005",
      "name": "Generate AI performance digest",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        1020,
        300
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini"
        },
        "options": {
          "maxTokens": 1000,
          "temperature": 0.4
        },
        "messages": {
          "values": [
            {
              "content": "=You are a business analyst writing a weekly performance digest for {{ $json.companyName }}. Write a concise, actionable report based on these metrics:\n\nTHIS WEEK:\n- Revenue: ${{ $json.metrics.thisWeek.revenue }} ({{ $json.metrics.changes.revenue }}% vs last week)\n- Leads: {{ $json.metrics.thisWeek.leads }} ({{ $json.metrics.changes.leads }}% vs last week)\n- Conversions: {{ $json.metrics.thisWeek.conversions }} ({{ $json.metrics.changes.conversions }}% vs last week)\n- Ad Spend: ${{ $json.metrics.thisWeek.adSpend }} ({{ $json.metrics.changes.adSpend }}% vs last week)\n- Support Tickets: {{ $json.metrics.thisWeek.supportTickets }} ({{ $json.metrics.changes.supportTickets }}% vs last week)\n- Conversion Rate: {{ $json.metrics.thisWeek.conversionRate }}%\n- ROAS: {{ $json.metrics.thisWeek.roas }}x\n\nFormat your response with these sections:\n1. HEADLINE: One sentence performance summary with emoji\n2. WINS: 2-3 positive highlights\n3. WATCH: 1-2 areas of concern\n4. PRIORITIES: 3 recommended actions for this week\n5. OUTLOOK: Brief 1-sentence forecast\n\nKeep it under 300 words. Be specific with numbers."
            }
          ]
        },
        "resource": "chat"
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "b2000001-1000-0000-0000-000000000006",
      "name": "Format digest for Slack and email",
      "type": "n8n-nodes-base.code",
      "position": [
        1260,
        300
      ],
      "parameters": {
        "jsCode": "// Format the AI digest for Slack and email\nconst aiResponse = $input.first().json;\nconst prev = $('Calculate weekly comparisons').first().json;\nconst digest = aiResponse.message?.content || aiResponse.text || aiResponse.content || 'Report generation failed.';\nconst slackMessage = ':bar_chart: *Weekly Performance Digest \u2014 ' + prev.reportDate + '*\\n\\n' + digest;\nconst emailHtml = '<div style=\"font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;\"><h2>Weekly Performance Digest \u2014 ' + prev.reportDate + '</h2><div style=\"background: #f5f5f5; padding: 20px; border-radius: 8px; margin: 20px 0;\"><h3>Key Metrics</h3><p>Revenue: $' + prev.metrics.thisWeek.revenue + ' (' + (prev.metrics.changes.revenue > 0 ? '+' : '') + prev.metrics.changes.revenue + '%)<br>Leads: ' + prev.metrics.thisWeek.leads + '<br>Conversions: ' + prev.metrics.thisWeek.conversions + '<br>ROAS: ' + prev.metrics.thisWeek.roas + 'x</p></div><div style=\"white-space: pre-wrap;\">' + digest + '</div></div>';\nreturn [{ json: { slackMessage, emailHtml, emailSubject: 'Weekly Performance Digest \u2014 ' + prev.reportDate, slackChannel: prev.slackChannel, emailRecipients: prev.emailRecipients, reportDate: prev.reportDate } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "b2000001-1000-0000-0000-000000000007",
      "name": "Post digest to Slack channel",
      "type": "n8n-nodes-base.slack",
      "position": [
        1520,
        200
      ],
      "parameters": {
        "text": "={{ $json.slackMessage }}",
        "channel": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $json.slackChannel }}"
        },
        "resource": "message",
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "b2000001-1000-0000-0000-000000000008",
      "name": "Email digest to team",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1520,
        420
      ],
      "parameters": {
        "sendTo": "={{ $json.emailRecipients }}",
        "message": "={{ $json.emailHtml }}",
        "options": {},
        "subject": "={{ $json.emailSubject }}",
        "emailType": "html"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    }
  ],
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": null,
  "connections": {
    "Set report config variables": {
      "main": [
        [
          {
            "node": "Fetch metrics from Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trigger every Monday at 8am": {
      "main": [
        [
          {
            "node": "Set report config variables",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate weekly comparisons": {
      "main": [
        [
          {
            "node": "Generate AI performance digest",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate AI performance digest": {
      "main": [
        [
          {
            "node": "Format digest for Slack and email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch metrics from Google Sheets": {
      "main": [
        [
          {
            "node": "Calculate weekly comparisons",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format digest for Slack and email": {
      "main": [
        [
          {
            "node": "Post digest to Slack channel",
            "type": "main",
            "index": 0
          },
          {
            "node": "Email digest to team",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}