This workflow corresponds to n8n.io template #15568 — we link there as the canonical source.
This workflow follows the Agent → Gmail 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 →
{
"id": "bmkUvICtIGmaEAUA",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Weekly Client Report Generator",
"tags": [],
"nodes": [
{
"id": "74f8e71a-17c3-482a-8cfb-d86fef73673a",
"name": "Start workflow",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-400,
-48
],
"parameters": {},
"typeVersion": 1
},
{
"id": "1d75f247-1432-4d4f-aef3-7c322d19a87d",
"name": "Format Report",
"type": "n8n-nodes-base.code",
"position": [
1088,
-64
],
"parameters": {
"jsCode": "const output = $json.output || \"\";\n\n// Remove markdown (**)\nconst cleanOutput = output.replace(/\\*\\*/g, \"\");\n\n// Convert sections to HTML\nconst formatted = cleanOutput\n .replace(/Summary:/gi, \"<b>Summary:</b><br>\")\n .replace(/Key Highlights:/gi, \"<b>Key Highlights:</b><br>\")\n .replace(/Risk Analysis:/gi, \"<b>Risk Analysis:</b><br>\")\n .replace(/Future Outlook:/gi, \"<b>Future Outlook:</b><br>\")\n .replace(/\\n/g, \"<br>\");\n\n// Final HTML\nconst formattedReport = `\n<div>\n <p>${formatted}</p>\n</div>\n`;\n\nreturn [\n {\n json: {\n ...$json, \n formattedReport\n }\n }\n];"
},
"typeVersion": 2
},
{
"id": "d87b22b5-d255-49fd-98f2-20e092f2a529",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-880,
-272
],
"parameters": {
"width": 336,
"height": 960,
"content": "# Weekly Client Report Generator\n\n# How It Works\n\nThis workflow automatically generates and emails weekly portfolio reports to clients. It fetches client data from Google Sheets, calculates investment, profit and growth, then uses AI to create a short, clear report. The report is formatted in HTML, sent via Gmail and the Google Sheet is updated to mark the email \u201cSent,\u201d keeping track of all reports automatically.\n\n# Setup Steps\n## Prepare Google Sheet\nMake sure your sheet has columns: Client, Email, Invested, Current Value and Status.\n\n## Connect Accounts in n8n\nAdd credentials for Google Sheets, Gmail and Groq AI.\n\n## Start Workflow\nUse a trigger to begin.\n\n## Process Data\nFetch client data, calculate portfolio metrics, generate AI report.\n\n## Send Email & Update Sheet\nSend the report via Gmail and update the Status column in Google Sheets."
},
"typeVersion": 1
},
{
"id": "0393ca71-aa77-45a8-8d93-e1c3efb07d12",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-464,
-240
],
"parameters": {
"color": 7,
"width": 896,
"height": 432,
"content": "## Client Data Fetch & Batch Processing\n\nThis section starts the workflow manually, fetches client data from Google Sheets and processes clients in batches. It ensures each client\u2019s investment details (Invested, Current Value, Email) are handled individually, preparing accurate data for portfolio calculations and personalized report generation."
},
"typeVersion": 1
},
{
"id": "41c5e3d7-7586-4393-9799-c3a4b610bb0e",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
464,
-240
],
"parameters": {
"color": 7,
"width": 768,
"height": 560,
"content": "## Portfolio Calculation & Report Generation\n\nThese nodes calculate each client\u2019s total investment, profit and growth. Then, AI generates a short, simple weekly report including Summary, Key Highlights, Risk Analysis and Future Outlook, also format the report."
},
"typeVersion": 1
},
{
"id": "d76ab043-6bb3-4ab7-bb9b-d061eb47aa95",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1280,
-224
],
"parameters": {
"color": 7,
"width": 864,
"height": 512,
"content": "## Final Delivery & Tracking\n\nThe Wait node ensures smooth processing, the Gmail node sends the weekly report to the client and the Google Sheets update node marks the \u201cStatus\u201d as Sent, so you can track which clients have received their reports."
},
"typeVersion": 1
},
{
"id": "b904b524-7647-495b-a46d-e8e0e1fecc32",
"name": "Prepare Data for Sheet",
"type": "n8n-nodes-base.set",
"position": [
1520,
-64
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "8266d657-66aa-424c-8251-7c4345c3efe3",
"name": "=Client",
"type": "string",
"value": "={{$json.Client}}"
},
{
"id": "7f76db0b-59e5-4145-9692-9612267cc255",
"name": "=Invested",
"type": "number",
"value": "={{ $json.Invested }}"
},
{
"id": "d19c16fc-9e2d-4c75-bcf5-7d8dc1c06af9",
"name": "Current Value",
"type": "string",
"value": "={{ $json['Current Value'] }}"
},
{
"id": "c01d2b24-39fa-4166-9010-13befcf5b48c",
"name": "Email",
"type": "string",
"value": "={{ $json.Email }}"
},
{
"id": "e2326aef-0d40-47de-82cf-f6262e07d671",
"name": "formattedReport",
"type": "string",
"value": "={{ $json.formattedReport }}"
},
{
"id": "5c3ad6a2-b313-401c-a925-fcb906305921",
"name": "Status",
"type": "string",
"value": "Sent"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "c4f016c1-2a1b-4a6f-a9cb-8a6f9e71aad5",
"name": "Pause Before Sending Email",
"type": "n8n-nodes-base.wait",
"position": [
1312,
-64
],
"parameters": {},
"typeVersion": 1.1
},
{
"id": "0b5dd762-3fff-419a-b239-e18c7c0a3359",
"name": "Get Client Data from Google Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
-192,
-48
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1GwBgjfbdWzXLA5eOiob1O1YFzgqPPW69sOYWTZWQw-w/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1GwBgjfbdWzXLA5eOiob1O1YFzgqPPW69sOYWTZWQw-w",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1GwBgjfbdWzXLA5eOiob1O1YFzgqPPW69sOYWTZWQw-w/edit?usp=drivesdk",
"cachedResultName": "weekely clientData"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "d12d0923-eb79-4013-9c96-86668e8bb786",
"name": "Process Clients in Batches",
"type": "n8n-nodes-base.splitInBatches",
"position": [
16,
-48
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "f1b22db7-e35c-46fd-8b81-94c4ebff35d3",
"name": "Compute Investment, Profit & Growth",
"type": "n8n-nodes-base.code",
"position": [
288,
-32
],
"parameters": {
"jsCode": "const invested = Number($json[\"Invested\"] || 0);\nconst current = Number($json[\"Current Value\"] || 0);\n\nconst profit = current - invested;\n\nconst growth = invested > 0\n ? ((profit / invested) * 100).toFixed(2)\n : 0;\n\nreturn [\n {\n json: {\n ...$json, // keep original data (Email, Client)\n totalInvested: invested,\n totalCurrent: current,\n profit,\n growth\n }\n }\n];"
},
"typeVersion": 2
},
{
"id": "ced41c5e-69ac-44fc-91f8-7b76d228122d",
"name": "Generate Weekly Portfolio Report",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
544,
-64
],
"parameters": {
"text": "=You are a financial analyst.\n\nGenerate a weekly client portfolio report using the data below:\n\nTotal Investment: {{$json.totalInvested}}\nCurrent Value: {{$json.totalCurrent}}\nProfit: {{$json.profit}}\nGrowth: {{$json.growth}}%\n\nYour report must include:\n\n1. Summary (overall performance in simple words)\n2. Key Highlights (profit/loss insights)\n3. Risk Analysis (low/medium/high risk)\n4. Future Outlook (next week expectation)\n\nKeep the report:\n- Simple\n- Professional\n- Short (5\u20136 lines)\n\nDo not use complex financial jargon.",
"options": {},
"promptType": "define"
},
"typeVersion": 3.1
},
{
"id": "8c18d666-7ebb-47e4-8180-557c4a47f16b",
"name": "Generate Weekly Portfolio Report1",
"type": "@n8n/n8n-nodes-langchain.lmChatGroq",
"position": [
560,
160
],
"parameters": {
"model": "openai/gpt-oss-120b",
"options": {}
},
"credentials": {
"groqApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "08dbdd32-5200-48bd-94cd-f988515edaf5",
"name": "Prepare AI Output for Formatting",
"type": "n8n-nodes-base.code",
"position": [
880,
-64
],
"parameters": {
"jsCode": "return items.map(item => {\n return {\n json: {\n ...$node[\"Compute Investment, Profit & Growth\"].json, // original client data\n output: item.json.output\n }\n };\n});"
},
"typeVersion": 2
},
{
"id": "465ac0ba-4a12-4d79-a88a-e5403108ed5e",
"name": "Send Report via Gmail",
"type": "n8n-nodes-base.gmail",
"position": [
1712,
-64
],
"parameters": {
"sendTo": "={{ $json.Email }}",
"message": "=Hello {{ $json.Client }},\n\nHere is your weekly portfolio report:\n\n{{ $json.formattedReport }}\n\nRegards,\nYour Company",
"options": {},
"subject": "Weekly Portfolio Report"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "a394285b-286e-4dbe-b15f-ec2299213f69",
"name": "Update Client Status in Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
1920,
-64
],
"parameters": {
"columns": {
"value": {
"Email": "={{ $('Pause Before Sending Email').item.json.Email }}",
"Client": "={{ $('Pause Before Sending Email').item.json.Client }}",
"Status": "Sent",
"Invested": "={{ $('Pause Before Sending Email').item.json.Invested }}",
"row_number": 0,
"Current Value": "={{ $('Pause Before Sending Email').item.json['Current Value'] }}"
},
"schema": [
{
"id": "Client",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Client",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Invested",
"type": "string",
"display": true,
"required": false,
"displayName": "Invested",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Current Value",
"type": "string",
"display": true,
"required": false,
"displayName": "Current Value",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Status",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "row_number",
"type": "number",
"display": true,
"removed": false,
"readOnly": true,
"required": false,
"displayName": "row_number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Client"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1GwBgjfbdWzXLA5eOiob1O1YFzgqPPW69sOYWTZWQw-w/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1GwBgjfbdWzXLA5eOiob1O1YFzgqPPW69sOYWTZWQw-w",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1GwBgjfbdWzXLA5eOiob1O1YFzgqPPW69sOYWTZWQw-w/edit?usp=drivesdk",
"cachedResultName": "weekely clientData"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
}
],
"active": false,
"settings": {
"availableInMCP": false,
"executionOrder": "v1"
},
"versionId": "2817799c-11b5-4711-80c7-e14e7e7d0f60",
"connections": {
"Format Report": {
"main": [
[
{
"node": "Pause Before Sending Email",
"type": "main",
"index": 0
}
]
]
},
"Start workflow": {
"main": [
[
{
"node": "Get Client Data from Google Sheets",
"type": "main",
"index": 0
}
]
]
},
"Send Report via Gmail": {
"main": [
[
{
"node": "Update Client Status in Sheet",
"type": "main",
"index": 0
}
]
]
},
"Prepare Data for Sheet": {
"main": [
[
{
"node": "Send Report via Gmail",
"type": "main",
"index": 0
}
]
]
},
"Pause Before Sending Email": {
"main": [
[
{
"node": "Prepare Data for Sheet",
"type": "main",
"index": 0
}
]
]
},
"Process Clients in Batches": {
"main": [
[],
[
{
"node": "Compute Investment, Profit & Growth",
"type": "main",
"index": 0
}
]
]
},
"Update Client Status in Sheet": {
"main": [
[
{
"node": "Process Clients in Batches",
"type": "main",
"index": 0
}
]
]
},
"Generate Weekly Portfolio Report": {
"main": [
[
{
"node": "Prepare AI Output for Formatting",
"type": "main",
"index": 0
}
]
]
},
"Prepare AI Output for Formatting": {
"main": [
[
{
"node": "Format Report",
"type": "main",
"index": 0
}
]
]
},
"Generate Weekly Portfolio Report1": {
"ai_languageModel": [
[
{
"node": "Generate Weekly Portfolio Report",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Get Client Data from Google Sheets": {
"main": [
[
{
"node": "Process Clients in Batches",
"type": "main",
"index": 0
}
]
]
},
"Compute Investment, Profit & Growth": {
"main": [
[
{
"node": "Generate Weekly Portfolio Report",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
gmailOAuth2googleSheetsOAuth2ApigroqApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow automatically generates weekly portfolio reports for clients using their investment data from Google Sheets. It calculates profit, growth and other key metrics, formats a professional report, sends it via Gmail and updates the client’s status in the sheet.
Source: https://n8n.io/workflows/15568/ — 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 n8n workflow automates your entire B2B outreach pipeline from lead discovery to personalized cold email delivery. Submit a form, let Apollo find and enrich your leads, review AI-generated emails
How It Works Trigger: The workflow starts automatically when a new file (PDF, DOCX, or TXT) is uploaded to a specific Google Drive folder for client briefs. Configuration: The workflow sets up key var
This workflow automates real estate investment analysis using Google Sheets and AI. It calculates ROI and rental yield, detects duplicate entries, generates AI-based recommendations and sends email re
This workflow automates the tracking of stock market sector rotation. It fetches a list of active stocks from Google Sheets, pulls their last 5 days of market data from Yahoo Finance and calculates mo
This automated n8n workflow evaluates the historical performance of gold against equity markets. It extracts daily price data from Google Sheets, calculates comparative returns and uses an AI agent to