ChatGPTWorkBack officeAI score · PendingAI-assisted edit · no obvious prompt-injection riskn8n.io

Daily Automated Executive Financial Briefing: Google Sheets + GPT-4o-mini + Notion + Telegram

Weekday 7 AM trigger → parallel fetch from 5 Google Sheets tabs → KPI calculation → GPT-4o-mini generates Telegram-formatted briefing → Notion archive + Telegram delivery → critical alert if revenue drops >10% → Slack error notification

Some experienceStepsWorkflowPrompt
Who
Operations or finance staff who need to push daily executive briefings, or small teams automating a CFO dashboard
You get
Receive an AI-generated Telegram financial briefing every weekday morning, with extra alerts on key metric anomalies and execution logs saved to Notion
You need
n8n · google-sheets · notion · telegram · slack

Constraints

Prerequisites: n8n instance (self-hosted or cloud); Google Sheets OAuth2 credential and 5 tabs (CashFlow, Revenue, Payroll, Subscriptions, Expenses); OpenAI API key; Notion integration and CFO Report database; Telegram Bot and target Chat ID; Slack OAuth2 and alert channel. Costs: OpenAI GPT-4o-mini billed by token; other services per their platforms. Not tested by this site; first run should be triggered manually for verification.

What they did

Author rahul08 published a 25-node workflow template on n8n.io. It triggers automatically at 7 AM on weekdays, fetches the latest rows from five Google Sheets tabs (CashFlow, Revenue, Payroll, Subscriptions, Expenses) in parallel, merges them, and runs a Code node to calculate KPIs (revenue, payroll, marketing ROI, cash runway) and status labels (GOOD/WARNING/ALERT). An AI Agent node then calls GPT-4o-mini using a structured systemMessage and user prompt to generate a Telegram-formatted executive briefing. A second Code node merges the AI output back with the financial data, which is then sent simultaneously to a Telegram channel and saved to a Notion database. If revenue has dropped more than 10% month-over-month, an If node triggers an additional critical Telegram alert. A separate Error Trigger → Slack branch captures and alerts on any execution failure.

How it went

Source report (author_report): the template is marked published on n8n.io with 98 total views. No specific success rate, latency, or ROI data is provided. This site has not tested the workflow; actual results depend on credential setup, sheet data quality, and OpenAI API availability.

Worth knowing

1) The marketing ROI baseline is hardcoded to 85 in the KPI code; change it if your baseline differs. 2) The Slack error alert node text is only a placeholder '=Error occured '; production use should include workflow name, node name, and error timestamp. 3) All credentials (Google Sheets, Notion, OpenAI, Telegram, Slack) must be configured via n8n's credential manager — never paste keys directly into node fields. 4) Run a manual test before relying on the schedule; verify field mappings match your actual sheet column names. 5) The source does not provide long-term operational records for this template; observe stability yourself.

n8n workflow template

Structure checked · Not run-tested

Use “Import from File” in n8n, or copy the JSON and paste it into the editor. Connect your own accounts, then try test data. The template is inactive by default.

Setup and test checklist

Credentials to connect

  • Send Daily Briefing to Telegram node: connect Telegram API credentials.
  • Slack: Error Alert node: connect Slack OAuth2 credentials.

Configuration to replace

  • Source template is n8n public workflow #16459 (~25 nodes). Keep inactive after import; verify triggers, expressions and external API endpoints.
  • Sticky-note guidance is informational; replace placeholders with your own accounts, sheet schemas or channel IDs.

Test input and expected output

  • Manually run the main path once in a test workspace and confirm credentialed nodes authenticate without errors.
  • Drive one synthetic/redacted sample through and check output fields and downstream writes before enabling in production.

Template changes

  • Author credential bindings, webhookId and execution data are removed; the workflow is inactive. Nodes, connections and original prompts are preserved. Not run-tested in n8n.
  • No business-logic edits; verify keys, quotas and privacy compliance before use.

Template retrieved: 2026-10-25

