This workflow corresponds to n8n.io template #15338 — we link there as the canonical source.
This workflow follows the Gmail → Googlegemini 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 →
{
"meta": {
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "73d83ab3-98bc-49f8-90d5-b26c8ebb7823",
"name": "Calculate Portfolio Metrics",
"type": "n8n-nodes-base.code",
"position": [
1552,
880
],
"parameters": {
"jsCode": "const portfolio = $input.all().map((item, index) => {\n const quantity = parseFloat($('Google Sheet New Row Add Trigger').all()[index].json.Quantity);\n const purchasePrice = parseFloat($('Google Sheet New Row Add Trigger').all()[index].json['Purchase Price']);\n const currentPrice = Object.values(item.json.prices)[0].last_price;\n\n const currentValue = quantity * currentPrice;\n const gainLoss = currentValue - (quantity * purchasePrice);\n\n return {\n name: Object.values(item.json.prices)[0].symbol,\n PurchasePrice: purchasePrice,\n Quantity: quantity,\n CurrentValue: currentValue,\n GainLoss: gainLoss,\n };\n});\n\nreturn { \n json: {\n portfolio: portfolio\n }\n};"
},
"typeVersion": 2
},
{
"id": "0d7cdd02-b18d-4adb-ab54-1146382dfe19",
"name": "Iterate Stocks for News",
"type": "n8n-nodes-base.splitInBatches",
"position": [
1280,
1104
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "fdcac84d-2baf-4af4-ad8e-983fbc66e4cc",
"name": "Combining All News Articles",
"type": "n8n-nodes-base.code",
"position": [
1552,
1088
],
"parameters": {
"jsCode": "const allArticles = [];\n\nfor (const item of $input.all()) {\n \n if (item.json.articles) {\n let limitArticles = item.json.articles.slice(0, 4);\n allArticles.push(limitArticles);\n }\n}\n\nreturn {\n json: {\n articles: allArticles\n }\n }\n"
},
"typeVersion": 2
},
{
"id": "d702c7df-c612-4236-be2c-ef74aefe9dbc",
"name": "Combine Portfolio + News",
"type": "n8n-nodes-base.merge",
"position": [
1952,
960
],
"parameters": {},
"typeVersion": 3.2
},
{
"id": "bc68edd5-1ce9-4b89-b301-19a2857f3c16",
"name": "Final Data Formatter",
"type": "n8n-nodes-base.code",
"position": [
2128,
960
],
"parameters": {
"jsCode": "const out = [];\nlet input = $input.all()\nfor (const item of input) {\n console.log(item.json[0])\n out.push(Object.values(item.json)[0])\n}\n\nreturn {\n json:{\n out\n }\n};"
},
"typeVersion": 2
},
{
"id": "d007519a-1469-420f-b57b-10cd01c30b76",
"name": "Generate Portfolio Summary",
"type": "@n8n/n8n-nodes-langchain.googleGemini",
"position": [
2288,
960
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "models/gemini-3.1-flash-lite-preview",
"cachedResultName": "models/gemini-3.1-flash-lite-preview"
},
"options": {},
"messages": {
"values": [
{
"content": "=You are a financial assistant.\n\nAnalyze the following client portfolio data and generate a simple, easy-to-understand summary.\n\nData:\n{{ JSON.stringify($json.out) }}\n\nInstructions:\n- Start with an overall portfolio performance summary (profit or loss).\n- Mention total gain or loss clearly.\n- Briefly highlight best-performing and worst-performing holdings.\n- Keep the tone simple and client-friendly (not technical).\n- Keep it within 4\u20136 sentences.\n- If there is a loss, explain it calmly and suggest staying diversified or long-term thinking.\n- If there is a gain, mention positive performance but avoid overpromising.\n\nOutput format:\nA short paragraph summary only."
}
]
},
"builtInTools": {}
},
"executeOnce": false,
"typeVersion": 1.1
},
{
"id": "2923bbb6-14d3-4382-86aa-0b5dfffaa1c9",
"name": "Send Email Report",
"type": "n8n-nodes-base.gmail",
"position": [
2576,
960
],
"parameters": {
"sendTo": "",
"message": "={{ $json.content.parts[0].text }}",
"options": {
"appendAttribution": false
},
"subject": "Portfolio Analysis",
"emailType": "text"
},
"typeVersion": 2.2
},
{
"id": "5ade9665-9fe7-404c-9b36-8c03bbb416af",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
320,
496
],
"parameters": {
"width": 464,
"height": 496,
"content": "### AUTOMATED STOCK PORTFOLIO ANALYSIS WORKFLOW\n\n### How it works:\nThis workflow automatically analyzes your stock portfolio whenever a new row is added to Google Sheets. It fetches live stock prices, calculates portfolio performance (current value and gain/loss) and gathers recent news for each stock. The data is then combined and processed using AI to generate a simple, client-friendly summary, which is sent via email.\n\n### Setup steps:\nConnect your Google Sheets account and select the portfolio sheet.\nAdd stock entries with Name, Quantity and Purchase Price.\nConfigure API keys for stock prices and news services.\nConnect your email account for report delivery.\nActivate the workflow.\n\nThis setup provides automated, real-time insights by combining financial data with relevant news, helping users track performance and stay informed effortlessly."
},
"typeVersion": 1
},
{
"id": "b0bea0f1-d1af-4f97-9a9b-837e926e5d3b",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
848,
800
],
"parameters": {
"color": 7,
"width": 384,
"height": 512,
"content": "### Data INPUT & PREPARATION\nCaptures new rows from Google Sheets and standardizes fields like stock name, quantity and price.\nEnsures clean, consistent data for processing."
},
"typeVersion": 1
},
{
"id": "e324c325-722c-4f4d-81a3-5e7bdc1ea9f8",
"name": "Wait For 5 Seconds (Cooling Period)",
"type": "n8n-nodes-base.wait",
"position": [
1488,
1280
],
"parameters": {},
"typeVersion": 1.1
},
{
"id": "8644479b-64fa-46dc-ae19-9de04c2d6c63",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1296,
752
],
"parameters": {
"color": 7,
"width": 420,
"height": 300,
"content": "### PRICE & PORTFOLIO CALCULATION\nFetches live stock prices and calculates current value and gain/loss for each holding.\nProvides real-time portfolio performance."
},
"typeVersion": 1
},
{
"id": "d0f7b729-4f70-4439-9a94-4042f3af2881",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1248,
1088
],
"parameters": {
"color": 7,
"width": 624,
"height": 524,
"content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n### NEWS LOOP & FETCHING\nIterates through each stock, applies delay to avoid rate limits and fetches related news articles.\nFilters top articles to keep only relevant insights."
},
"typeVersion": 1
},
{
"id": "4df8e5df-1d0c-41db-a40c-0e78077013a0",
"name": "Cleans & standardizes",
"type": "n8n-nodes-base.set",
"position": [
1088,
1104
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "2fa6ba2e-7e6c-4b20-94ec-6f02b61dbbae",
"name": "Name",
"type": "string",
"value": "={{ $json.Name }}"
},
{
"id": "2148e01a-1c21-42bc-acb7-a6467be8fc04",
"name": "Quantity",
"type": "number",
"value": "={{ $json.Quantity }}"
},
{
"id": "8697c2c5-1289-4179-8499-426f742a39cb",
"name": "Purchase Price",
"type": "number",
"value": "={{ $json[\"Purchase Price\"] }}"
},
{
"id": "73fd1e02-e31a-4108-9aae-6b3ba49aba2a",
"name": "Purchase Date",
"type": "string",
"value": "={{ $json[\"Purchase Date\"] }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "e344e105-3d0f-42ec-90d9-924c6d3cd888",
"name": "Google Sheet New Row Add Trigger",
"type": "n8n-nodes-base.googleSheetsTrigger",
"position": [
896,
960
],
"parameters": {
"event": "rowAdded",
"options": {},
"pollTimes": {
"item": [
{
"mode": "everyHour"
}
]
},
"sheetName": {
"__rl": true,
"mode": "list",
"value": 1110866377,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1fwvOWtXwLzgx1FF_v1FaxTMDEiIN0qPF_zE1uFJj1Q8/edit#gid=1110866377",
"cachedResultName": "stock portfolio"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1fwvOWtXwLzgx1FF_v1FaxTMDEiIN0qPF_zE1uFJj1Q8",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1fwvOWtXwLzgx1FF_v1FaxTMDEiIN0qPF_zE1uFJj1Q8/edit?usp=drivesdk",
"cachedResultName": "N8N - PRACTICE"
}
},
"typeVersion": 1
},
{
"id": "3ef8aa60-60ec-4ad8-a622-b17d17212127",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
1888,
832
],
"parameters": {
"color": 7,
"width": 816,
"height": 320,
"content": "### AI SUMMARY & EMAIL DELIVERY\nCombines portfolio and news data, generates a simple AI-based summary and sends the final report via email."
},
"typeVersion": 1
},
{
"id": "4c329382-1fbd-45f5-a293-0820edc0ec5a",
"name": "Fetch Live Stock Prices",
"type": "n8n-nodes-base.httpRequest",
"position": [
1360,
880
],
"parameters": {
"url": "https://memic-nse-quotes-api.hf.space/quotes",
"options": {},
"jsonBody": "={{ \n JSON.stringify({\"symbols\": [$json.Name]})\n}}",
"sendBody": true,
"specifyBody": "json"
},
"typeVersion": 4.3
},
{
"id": "c60478ea-022d-4272-8115-6d8b965ee1ba",
"name": "Fetch Stock News",
"type": "n8n-nodes-base.httpRequest",
"position": [
1680,
1280
],
"parameters": {
"url": "https://newsapi.org/v2/everything",
"options": {},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "q",
"value": "={{ $json.Name }}"
},
{
"name": "apiKey"
}
]
}
},
"typeVersion": 4.3
}
],
"connections": {
"Fetch Stock News": {
"main": [
[
{
"node": "Iterate Stocks for News",
"type": "main",
"index": 0
}
]
]
},
"Final Data Formatter": {
"main": [
[
{
"node": "Generate Portfolio Summary",
"type": "main",
"index": 0
}
]
]
},
"Cleans & standardizes": {
"main": [
[
{
"node": "Iterate Stocks for News",
"type": "main",
"index": 0
}
]
]
},
"Fetch Live Stock Prices": {
"main": [
[
{
"node": "Calculate Portfolio Metrics",
"type": "main",
"index": 0
}
]
]
},
"Iterate Stocks for News": {
"main": [
[
{
"node": "Combining All News Articles",
"type": "main",
"index": 0
}
],
[
{
"node": "Wait For 5 Seconds (Cooling Period)",
"type": "main",
"index": 0
}
]
]
},
"Combine Portfolio + News": {
"main": [
[
{
"node": "Final Data Formatter",
"type": "main",
"index": 0
}
]
]
},
"Generate Portfolio Summary": {
"main": [
[
{
"node": "Send Email Report",
"type": "main",
"index": 0
}
]
]
},
"Calculate Portfolio Metrics": {
"main": [
[
{
"node": "Combine Portfolio + News",
"type": "main",
"index": 0
}
]
]
},
"Combining All News Articles": {
"main": [
[
{
"node": "Combine Portfolio + News",
"type": "main",
"index": 1
}
]
]
},
"Google Sheet New Row Add Trigger": {
"main": [
[
{
"node": "Cleans & standardizes",
"type": "main",
"index": 0
},
{
"node": "Fetch Live Stock Prices",
"type": "main",
"index": 0
}
]
]
},
"Wait For 5 Seconds (Cooling Period)": {
"main": [
[
{
"node": "Fetch Stock News",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
> Google Sheets, NewsAPI, Gemini AI & Gmail
Source: https://n8n.io/workflows/15338/ — 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.
Consultants, agencies, freelancers, and professional service firms who need to create customized proposals and contracts quickly and efficiently.
This workflow automatically generates and sends personalized client emails using portfolio data and live market trends. It fetches client details from Google Sheets, retrieves market news via API, fil
This workflow automatically generates and sends personalized sales proposals when a new row is added to Google Sheets. It uses AI to create proposal content, updates contact details in HubSpot, and ge
This template is perfect for YouTube creators, content marketers, and social media managers who want to turn existing videos into fresh, high-performing content ideas—automatically. It’s ideal if you
This workflow turns brand mentions into a lively “personality analysis” — making your reports not only insightful but also fun to read. Perfect for teams that want to stay informed and entertained.