This workflow corresponds to n8n.io template #13521 β we link there as the canonical source.
This workflow follows the Gmail β Google Sheets 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": "oPfF3svbkGBXTp2J",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Transform Your Employee Leave Sheet into a Smart Alert System",
"tags": [],
"nodes": [
{
"id": "generated-6ace5735-9c46-454a-aef7-196487beb8d3",
"name": "Holiday Workflow Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
-592,
-496
],
"parameters": {
"width": 518,
"height": 664,
"content": "## Workflow Overview\n\n### How it works \n\nThis workflow automatically manages employee leave notifications based on a central Google Sheet. Every day at a scheduled time, it checks whether any employee\u2019s leave period has started or ended. If a leave period begins, the workflow sends a notification to a designated Slack channel and sends a reminder email to the employee to update their Slack status and availability. Once processed, the employee\u2019s status in the sheet is marked as \u201cActive\u201d to prevent duplicate notifications.\n\nWhen a leave period ends, the workflow detects it automatically. It posts an update to the same Slack channel and sends a \u201cWelcome Back\u201d reminder email to the employee. The sheet is then updated to mark the leave as \u201cInactive.\u201d All processing happens sequentially to avoid API limits and ensure reliability.\n\nThis automation is designed to be safe for shared environments. It does not modify user Slack profiles or Gmail settings directly. Instead, it sends reminders and keeps HR or operations teams informed through Slack notifications.\n\n### Setup Instructions\n\nConnect your Google Sheets OAuth2 credential.\n\nConnect your Slack OAuth2 credential.\n\nConnect your Gmail OAuth2 credential.\n"
}
},
{
"id": "generated-80e8e821-a933-4601-8b0a-6d3af492e1a0",
"name": "Daily Leave Check Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
144,
64
],
"parameters": {
"rule": {
"values": [],
"interval": [
{
"triggerAtHour": 8
}
]
}
}
},
{
"id": "c5d33038-aba0-497b-9aaf-2fdb19b47f1c",
"name": "Fetch Leave Records",
"type": "n8n-nodes-base.googleSheets",
"position": [
352,
64
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": 273133283,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1bqwC7pOQE_szyOD9yNZXa3edVmeqH6UoT00vPM12xR8/edit#gid=273133283",
"cachedResultName": "dummy leave data"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1bqwC7pOQE_szyOD9yNZXa3edVmeqH6UoT00vPM12xR8",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1bqwC7pOQE_szyOD9yNZXa3edVmeqH6UoT00vPM12xR8/edit?usp=drivesdk",
"cachedResultName": "Employee Leave Records1"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"retryOnFail": true,
"typeVersion": 4.7
},
{
"id": "44ed6649-3b28-43d4-9ea1-604c51e46b0b",
"name": "Validate & Normalize Leave Data",
"type": "n8n-nodes-base.code",
"position": [
576,
64
],
"parameters": {
"jsCode": "const today = new Date();\ntoday.setHours(0,0,0,0);\n\nreturn items\n .map(item => {\n const email = item.json[\"Employee Email\"];\n const name = item.json[\"Name\"];\n const startRaw = item.json[\"Start Date\"];\n const endRaw = item.json[\"End Date\"];\n const status = item.json[\"Status\"] || \"Inactive\";\n\n // Validate required fields\n if (!email || !startRaw || !endRaw) {\n return null;\n }\n\n const startDate = new Date(startRaw);\n const endDate = new Date(endRaw);\n\n // Normalize time\n startDate.setHours(0,0,0,0);\n endDate.setHours(0,0,0,0);\n\n if (isNaN(startDate) || isNaN(endDate)) {\n return null;\n }\n\n const isWithinLeave = today >= startDate && today <= endDate;\n const isLeaveEnded = today > endDate;\n\n return {\n json: {\n email,\n name,\n startDate: startDate.toISOString().split(\"T\")[0],\n endDate: endDate.toISOString().split(\"T\")[0],\n returnDate: endDate.toISOString().split(\"T\")[0],\n currentStatus: status,\n today: today.toISOString().split(\"T\")[0],\n isWithinLeave,\n isLeaveEnded,\n needsActivation: isWithinLeave && status !== \"Active\",\n needsReset: isLeaveEnded && status === \"Active\"\n }\n };\n })\n .filter(item => item !== null);\n"
},
"typeVersion": 2
},
{
"id": "generated-baa5999e-cb81-460b-975f-8e53e0c7627b",
"name": "Check Needs Activation",
"type": "n8n-nodes-base.if",
"position": [
928,
64
],
"parameters": {
"options": {
"ignoreCase": true,
"looseTypeValidation": true
},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": false,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "4e3b451e-dc0e-4b65-9e7e-7153d3238634",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{$json.needsActivation}}",
"rightValue": ""
}
]
}
}
},
{
"id": "18952c94-d843-44f8-9ca5-dc89917dafb7",
"name": "Check Needs Reset",
"type": "n8n-nodes-base.if",
"position": [
1104,
288
],
"parameters": {
"options": {
"ignoreCase": true
},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": false,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "4e3b451e-dc0e-4b65-9e7e-7153d3238634",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{$json.needsReset}}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.3
},
{
"id": "b53131b4-d779-4483-b0ce-ce5f1d7ec28f",
"name": "Process Activations Sequentially",
"type": "n8n-nodes-base.splitInBatches",
"position": [
1296,
16
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "1f73b0d8-bee5-49e8-bfad-3e3f2f237409",
"name": "Notify HR Channel",
"type": "n8n-nodes-base.slack",
"position": [
1584,
32
],
"parameters": {
"text": "=\ud83d\udcc5 Leave Activated\n\nEmployee: {{$json.name}}\nEmail: {{$json.email}}\nLeave Period: {{$json.startDate}} \u2192 {{$json.endDate}}\n\nReminder email sent to employee.",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "C09L70CVDL3",
"cachedResultName": "alerting-channel"
},
"otherOptions": {},
"authentication": "oAuth2"
},
"credentials": {
"slackOAuth2Api": {
"name": "<your credential>"
}
},
"retryOnFail": true,
"typeVersion": 2.4
},
{
"id": "84e16891-9f27-4447-9dfe-15f62f61d0b0",
"name": "Send OOO Reminder Email",
"type": "n8n-nodes-base.gmail",
"position": [
1792,
32
],
"parameters": {
"sendTo": "={{ \"forreferal04@gmail.com\" || !$('Process Activations Sequentially').item.json.email }}",
"message": "=Hi {{$('Process Activations Sequentially').item.json.name}},\n\nOur records show your leave from {{$('Process Activations Sequentially').item.json.startDate}} to {{$('Process Activations Sequentially').item.json.endDate}}.\n\nPlease make sure to:\n\u2022 Update your Slack status to \"Out of Office\"\n\u2022 Inform your team if needed\n\nRegards,\nHR Automation System",
"options": {},
"subject": "=Leave Reminder \u2013 Please Enable Out of Office"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"retryOnFail": true,
"typeVersion": 2.2
},
{
"id": "2b00a36a-857e-42e7-a798-5460fd639373",
"name": "Process Resets Sequentially",
"type": "n8n-nodes-base.splitInBatches",
"position": [
1392,
272
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "5e70ba30-ba79-4701-9b5b-f7acc759cd3d",
"name": "Notify HR Leave Reset",
"type": "n8n-nodes-base.slack",
"position": [
1680,
288
],
"parameters": {
"text": "=\ud83d\udd04 Leave Completed\n\nEmployee: {{$json.name}}\nEmail: {{$json.email}}\nLeave Period: {{$json.startDate}} \u2192 {{$json.endDate}}\n\nEmployee has returned from leave.\nStatus reset automatically.",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "C09L70CVDL3",
"cachedResultName": "alerting-channel"
},
"otherOptions": {},
"authentication": "oAuth2"
},
"credentials": {
"slackOAuth2Api": {
"name": "<your credential>"
}
},
"retryOnFail": true,
"typeVersion": 2.4
},
{
"id": "c9207def-24de-49cd-b012-42b83302c648",
"name": "Send Welcome Back Email",
"type": "n8n-nodes-base.gmail",
"position": [
1888,
288
],
"parameters": {
"sendTo": "={{ \"forreferal04@gmail.com\" || !$('Process Resets Sequentially').item.json.email }}",
"message": "=Hi {{$('Process Resets Sequentially').item.json.name}},\n\nOur records show your leave ended on {{$('Process Resets Sequentially').item.json.endDate}}.\n\nWelcome Back !!\n\nHave a productive day!\n\nHR Leave Automation System",
"options": {},
"subject": "=Welcome Back \u2013 Leave Completed"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"retryOnFail": true,
"typeVersion": 2.2
},
{
"id": "2d6c5d35-a7a2-4208-8233-efaf14be065a",
"name": "Mark Leave As Inactive",
"type": "n8n-nodes-base.googleSheets",
"position": [
2112,
288
],
"parameters": {
"columns": {
"value": {
"Status": "={{ \"Inactive\" }}",
"Last Updated": "={{ $('Process Resets Sequentially').item.json.today }}",
"Employee Email": "={{ $('Process Resets Sequentially').item.json.email }}"
},
"schema": [
{
"id": "Employee Email",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Employee Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Name",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Start Date",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Start Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "End Date",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "End Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Status",
"type": "string",
"display": true,
"required": false,
"displayName": "Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Last Updated",
"type": "string",
"display": true,
"required": false,
"displayName": "Last Updated",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "row_number",
"type": "number",
"display": true,
"removed": true,
"readOnly": true,
"required": false,
"displayName": "row_number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Employee Email"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 273133283,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1bqwC7pOQE_szyOD9yNZXa3edVmeqH6UoT00vPM12xR8/edit#gid=273133283",
"cachedResultName": "dummy leave data"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1bqwC7pOQE_szyOD9yNZXa3edVmeqH6UoT00vPM12xR8",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1bqwC7pOQE_szyOD9yNZXa3edVmeqH6UoT00vPM12xR8/edit?usp=drivesdk",
"cachedResultName": "Employee Leave Records1"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"retryOnFail": true,
"typeVersion": 4.7
},
{
"id": "07b1bdf9-8ed4-444a-b2c8-ff9ba89c71f7",
"name": "Mark Leave as Active",
"type": "n8n-nodes-base.googleSheets",
"position": [
2016,
32
],
"parameters": {
"columns": {
"value": {
"Status": "={{ \"Active\" }}",
"Last Updated": "={{ $('Process Activations Sequentially').item.json.today }}",
"Employee Email": "={{ $('Process Activations Sequentially').item.json.email }}"
},
"schema": [
{
"id": "Employee Email",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Employee Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Name",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Start Date",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Start Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "End Date",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "End Date",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Status",
"type": "string",
"display": true,
"required": false,
"displayName": "Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Last Updated",
"type": "string",
"display": true,
"required": false,
"displayName": "Last Updated",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "row_number",
"type": "number",
"display": true,
"removed": true,
"readOnly": true,
"required": false,
"displayName": "row_number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Employee Email"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 273133283,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1bqwC7pOQE_szyOD9yNZXa3edVmeqH6UoT00vPM12xR8/edit#gid=273133283",
"cachedResultName": "dummy leave data"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1bqwC7pOQE_szyOD9yNZXa3edVmeqH6UoT00vPM12xR8",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1bqwC7pOQE_szyOD9yNZXa3edVmeqH6UoT00vPM12xR8/edit?usp=drivesdk",
"cachedResultName": "Employee Leave Records1"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"retryOnFail": true,
"typeVersion": 4.7
},
{
"id": "ecf90988-0392-4baf-96fe-1f7231651c7c",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
864,
-128
],
"parameters": {
"color": 7,
"width": 1360,
"height": 384,
"content": "Handles employees whose leave starts today. Sends Slack notification, emails reminder, updates sheet status, and prevents duplicate activations."
},
"typeVersion": 1
},
{
"id": "6c36d41d-6c25-4249-9f25-44ca1a123fcd",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
1040,
272
],
"parameters": {
"color": 7,
"width": 1264,
"height": 352,
"content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nHandles employees whose leave has ended. Sends return notification, emails reminder, and resets status to inactive in the sheet."
},
"typeVersion": 1
},
{
"id": "54ffe19f-2914-4561-b209-2bf5493623c6",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
96,
-80
],
"parameters": {
"color": 7,
"width": 752,
"height": 368,
"content": "Triggers daily execution, loads configuration values, reads leave records from Google Sheets, validates inputs, and calculates activation and reset conditions."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "270ca519-f458-4f77-96cc-c4a8f7f358d0",
"connections": {
"Check Needs Reset": {
"main": [
[
{
"node": "Process Resets Sequentially",
"type": "main",
"index": 0
}
]
]
},
"Notify HR Channel": {
"main": [
[
{
"node": "Send OOO Reminder Email",
"type": "main",
"index": 0
}
]
]
},
"Fetch Leave Records": {
"main": [
[
{
"node": "Validate & Normalize Leave Data",
"type": "main",
"index": 0
}
]
]
},
"Mark Leave as Active": {
"main": [
[
{
"node": "Process Activations Sequentially",
"type": "main",
"index": 0
}
]
]
},
"Notify HR Leave Reset": {
"main": [
[
{
"node": "Send Welcome Back Email",
"type": "main",
"index": 0
}
]
]
},
"Check Needs Activation": {
"main": [
[
{
"node": "Process Activations Sequentially",
"type": "main",
"index": 0
}
],
[
{
"node": "Check Needs Reset",
"type": "main",
"index": 0
}
]
]
},
"Mark Leave As Inactive": {
"main": [
[
{
"node": "Process Resets Sequentially",
"type": "main",
"index": 0
}
]
]
},
"Send OOO Reminder Email": {
"main": [
[
{
"node": "Mark Leave as Active",
"type": "main",
"index": 0
}
]
]
},
"Send Welcome Back Email": {
"main": [
[
{
"node": "Mark Leave As Inactive",
"type": "main",
"index": 0
}
]
]
},
"Daily Leave Check Trigger": {
"main": [
[
{
"node": "Fetch Leave Records",
"type": "main",
"index": 0
}
]
]
},
"Process Resets Sequentially": {
"main": [
[],
[
{
"node": "Notify HR Leave Reset",
"type": "main",
"index": 0
}
]
]
},
"Validate & Normalize Leave Data": {
"main": [
[
{
"node": "Check Needs Activation",
"type": "main",
"index": 0
}
]
]
},
"Process Activations Sequentially": {
"main": [
[],
[
{
"node": "Notify HR Channel",
"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.
gmailOAuth2googleSheetsOAuth2ApislackOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Automate employee leave tracking and communication with structured notifications and reminders π π£. This workflow checks a centralized Google Sheet daily to detect when leave periods start or end. When leave begins, it notifies your HR Slack channel and reminds the employee toβ¦
Source: https://n8n.io/workflows/13521/ β original creator credit. Request a take-down β
More Email & Gmail workflows β Β· Browse all categories β
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow automatically scans AWS accounts for orphaned resources (unattached EBS volumes, old snapshots >90 days, unassociated Elastic IPs) that waste money. It calculates cost impact, validat
Streamline IT and operations change management by automating approval routing, Jira issue creation, audit logging, and real-time Slack alerts. This workflow ensures faster reviews, traceable approvals
Streamline IT and operations change management by automating approval routing, Jira issue creation, audit logging, and real-time Slack alerts. This workflow ensures faster reviews, traceable approvals
Automate your GoHighLevel (GHL) pipeline tracking and deal management process. This workflow fetches all opportunities, calculates the time spent in each stage, logs historical pipeline data in Google
Automatically consolidate Zendesk and Freshdesk ticket data into a unified performance dashboard with KPI calculations, Google Sheets logging, real-time Slack alerts, and weekly Gmail email reports. P