Steps

  1. Configure the schedule trigger

    Add a Schedule Trigger node in n8n and set the cron expression to 0 7 * * 1-5 (Mon–Fri at 7:00). Click 'Test Workflow' to confirm the trigger starts correctly.

  2. Configure 5 parallel Google Sheets fetches

    Add one Google Sheets node (typeVersion 4) for each tab: CashFlow, Revenue, Payroll, Subscriptions, Expenses. In each node: select or create a googleSheetsOAuth2Api credential; replace the documentId placeholder YOUR_GOOGLE_SHEET_ID with your actual spreadsheet ID; confirm the sheetName matches your tab. Connect all 5 nodes to the same output of the Weekday 7 AM Trigger for parallel execution.

  3. Merge all sheet data

    Add a Merge node (typeVersion 3.2) and set numberInputs to 5. Connect the 5 Google Sheets outputs to inputs 0–4 of the Merge node. Verify the merged output contains rows from all tabs.

  4. Calculate KPIs and status labels

    Add a Code node (typeVersion 2, JavaScript) and paste the code below. It filters items by sheet name or field presence, computes current/previous revenue, payroll, marketing ROI, cash balance, monthly burn rate, runway months, subscription MRR, total expenses, and outputs GOOD/WARNING/ALERT status labels.

    Execution prompt · Source text。JS Code field of the 'Calculate KPIs & Status Labels' node

    const allItems = $input.all();
    
    const cashflowData = allItems.filter(i => i.json.sheet === 'CashFlow' || i.json.cash_in !== undefined);
    const revenueData = allItems.filter(i => i.json.sheet === 'Revenue' || i.json.revenue_current !== undefined);
    const payrollData = allItems.filter(i => i.json.sheet === 'Payroll' || i.json.payroll_current !== undefined);
    const subscriptionData = allItems.filter(i => i.json.sheet === 'Subscriptions' || i.json.subscription_revenue !== undefined);
    const expensesData = allItems.filter(i => i.json.sheet === 'Expenses' || i.json.expense_amount !== undefined);
    
    const totalRevenueCurrent = revenueData.reduce((sum, i) => sum + (parseFloat(i.json.revenue_current) || 0), 0);
    const totalRevenuePrevious = revenueData.reduce((sum, i) => sum + (parseFloat(i.json.revenue_previous) || 0), 0);
    const revenueChange = totalRevenuePrevious > 0 ? (((totalRevenueCurrent - totalRevenuePrevious) / totalRevenuePrevious) * 100).toFixed(1) : 0;
    
    const totalPayrollCurrent = payrollData.reduce((sum, i) => sum + (parseFloat(i.json.payroll_current) || 0), 0);
    const totalPayrollPrevious = payrollData.reduce((sum, i) => sum + (parseFloat(i.json.payroll_previous) || 0), 0);
    const payrollChange = totalPayrollPrevious > 0 ? (((totalPayrollCurrent - totalPayrollPrevious) / totalPayrollPrevious) * 100).toFixed(1) : 0;
    
    const totalMarketingSpend = expensesData.reduce((sum, i) => sum + (parseFloat(i.json.marketing_spend) || 0), 0);
    const totalMarketingRevenue = revenueData.reduce((sum, i) => sum + (parseFloat(i.json.marketing_attributed_revenue) || 0), 0);
    const marketingROI = totalMarketingSpend > 0 ? ((totalMarketingRevenue / totalMarketingSpend) * 100).toFixed(1) : 0;
    const marketingROIPrevious = 85;
    const marketingROIChange = (marketingROI - marketingROIPrevious).toFixed(1);
    
    const currentCash = cashflowData.reduce((sum, i) => sum + (parseFloat(i.json.cash_balance) || 0), 0);
    const monthlyBurnRate = expensesData.reduce((sum, i) => sum + (parseFloat(i.json.monthly_burn) || 0), 0);
    const cashRunway = monthlyBurnRate > 0 ? (currentCash / monthlyBurnRate).toFixed(1) : 'N/A';
    
    const totalSubscriptions = subscriptionData.reduce((sum, i) => sum + (parseFloat(i.json.subscription_revenue) || 0), 0);
    const totalExpenses = expensesData.reduce((sum, i) => sum + (parseFloat(i.json.expense_amount) || 0), 0);
    
    const today = new Date().toISOString().split('T')[0];
    
    const revenueStatus = revenueChange < -10 ? '🔴 ALERT' : revenueChange < 0 ? '🟡 WARNING' : '🟢 GOOD';
    const payrollStatus = payrollChange > 10 ? '🔴 ALERT' : payrollChange > 5 ? '🟡 WARNING' : '🟢 GOOD';
    const cashRunwayStatus = parseFloat(cashRunway) < 3 ? '🔴 CRITICAL' : parseFloat(cashRunway) < 6 ? '🟡 WARNING' : '🟢 HEALTHY';
    const marketingStatus = marketingROIChange > 0 ? '🟢 IMPROVING' : '🟡 DECLINING';
    
    return [{
      json: {
        date: today,
        revenue_current: totalRevenueCurrent,
        revenue_previous: totalRevenuePrevious,
        revenue_change_pct: parseFloat(revenueChange),
        payroll_current: totalPayrollCurrent,
        payroll_change_pct: parseFloat(payrollChange),
        marketing_roi: parseFloat(marketingROI),
        marketing_roi_change: parseFloat(marketingROIChange),
        cash_balance: currentCash,
        monthly_burn_rate: monthlyBurnRate > 0 ? monthlyBurnRate / allItems.filter(i => i.json.monthly_burn).length : 0,
        cash_runway_months: parseFloat(cashRunway),
        subscriptions_mrr: totalSubscriptions,
        total_expenses: totalExpenses,
        revenue_status: revenueStatus,
        payroll_status: payrollStatus,
        cash_status: cashRunwayStatus,
        marketing_status: marketingStatus
      }
    }];
  5. Configure the AI Agent to generate the briefing

    Add an AI Agent node (@n8n/n8n-nodes-langchain.agent, typeVersion 3, promptType: define). Connect an OpenAI GPT-4o-mini sub-node (@n8n/n8n-nodes-langchain.lmChatOpenAi, typeVersion 1.3, model: gpt-4o-mini) to its ai_languageModel input. Fill the Agent node's options.systemMessage and text fields with the prompts below. The {{ $json.* }} variables in the text field automatically reference the previous KPI node's output.

    Execution prompt · Source text。options.systemMessage field of the 'Generate AI Outreach Message1' node

    You are a senior CFO assistant. Your job is to turn raw financial KPI data into a sharp, scannable executive briefing for Telegram. Rules: use Telegram Markdown (*bold* for labels), include emojis for each section, keep total length under 350 words, be direct and action-oriented — if a metric is at WARNING or ALERT status call out the specific recommended action, otherwise just confirm it is healthy. Never add filler sentences.

    Execution prompt · Source text。text field (user prompt) of the 'Generate AI Outreach Message1' node

    =You are an expert CFO assistant. Write a concise daily financial briefing for the executive team based on the data below. Format it for Telegram using *bold* for section labels. Use emojis for quick scanning. Be direct, highlight what changed and what action (if any) is needed. Keep it under 350 words.
    
    📅 Report Date: {{ $json.date }}
    
    💰 REVENUE
    - Current: ${{ $json.revenue_current }}
    - Previous: ${{ $json.revenue_previous }}
    - Change: {{ $json.revenue_change_pct }}%
    - Status: {{ $json.revenue_status }}
    
    👥 PAYROLL
    - Current: ${{ $json.payroll_current }}
    - Change: {{ $json.payroll_change_pct }}%
    - Status: {{ $json.payroll_status }}
    
    📣 MARKETING ROI
    - ROI: {{ $json.marketing_roi }}%
    - Change vs baseline: {{ $json.marketing_roi_change }}%
    - Status: {{ $json.marketing_status }}
    
    🏦 CASH POSITION
    - Balance: ${{ $json.cash_balance }}
    - Monthly Burn: ${{ $json.monthly_burn_rate }}
    - Runway: {{ $json.cash_runway_months }} months
    - Status: {{ $json.cash_status }}
    
    📦 SUBSCRIPTIONS MRR: ${{ $json.subscriptions_mrr }}
    💸 TOTAL EXPENSES: ${{ $json.total_expenses }}
    
    End with a 1–2 line executive summary highlighting the single most important insight today.
  6. Merge AI briefing with financial data

    Add a Code node (typeVersion 2) and paste the code below. It merges the AI Agent output (output) with the KPI data into a single object containing a telegram_report field, used by downstream Notion and Telegram nodes.

    Execution prompt · Source text。JS Code field of the 'Merge AI Report + Financial Data' node

    const aiOutput = $('Generate AI Outreach Message1').item.json.output || '';
    const financialData = $('Calculate KPIs & Status Labels').item.json;
    
    return [{
      json: {
        ...financialData,
        telegram_report: aiOutput
      }
    }];
  7. Configure delivery and archiving

    From the 'Merge AI Report + Financial Data' node, create 3 branches: 1) Notion node (typeVersion 2, resource: databasePage): set databaseId to your CFO Report database ID; title to =CFO Report — {{ $json.date }}; blockUi and propertiesUi to {{ $json.telegram_report }} and {{ $json.marketing_status }}. 2) Telegram node (typeVersion 1.1): set chatId to your target Chat ID; text to {{ $json.telegram_report }}; additionalFields.parse_mode to Markdown. 3) If node (typeVersion 2, 'Check for Critical Revenue Drop'): condition revenue_change_pct < -10 (number/lt). The true branch connects to a second Telegram node that sends the critical alert.

    Execution prompt · Source text。text field of the 'Send Critical Revenue Alert' node

    =🚨 *CRITICAL CFO ALERT — {{ $json.date }}*
    
    ⚠️ Revenue has dropped {{ $json.revenue_change_pct }}% — immediate attention required!
    
    💰 Cash Runway: {{ $json.cash_runway_months }} months
    🔥 Monthly Burn: ${{ $json.monthly_burn_rate }}
    
    Check the full report in Notion now.
  8. Configure error alerting

    Add an Error Trigger node (typeVersion 1) and a Slack node (typeVersion 2.3). Connect the Error Trigger output to the Slack node input. In the Slack node: select channel mode and specify the target channel; set authentication to oAuth2; the text field currently contains a placeholder '=Error occured ' — replace it with a template including workflow name, node name, and error timestamp for production use. This branch is independent of the main flow and catches failures from any node.

