This workflow corresponds to n8n.io template #10188 — we link there as the canonical source.
This workflow follows the Datatable → 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 →
{
"nodes": [
{
"id": "c95623b4-57f9-4f90-96dc-545f13e3892e",
"name": "Webhook - Mood",
"type": "n8n-nodes-base.webhook",
"position": [
-640,
-256
],
"parameters": {
"path": "mood",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 2
},
{
"id": "84062798-8530-43ea-9320-cbef772f48f5",
"name": "Set Mood Data",
"type": "n8n-nodes-base.set",
"position": [
-416,
-256
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "date-field",
"name": "date",
"type": "string",
"value": "={{ $now.toFormat('yyyy-MM-dd') }}"
},
{
"id": "hour-field",
"name": "hour",
"type": "string",
"value": "={{ $now.format('HH:mm') }}"
},
{
"id": "mood-field",
"name": "mood",
"type": "string",
"value": "={{ $json.body.mood }}"
},
{
"id": "note-field",
"name": "note",
"type": "string",
"value": "={{ $json.body.note }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "941ed779-8388-42fd-bee2-72dc3ce23902",
"name": "Insert Mood Row",
"type": "n8n-nodes-base.dataTable",
"position": [
-128,
-256
],
"parameters": {
"columns": {
"value": {
"date": "={{ $('Set Mood Data').item.json.date }}",
"hour": "={{ $('Set Mood Data').item.json.hour }}",
"mood": "={{ $('Set Mood Data').item.json.mood }}",
"note": "={{ $('Set Mood Data').item.json.note }}"
},
"schema": [
{
"id": "date",
"type": "string",
"required": false,
"displayName": "date"
},
{
"id": "hour",
"type": "string",
"required": false,
"displayName": "hour"
},
{
"id": "mood",
"type": "string",
"required": false,
"displayName": "mood"
},
{
"id": "note",
"type": "string",
"required": false,
"displayName": "note"
}
],
"mappingMode": "defineBelow",
"matchingColumns": []
},
"options": {},
"dataTableId": {
"__rl": true,
"mode": "id",
"value": ""
}
},
"typeVersion": 1
},
{
"id": "7348155b-62fd-499e-ac16-1120d27683a6",
"name": "List Rows (Weekly)",
"type": "n8n-nodes-base.dataTable",
"position": [
-416,
32
],
"parameters": {
"operation": "get",
"returnAll": true,
"dataTableId": {
"__rl": true,
"mode": "id",
"value": ""
}
},
"typeVersion": 1
},
{
"id": "bb67d067-2f38-4c6a-b160-0892f24a081a",
"name": "Aggregate (7d)",
"type": "n8n-nodes-base.code",
"position": [
-208,
32
],
"parameters": {
"jsCode": "const now = new Date();\nconst start = new Date(now.getTime() - 7*24*60*60*1000);\n\nfunction parseDate(d){ const [Y,M,D] = String(d||'').split('-').map(Number); return new Date(Y,(M-1),D); }\nconst score = m => m==='\ud83d\ude42'?2 : m==='\ud83d\ude10'?1 : 0;\n\nconst rows = items.map(i=>i.json).filter(r => {\n const dt = parseDate(r.date);\n return dt && dt >= start && dt <= now;\n});\n\nconst counts = {'\ud83d\ude42':0,'\ud83d\ude10':0,'\ud83d\ude29':0};\nlet sum = 0;\nfor (const r of rows) { counts[r.mood] = (counts[r.mood]||0)+1; sum += score(r.mood); }\n\nconst n = rows.length || 1;\nconst avg = sum / n;\nconst label = avg >= 1.5 ? 'positive \ud83d\ude42' : avg >= 0.75 ? 'neutral \ud83d\ude10' : 'low \ud83d\ude29';\n\n// mini-barras\nconst maxv = Math.max(counts['\ud83d\ude42'], counts['\ud83d\ude10'], counts['\ud83d\ude29'], 1);\nconst bar = v => '\u2588'.repeat(Math.round(v ? (10 * v / maxv) : 0));\nconst chart = [\n `\ud83d\ude42 ${counts['\ud83d\ude42']} ${bar(counts['\ud83d\ude42'])}`,\n `\ud83d\ude10 ${counts['\ud83d\ude10']} ${bar(counts['\ud83d\ude10'])}`,\n `\ud83d\ude29 ${counts['\ud83d\ude29']} ${bar(counts['\ud83d\ude29'])}`,\n].join('\\n');\n\nconst summary = [\n 'Resumen semanal (\u00faltimos 7 d\u00edas)',\n `Registros: ${rows.length}`,\n `Promedio: ${avg.toFixed(2)} (${label})`,\n '',\n chart\n].join('\\n');\n\nreturn [{ json: { summary, counts, avg, label, rows } }];"
},
"typeVersion": 2
},
{
"id": "04669175-8e1c-4e59-bd22-55b115a795a5",
"name": "List Rows (Monthly)",
"type": "n8n-nodes-base.dataTable",
"position": [
-416,
336
],
"parameters": {
"operation": "get",
"returnAll": true,
"dataTableId": {
"__rl": true,
"mode": "id",
"value": ""
}
},
"typeVersion": 1
},
{
"id": "e96febbe-fe2c-4337-b4c7-47baea124dd2",
"name": "Aggregate (~30d)",
"type": "n8n-nodes-base.code",
"position": [
-208,
336
],
"parameters": {
"jsCode": "const now = new Date();\nconst start = new Date(now.getTime() - 30*24*60*60*1000);\n\nfunction parseDate(d){ const [Y,M,D] = String(d||'').split('-').map(Number); return new Date(Y,(M-1),D); }\nconst score = m => m==='\ud83d\ude42'?2 : m==='\ud83d\ude10'?1 : 0;\n\nconst rows = items.map(i=>i.json).filter(r => {\n const dt = parseDate(r.date);\n return dt && dt >= start && dt <= now;\n});\n\nconst counts = {'\ud83d\ude42':0,'\ud83d\ude10':0,'\ud83d\ude29':0};\nlet sum = 0;\nfor (const r of rows) { counts[r.mood] = (counts[r.mood]||0)+1; sum += score(r.mood); }\n\nconst n = rows.length || 1;\nconst avg = sum / n;\nconst label = avg >= 1.5 ? 'positive \ud83d\ude42' : avg >= 0.75 ? 'neutral \ud83d\ude10' : 'low \ud83d\ude29';\n\nconst maxv = Math.max(counts['\ud83d\ude42'], counts['\ud83d\ude10'], counts['\ud83d\ude29'], 1);\nconst bar = v => '\u2588'.repeat(Math.round(v ? (10 * v / maxv) : 0));\nconst chart = [\n `\ud83d\ude42 ${counts['\ud83d\ude42']} ${bar(counts['\ud83d\ude42'])}`,\n `\ud83d\ude10 ${counts['\ud83d\ude10']} ${bar(counts['\ud83d\ude10'])}`,\n `\ud83d\ude29 ${counts['\ud83d\ude29']} ${bar(counts['\ud83d\ude29'])}`,\n].join('\\n');\n\nconst summary = [\n 'Resumen mensual (\u00faltimos ~30 d\u00edas)',\n `Registros: ${rows.length}`,\n `Promedio: ${avg.toFixed(2)} (${label})`,\n '',\n chart\n].join('\\n');\n\nreturn [{ json: { summary, counts, avg, label, rows } }];"
},
"typeVersion": 2
},
{
"id": "7221f78e-7303-42bb-a4f2-c49a472c989f",
"name": "Sticky Note - Registro",
"type": "n8n-nodes-base.stickyNote",
"position": [
-704,
-368
],
"parameters": {
"color": 4,
"width": 1120,
"height": 280,
"content": "## MOOD LOG\nWebhook POST /mood receives mood and optional note"
},
"typeVersion": 1
},
{
"id": "4ffe2f6a-1ea9-429a-9c3a-70f377246a95",
"name": "Sticky Note - Weekly",
"type": "n8n-nodes-base.stickyNote",
"position": [
-704,
-64
],
"parameters": {
"color": 5,
"width": 1120,
"height": 280,
"content": "## WEEKLY SUMMARY\nSundays 8:00 PM - Analysis of the last 7 days"
},
"typeVersion": 1
},
{
"id": "ae23549f-9342-4b82-86cb-c5c59b13de5c",
"name": "Sticky Note - Monthly",
"type": "n8n-nodes-base.stickyNote",
"position": [
-704,
240
],
"parameters": {
"color": 6,
"width": 1120,
"height": 280,
"content": "## MONTHLY SUMMARY\nDay 1 of the month 8:00 AM - Analysis of the last 30 days"
},
"typeVersion": 1
},
{
"id": "9eea882b-927d-4935-b5b8-b94c04f4a0ad",
"name": "Respond to Webhook1",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
176,
-256
],
"parameters": {
"options": {},
"respondWith": "json",
"responseBody": "={{ {\"message\": \"Emotional state saved. Come back tomorrow \ud83d\udc4c\"} }}"
},
"typeVersion": 1.1
},
{
"id": "f45adf5f-4f2b-43c7-8c28-748bfa3d3973",
"name": "Schedule Weekly (SUNDAY 20:00)",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-640,
32
],
"parameters": {
"rule": {
"interval": [
{
"field": "weeks",
"triggerAtDay": [],
"triggerAtHour": 20
}
]
}
},
"typeVersion": 1.2
},
{
"id": "3c0fa2c0-e20e-4dc3-8946-8abc92d7473f",
"name": "Schedule Monthly (1th, 08:00)",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-640,
336
],
"parameters": {
"rule": {
"interval": [
{
"field": "months",
"triggerAtHour": 8
}
]
}
},
"typeVersion": 1.2
},
{
"id": "6bce607d-5319-4b14-af97-765bcd74280c",
"name": "ChatGPT Weekly Analysis",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
-48,
32
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4o"
},
"options": {},
"messages": {
"values": [
{
"content": "=Analyze these moods from the past 7 days and generate a summary with trends, potential triggers (based on 'note'), and 3 actionable recommendations. Keep it short and sweet.\n\n{{ $json.summary }}\n\nFull data:\n{{ JSON.stringify($json.rows) }}"
}
]
}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.8
},
{
"id": "d55980d6-cdae-414e-8b4b-e38e3c0cfa12",
"name": "ChatGPT Monthly Analysis",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
-48,
336
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4o"
},
"options": {},
"messages": {
"values": [
{
"content": "=Analyze my moods from the past month. Summarize trends, notable days/times, correlations between 'note' and mood, and 3 specific habits to try this month. Be specific.\n\n{{ $json.summary }}\n\nFull data:\n{{ JSON.stringify($json.rows) }}"
}
]
}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.8
},
{
"id": "30ad84b4-7bb0-4258-a6ff-eed7c9862c8e",
"name": "Gmail (Weekly)",
"type": "n8n-nodes-base.gmail",
"position": [
256,
32
],
"parameters": {
"sendTo": "user@example.com",
"message": "=Automatic summary (text + graphic):\n\n{{ $('Aggregate (7d)').item.json.summary }}\n\n---\n\nAI Analysis:\n\n{{ $json.message.content }}",
"options": {},
"subject": "Weekly Mood Summary"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "17a60bc3-02f1-402b-8971-9a0de69982a6",
"name": "Gmail (Monthly)",
"type": "n8n-nodes-base.gmail",
"position": [
256,
336
],
"parameters": {
"sendTo": "user@example.com",
"message": "=Automatic summary (text + graphic):\n\n{{ $('Aggregate (~30d)').item.json.summary }}\n\n---\n\nAI Analysis:\n\n{{ $json.message.content }}",
"options": {},
"subject": "Monthly Mood Summary"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "f595c545-2c3f-4aa1-8902-da8052702bfc",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1328,
-288
],
"parameters": {
"width": 544,
"height": 144,
"content": "## MOOD LOG\nWebhook POST /mood receives mood and optional note.\n\u26a0\ufe0f Configure your own Data Table ID in the \"Insert Mood Row\" node before running the workflow.\n"
},
"typeVersion": 1
}
],
"connections": {
"Set Mood Data": {
"main": [
[
{
"node": "Insert Mood Row",
"type": "main",
"index": 0
}
]
]
},
"Aggregate (7d)": {
"main": [
[
{
"node": "ChatGPT Weekly Analysis",
"type": "main",
"index": 0
}
]
]
},
"Webhook - Mood": {
"main": [
[
{
"node": "Set Mood Data",
"type": "main",
"index": 0
}
]
]
},
"Insert Mood Row": {
"main": [
[
{
"node": "Respond to Webhook1",
"type": "main",
"index": 0
}
]
]
},
"Aggregate (~30d)": {
"main": [
[
{
"node": "ChatGPT Monthly Analysis",
"type": "main",
"index": 0
}
]
]
},
"List Rows (Weekly)": {
"main": [
[
{
"node": "Aggregate (7d)",
"type": "main",
"index": 0
}
]
]
},
"List Rows (Monthly)": {
"main": [
[
{
"node": "Aggregate (~30d)",
"type": "main",
"index": 0
}
]
]
},
"ChatGPT Weekly Analysis": {
"main": [
[
{
"node": "Gmail (Weekly)",
"type": "main",
"index": 0
}
]
]
},
"ChatGPT Monthly Analysis": {
"main": [
[
{
"node": "Gmail (Monthly)",
"type": "main",
"index": 0
}
]
]
},
"Schedule Monthly (1th, 08:00)": {
"main": [
[
{
"node": "List Rows (Monthly)",
"type": "main",
"index": 0
}
]
]
},
"Schedule Weekly (SUNDAY 20:00)": {
"main": [
[
{
"node": "List Rows (Weekly)",
"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.
gmailOAuth2openAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Track your daily mood in one tap and receive automated AI summaries of your emotional trends every week and month. Perfect for self-reflection, wellness tracking, or personal analytics.
Source: https://n8n.io/workflows/10188/ — 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 acts as an AI-powered smart time tracker for employees or personal use. It records work sessions via a webhook, logs start/end/break times into n8n Data Tables, and uses OpenAI to automa
Eu Clara – Funil Kiwify Completo. Uses postgres, openAi, httpRequest, gmail. Webhook trigger; 70 nodes.
User Signup & Verification: The workflow starts when a user signs up. It generates a verification code and sends it via SMS using Twilio. Code Validation: The user replies with the code. The workflow
Instantly map all internal URLs, perform AI-powered (ChatGPT) analysis, and deliver results in HTML via webhook, Google Sheets, or email. All from your own n8n instance!
Watch on Youtube▶️