This workflow corresponds to n8n.io template #15223 — 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": "vtGMD3Uq1vDutnQ5",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Goal-Based Savings Tracker with AI Nudges",
"tags": [],
"nodes": [
{
"id": "c04e8622-02c3-4013-8105-cd5dc8f380d6",
"name": "Overview: Savings AI Tracker",
"type": "n8n-nodes-base.stickyNote",
"position": [
0,
0
],
"parameters": {
"color": null,
"width": 448,
"height": 460,
"content": "## Goal-Based Savings Tracker + AI Nudges\n\n### How it works:\nThis workflow pulls savings data from Google Sheets, calculates progress toward a goal and uses AI to generate motivational nudges and adjusted savings targets.\n\n### Setup steps:\n1. Connect your Google Sheets account and map required columns\n2. Use Set/Edit Fields to clean and normalize the data\n3. Configure the IF node to evaluate progress (ahead vs. behind)\n4. Add Set fields again to define messaging context for each case\n5. Connect your OpenAI API to generate nudges\n6. Format the final message output\n7. Set up email (or notification) delivery\n8. Test and activate the workflow"
},
"typeVersion": 1
},
{
"id": "f07e7347-8896-4295-9334-ff8b31dd8649",
"name": "Fetch Savings Data (Google Sheets)",
"type": "n8n-nodes-base.googleSheets",
"position": [
544,
608
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1KA65Fzm1uP4kP8UiCN7rlQxUmcCv5ESxhivfxfDui2s/edit#gid=0",
"cachedResultName": "Savings"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1KA65Fzm1uP4kP8UiCN7rlQxUmcCv5ESxhivfxfDui2s",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1KA65Fzm1uP4kP8UiCN7rlQxUmcCv5ESxhivfxfDui2s/edit?usp=drivesdk",
"cachedResultName": "N8N Nirmit"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "ae676fa0-8ca6-455d-aa4c-fa0dfc27ffdf",
"name": "Prepare & Normalize Data (EDIT Fields)",
"type": "n8n-nodes-base.set",
"position": [
784,
608
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "bcc5d919-4380-461f-842c-27ea554ffc46",
"name": "goal_amount",
"type": "number",
"value": "={{$json[\"Goal Amount\"]}}"
},
{
"id": "9a90777f-143b-4b0b-86d3-550d26d3dc26",
"name": "current_savings",
"type": "number",
"value": "={{$json[\"Total Saved\"]}}"
},
{
"id": "42529b72-6724-4506-a2f4-07c694348808",
"name": "start_date",
"type": "string",
"value": "={{$json[\"Start Date\"]}}"
},
{
"id": "9fb0c1f8-e47b-4be8-88eb-d93b3a274de6",
"name": "target_date",
"type": "string",
"value": "={{$json[\"Target Date\"]}}"
},
{
"id": "ad5a0de3-319e-403b-b6d0-cc0870e11533",
"name": "today_date",
"type": "string",
"value": "={{$now}}"
},
{
"id": "d884ffc2-0082-40e7-9cf2-1c65a2c3e5eb",
"name": "=total_days",
"type": "number",
"value": "={{\nMath.floor(\n(new Date($json[\"Target Date\"]) - new Date($json[\"Start Date\"])) \n/ (1000 * 60 * 60 * 24)\n)\n}}"
},
{
"id": "b4ded097-b420-4521-b358-c882f4886d2e",
"name": "days_passed",
"type": "number",
"value": "={{\nMath.floor(\n(new Date() - new Date($json[\"Start Date\"])) \n/ (1000 * 60 * 60 * 24)\n)\n}}"
},
{
"id": "f7c95ddb-3d1d-4016-992c-eb33795a656a",
"name": "days_remaining",
"type": "number",
"value": "={{\nMath.max(\n0,\nMath.floor(\n(new Date($json[\"Target Date\"]) - new Date()) \n/ (1000 * 60 * 60 * 24)\n)\n)\n}}"
},
{
"id": "641d7f7a-068a-4108-9541-5dda2e9fe567",
"name": "expected_savings_by_now",
"type": "number",
"value": "={{\n(() => {\n const start = new Date($json[\"Start Date\"]);\n const target = new Date($json[\"Target Date\"]);\n const today = new Date();\n\n const totalDays = Math.floor((target - start) / (1000 * 60 * 60 * 24));\n const daysPassed = Math.floor((today - start) / (1000 * 60 * 60 * 24));\n\n if (!totalDays || totalDays <= 0) return 0;\n\n return ($json[\"Goal Amount\"] / totalDays) * Math.max(0, daysPassed);\n})()\n}}"
},
{
"id": "1035e652-41aa-45d2-ba6d-e769cd7d30db",
"name": "progress_percentage",
"type": "number",
"value": "={{\n($json[\"Total Saved\"] / $json[\"Goal Amount\"]) * 100\n}}"
},
{
"id": "89411b9c-5773-4bd9-8136-24824afda956",
"name": "daily_required_savings",
"type": "number",
"value": "={{\n($json[\"Goal Amount\"] - $json[\"Total Saved\"]) / ($json.days_remaining || 1)\n}}"
},
{
"id": "7d782a32-b565-42f8-b0d1-12c5bbf4696e",
"name": "status",
"type": "string",
"value": "={{ $json[\"Total Saved\"] > $json.expected_savings_by_now ? \"Ahead\" : ($json[\"Total Saved\"] === $json.expected_savings_by_now ? \"On Track\" : \"Behind\") }}"
},
{
"id": "bbd932a3-3b5a-4d43-9cdd-feb9896751db",
"name": "email",
"type": "string",
"value": "={{$json.Email}}"
},
{
"id": "d4cc8092-db79-4562-bf65-4d33b7c6ece4",
"name": "user_name",
"type": "string",
"value": "={{$json.Name}}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "24ac28d7-e1ec-407f-8e01-a6a819f26b9c",
"name": "Evaluate Progress (IF)",
"type": "n8n-nodes-base.if",
"position": [
1040,
608
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "or",
"conditions": [
{
"id": "ae1832d1-82ce-45ec-b5a0-a7ec53375acf",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{$json.status}}",
"rightValue": "Ahead"
},
{
"id": "72ebd124-c64a-4791-9802-e60fa958e912",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{$json.status}}",
"rightValue": "On Track"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "28d1a5ee-c983-4e0b-8edd-d7b908ba265d",
"name": "Format Final Output (EDIT Fields)",
"type": "n8n-nodes-base.set",
"position": [
1872,
608
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "e1e98646-b0fb-4f40-b71c-7784d287e9cf",
"name": "email_subject",
"type": "string",
"value": "Your Daily Savings Progress Update"
},
{
"id": "323a3a26-a456-40d0-b364-18aec49fa7e0",
"name": "email_body",
"type": "string",
"value": "=Hi {{$('Fetch Savings Data (Google Sheets)').item.json.Name || \"there\"}},\n\nMotivation: {{ JSON.parse($json.output).motivation }}\n\nAdvice: {{ JSON.parse($json.output).advice }}\n\nRecommended daily savings: ${{ JSON.parse($json.output).new_daily_target }}"
},
{
"id": "7bf549b1-1a5a-4a5f-b0e3-85+1234567890ff",
"name": "recipient",
"type": "string",
"value": "={{ $('Fetch Savings Data (Google Sheets)').item.json.Email }}"
},
{
"id": "16bae00e-99a7-43d8-a889-936d472d04f2",
"name": "current_savings",
"type": "number",
"value": "={{ $('Prepare & Normalize Data (EDIT Fields)').item.json.current_savings }}"
},
{
"id": "819f73fc-a070-491c-87ca-e77072697f9a",
"name": "goal_amount",
"type": "number",
"value": "={{ $('Prepare & Normalize Data (EDIT Fields)').item.json.goal_amount }}"
},
{
"id": "49b94f30-486a-4c4f-86da-50cc1893aaea",
"name": "days_remaining",
"type": "number",
"value": "={{ $('Prepare & Normalize Data (EDIT Fields)').item.json.days_remaining }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "e13be515-4975-48c4-ae15-734a3f4b428e",
"name": "Send Email Notification",
"type": "n8n-nodes-base.gmail",
"position": [
2080,
608
],
"parameters": {
"sendTo": "={{ $json.recipient }}",
"message": "={{$json.email_body}}",
"options": {},
"subject": "={{ $json.email_subject }}"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "667ce64b-39ca-4b80-90ac-97f7cc5388e3",
"name": "Data + Prep Group",
"type": "n8n-nodes-base.stickyNote",
"position": [
496,
304
],
"parameters": {
"color": 7,
"width": 448,
"height": 672,
"content": "## Fetch Data\nFetch savings data from Google Sheets, clean and normalize fields and compute key metrics like total days, progress and required savings. Ensure accurate date handling and avoid calculation dependencies by separating raw mapping from derived values."
},
"typeVersion": 1
},
{
"id": "7890340f-9941-4836-aefb-60d270dfd14b",
"name": "Logic Group",
"type": "n8n-nodes-base.stickyNote",
"position": [
1008,
304
],
"parameters": {
"color": 7,
"width": 448,
"height": 672,
"content": "## Process Data\nEvaluate user progress by comparing actual savings with expected savings. Classify status as Ahead, On Track or Behind, enabling dynamic branching for personalized messaging and smarter downstream AI-driven recommendations."
},
"typeVersion": 1
},
{
"id": "09ca40cc-b34c-4594-8080-28744547f279",
"name": "AI + Output Group",
"type": "n8n-nodes-base.stickyNote",
"position": [
1488,
304
],
"parameters": {
"color": 7,
"width": 720,
"height": 672,
"content": "## AI Nudges\nGenerate personalized financial nudges using AI based on user status and metrics. Craft motivational messages, suggest actionable savings targets and format the final output for delivery via email or notifications, ensuring clarity, encouragement and practical guidance."
},
"typeVersion": 1
},
{
"id": "39940c4d-4d72-4d5a-94ae-5c88ccde7740",
"name": "AI Savings Coach Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
1504,
608
],
"parameters": {
"text": "=User status: {{ $('Prepare & Normalize Data (EDIT Fields)').item.json.status }} \nCurrent savings: {{ $('Prepare & Normalize Data (EDIT Fields)').item.json.current_savings }} out of {{ $('Prepare & Normalize Data (EDIT Fields)').item.json.goal_amount }} \nDays remaining: {{ $('Prepare & Normalize Data (EDIT Fields)').item.json.days_remaining }} \nMotivation so far: {{ $json.motivation }} \nAdvice so far: {{ $json.advice }}\nRecommended daily savings target: {{ $json.new_daily_target }}\n\nUsing this data, generate a motivational message that includes: \n- A motivational statement \n- Practical advice tailored to their status \n- A specific new daily savings target to help reach their goal \n\nRemember to keep it encouraging and concise.",
"options": {
"systemMessage": "=You are a smart and friendly financial coach.\n\nYour job:\n- Analyze the user's savings progress\n- Motivate them to keep saving\n- Suggest adjusted daily savings targets\n\nRules:\n- Keep responses short (max 120 words)\n- Be encouraging and positive, never judgmental\n- If the user is behind \u2192 suggest a realistic catch-up plan\n- If the user is ahead \u2192 reinforce momentum\n- Always include a specific numeric daily savings suggestion\n\nOutput format:\n{\n \"motivation\": \"<text>\",\n \"advice\": \"<text>\",\n \"new_daily_target\": <number>\n}"
},
"promptType": "define"
},
"typeVersion": 3
},
{
"id": "7ab18492-7cf0-4868-afd5-c76a6a66d091",
"name": "Set Messaging Context (Ahead or Ontrack)",
"type": "n8n-nodes-base.set",
"position": [
1296,
512
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "12f8d08e-35b3-42cb-8f06-227cd5a5e3e0",
"name": "motivation",
"type": "string",
"value": "Great job! You're on track with your savings. Keep up the consistency!"
},
{
"id": "ef510496-7961-49cc-bd8e-d788d601ea2b",
"name": "advice",
"type": "string",
"value": "Maintain your current pace and keep saving steadily."
},
{
"id": "88afc648-939b-48ea-8956-eb6e8ad14f19",
"name": "new_daily_target",
"type": "number",
"value": "={{ $('Prepare & Normalize Data (EDIT Fields)').item.json.daily_required_savings }}"
},
{
"id": "a0eeb931-04fc-4d71-9167-66e22d8e75c3",
"name": "status",
"type": "string",
"value": "={{ $('Prepare & Normalize Data (EDIT Fields)').item.json.status }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "bb1780ba-455a-415f-b824-c452fe478f6f",
"name": "Set Messaging Context (Behind)",
"type": "n8n-nodes-base.set",
"position": [
1296,
704
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "4f24c9f5-6f88-458e-a16d-b2e5a37453d3",
"name": "motivation",
"type": "string",
"value": "Don't worry! You can still reach your goal with a small adjustment."
},
{
"id": "95fde763-8c5f-4e0c-9a79-57d46a52d644",
"name": "advice",
"type": "string",
"value": "Try increasing your daily savings slightly to catch up."
},
{
"id": "7563e704-9dee-4f0c-9148-fe6976184de2",
"name": "new_daily_target",
"type": "number",
"value": "={{$json.daily_required_savings}}"
},
{
"id": "c557aa01-c95c-4800-b7cf-e0afc7c1531e",
"name": "status",
"type": "string",
"value": "={{$json.status}}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "18281baf-0f1f-427b-a1fa-501a9c9a19a3",
"name": "When clicking \u2018Execute workflow\u2019",
"type": "n8n-nodes-base.manualTrigger",
"position": [
320,
608
],
"parameters": {},
"typeVersion": 1
},
{
"id": "2a7d76a1-6f40-4122-abdf-55f859510fc1",
"name": "Google Gemini Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
1504,
800
],
"parameters": {
"options": {},
"modelName": "models/gemini-3.1-flash-lite-preview"
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"executionOrder": "v1"
},
"versionId": "0880b25e-646b-4a01-8bb5-8a6f42b58740",
"connections": {
"AI Savings Coach Agent": {
"main": [
[
{
"node": "Format Final Output (EDIT Fields)",
"type": "main",
"index": 0
}
]
]
},
"Evaluate Progress (IF)": {
"main": [
[
{
"node": "Set Messaging Context (Ahead or Ontrack)",
"type": "main",
"index": 0
}
],
[
{
"node": "Set Messaging Context (Behind)",
"type": "main",
"index": 0
}
]
]
},
"Google Gemini Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Savings Coach Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Set Messaging Context (Behind)": {
"main": [
[
{
"node": "AI Savings Coach Agent",
"type": "main",
"index": 0
}
]
]
},
"Format Final Output (EDIT Fields)": {
"main": [
[
{
"node": "Send Email Notification",
"type": "main",
"index": 0
}
]
]
},
"Fetch Savings Data (Google Sheets)": {
"main": [
[
{
"node": "Prepare & Normalize Data (EDIT Fields)",
"type": "main",
"index": 0
}
]
]
},
"When clicking \u2018Execute workflow\u2019": {
"main": [
[
{
"node": "Fetch Savings Data (Google Sheets)",
"type": "main",
"index": 0
}
]
]
},
"Prepare & Normalize Data (EDIT Fields)": {
"main": [
[
{
"node": "Evaluate Progress (IF)",
"type": "main",
"index": 0
}
]
]
},
"Set Messaging Context (Ahead or Ontrack)": {
"main": [
[
{
"node": "AI Savings Coach Agent",
"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.
gmailOAuth2googlePalmApigoogleSheetsOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
> n8n, Google Sheets & Gemini AI
Source: https://n8n.io/workflows/15223/ — 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 workflow contains community nodes that are only compatible with the self-hosted version of n8n.
Turn a simple email workflow into a LinkedIn content machine. Generate post ideas, draft full posts, and auto-publish to LinkedIn all controlled by replying to emails.
This workflow is for hotel managers, travel agencies, and hospitality teams who receive booking requests via email. It eliminates the need for manual data entry by automatically parsing emails and att
Based on the Google Sheet data, the AI will retrieve the userstories ID's, retrieves the userstory data and the corresponding attachments and creates sprint goals according to the defined system promp
Laporan Penjualan Otomatis Telegram. Uses googleSheets, agent, httpRequest, gmail. Event-driven trigger; 32 nodes.