Prompt you can copy

Setup guidance · Editorial suggestion。Hand to a setup assistant to confirm inputs and permissions before reproducing

This block is the prompt. Ads are never placed here.

You are reproducing an n8n workflow template: daily automated executive financial briefings. Proceed in this order: 1) Confirm you have an n8n instance and all required credentials (Google Sheets OAuth2, OpenAI, Notion, Telegram Bot, Slack OAuth2); 2) Import workflow.json or build manually following the steps; 3) Replace YOUR_GOOGLE_SHEET_ID, YOUR_NOTION_DATABASE_ID, and YOUR_TELEGRAM_CHAT_ID with real values; 4) Trigger manually once to verify the 5 sheets load, KPIs calculate correctly, the AI briefing generates, and the Telegram message arrives; 5) Test the >10% revenue drop critical alert branch (temporarily adjust test data if needed); 6) Confirm the Slack error alert channel receives notifications. If you hit credential permission issues, check Google Sheets sharing settings and Notion integration permissions first.

This template has no single 'run prompt'; core execution content is distributed across Step 4 (KPI calculation code), Step 5 (AI Agent system/user prompts), Step 6 (merge code), and Step 7 (Telegram critical alert template).

Source

Send daily executive financial briefings with Google Sheets, GPT-4o-mini, Notion and Telegram · rahul08 · n8n.io · 2026-06-17

Comments & feedback

Tried this method? Share results, problems or improvements. Comments appear after moderation. Please avoid sensitive information.

Loading…

    Related