This workflow corresponds to n8n.io template #12970 — we link there as the canonical source.
This workflow follows the Gmail → Google Calendar 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": "DXiv1-EoPCc1WF_bu2HtN",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Pipedrive ops Automation",
"tags": [],
"nodes": [
{
"id": "64122695-fa8e-4ec4-a42a-b1a202aaf878",
"name": "Pipedrive Trigger",
"type": "n8n-nodes-base.pipedriveTrigger",
"position": [
-224,
-80
],
"parameters": {
"action": "change",
"entity": "deal"
},
"credentials": {
"pipedriveApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.1
},
{
"id": "975975ef-6f2d-43e1-b5a3-8ef60c341cad",
"name": "If stage_id is 2 (Meeting Booking)",
"type": "n8n-nodes-base.if",
"position": [
336,
-80
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "1a105ae5-c46e-4944-b52d-397df278451b",
"operator": {
"type": "number",
"operation": "equals"
},
"leftValue": "={{ $json.data.stage_id }}",
"rightValue": 2
}
]
}
},
"typeVersion": 2.3
},
{
"id": "0b2beda2-b359-4b9d-8fc2-df5d3ea86b02",
"name": "Extract deal info",
"type": "n8n-nodes-base.pipedrive",
"position": [
608,
-96
],
"parameters": {
"dealId": "={{ $json.data.id }}",
"operation": "get"
},
"credentials": {
"pipedriveApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "497631e8-b052-4aa6-819c-deee380e838c",
"name": "Wait untill the SDR submit the google meeting link from Deals in pipedrive",
"type": "n8n-nodes-base.wait",
"position": [
48,
-80
],
"parameters": {
"amount": 55
},
"typeVersion": 1.1
},
{
"id": "0a0c1391-e27a-480c-a523-e2a81dad253a",
"name": "Get meeting link URL, Start time and end time",
"type": "n8n-nodes-base.set",
"position": [
848,
-80
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "3f5fe3ad-0666-43ac-9ba9-2c888265f128",
"name": "person_id.name",
"type": "string",
"value": "={{ $json.person_id.name }}"
},
{
"id": "48c88d30-e6c2-4e50-9750-a90ad4be5f98",
"name": "person_id.email[0].value",
"type": "string",
"value": "={{ $json.person_id.email[0].value }}"
},
{
"id": "30eb4e8f-0957-4cf2-b78f-cde2cd5b5e1c",
"name": "next_activity.conference_meeting_url",
"type": "string",
"value": "={{ $json.next_activity.conference_meeting_url }}"
},
{
"id": "d330ae4f-f91c-4b29-b33c-e7dfe53dffc3",
"name": "next_activity.due_date",
"type": "string",
"value": "={{ $json.next_activity.due_date }}"
},
{
"id": "e5f3d69a-c89b-499f-a9e0-5219f404296b",
"name": "next_activity.due_time",
"type": "string",
"value": "={{ `${$json.next_activity.due_date}T${$json.next_activity.due_time}:00` }}"
},
{
"id": "b057e612-b578-42bc-a28c-de9968607230",
"name": "StartTime",
"type": "string",
"value": "={{\n (() => {\n const d = String($json.next_activity?.due_date ?? '');\n const tRaw = String($json.next_activity?.due_time ?? '');\n\n // If it's already a full ISO datetime\n if (tRaw.includes('T')) {\n return DateTime.fromISO(tRaw).setZone('Asia/Dubai').toISO();\n }\n\n // If it's only HH:mm or HH:mm:ss\n const t = tRaw.length === 5 ? `${tRaw}:00` : tRaw;\n return DateTime.fromISO(`${d}T${t}`).setZone('Asia/Dubai').toISO();\n })()\n}}"
},
{
"id": "3061579c-e7e1-4392-a2c7-e68751198ecd",
"name": "EndTime",
"type": "string",
"value": "={{\n (() => {\n const d = String($json.next_activity?.due_date ?? '');\n const tRaw = String($json.next_activity?.due_time ?? '');\n\n const start = tRaw.includes('T')\n ? DateTime.fromISO(tRaw).setZone('Asia/Dubai')\n : DateTime.fromISO(`${d}T${tRaw.length === 5 ? `${tRaw}:00` : tRaw}`).setZone('Asia/Dubai');\n\n const parts = String($json.next_activity?.duration ?? '00:00').split(':').map(Number);\n const hours = parts[0] || 0;\n const minutes = parts[1] || 0;\n\n return start.plus({ hours, minutes }).toISO();\n })()\n}}"
},
{
"id": "b613460b-b5fd-40b1-a21e-327b61c9b9c9",
"name": "org_id.name",
"type": "string",
"value": "={{ $json.org_id.name }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "0040dbb2-b40d-4eed-a56a-92efbed26b6b",
"name": "Create a meeting and add you recipient",
"type": "n8n-nodes-base.googleCalendar",
"position": [
1104,
-80
],
"parameters": {
"end": "={{ $json.EndTime }}",
"start": "={{ $json.StartTime }}",
"calendar": {
"__rl": true,
"mode": "list",
"value": "user@example.com",
"cachedResultName": "user@example.com"
},
"additionalFields": {
"summary": "Test Google calnder",
"location": "={{ $json.next_activity.conference_meeting_url }}",
"attendees": [
"={{ $json.person_id.email[0].value }}"
]
}
},
"credentials": {
"googleCalendarOAuth2Api": {
"name": "<your credential>"
}
},
"executeOnce": false,
"typeVersion": 1.3
},
{
"id": "ccf90a17-6310-4a0b-910e-c0fdfa7c3fc6",
"name": "Send Email reminder to the client",
"type": "n8n-nodes-base.gmail",
"position": [
1376,
-80
],
"parameters": {
"sendTo": "={{ $('Get meeting link URL, Start time and end time').item.json.person_id.email[0].value }}",
"message": "=Hi {{ $('Get meeting link URL, Start time and end time').item.json.person_id.name }},\n\nHope this message finds you will.\n\nThis email regarding our online meeting to discuss more about our product.\n\nKindly find the meeting time at {{ DateTime.fromISO($json.start.dateTime).toFormat('dd LLL yyyy, hh:mm a') }}\n\nRegards,",
"options": {
"appendAttribution": false
},
"subject": "=Meeting Reminder:{{ $('Get meeting link URL, Start time and end time').item.json.next_activity.due_date }}"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "1d604557-2c58-47d2-8142-6f49de0a0582",
"name": "Send a reminder to SDR in specific channel",
"type": "n8n-nodes-base.slack",
"position": [
1648,
-80
],
"parameters": {
"text": "=Hi Ahmed, You have a meeting at {{ DateTime.fromISO($json.start.dateTime).toFormat('dd LLL yyyy, hh:mm a') }}.\n\nMeeting Link: {{ $('Create a meeting and add you recipient').item.json.location }}",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "C0AAP1C16S2",
"cachedResultName": "meetings-reminder"
},
"otherOptions": {},
"authentication": "oAuth2"
},
"credentials": {
"slackOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2.4
},
{
"id": "a9d13442-326b-4c6b-aad2-9f4fcc738eb4",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1056,
-640
],
"parameters": {
"color": 4,
"width": 608,
"height": 848,
"content": "## \ud83d\udccc Template Overview (Read Before Using)\n\n### What is it\n###### This template is a **Revenue Ops meeting automation** that connects Pipedrive, Google Calendar, Gmail, and Slack. \n\n###### When a deal reaches the *Meeting Booking* stage in Pipedrive, the workflow automatically schedules the meeting, confirms it with the client, and notifies the internal team. \n\n###### It is designed to eliminate manual coordination and reduce missed or forgotten meetings.\n\n\n---\n\n### How it works\n1. The workflow listens for **deal stage changes** in Pipedrive. \n2. It runs only when the deal enters the *Meeting Booking* stage. \n3. A short wait is applied to allow the SDR to add meeting details. \n4. Deal and activity data are extracted and time values are normalized. \n5. A meeting is created in Google Calendar with the client as an attendee. \n6. A confirmation email is sent to the client via Gmail. \n7. A reminder is posted in a Slack channel for the sales team.\n\n---\n\n### Setup steps\n1. Connect your **Pipedrive account** and confirm the correct stage ID for *Meeting Booking*. \n2. Ensure meeting details (date, time, duration, meeting link) are saved in the deal activity. \n3. Connect **Google Calendar** and select the calendar where meetings should be created. \n4. Connect **Gmail** and review the email message content. \n5. Connect **Slack** and choose the channel for internal reminders. \n6. Run the workflow once with test data to confirm timings and notifications are correct. \n7. Activate the workflow once validation is complete.\n"
},
"typeVersion": 1
},
{
"id": "99d05263-30a2-4026-bf07-2b3f88c083dd",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-320,
-368
],
"parameters": {
"height": 288,
"content": "### Pipedrive Trigger\n**Why it exists** \nListens for deal updates so automation runs only when sales activity actually happens.\n\n**You can change** \n- Pipeline ID \n- Stage ID (for example, use a different stage like *Demo Scheduled*) \n- Trigger entity (deal vs activity)"
},
"typeVersion": 1
},
{
"id": "a013bc6e-299f-4acd-8f40-03a54a0bb5d6",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-32,
-368
],
"parameters": {
"height": 288,
"content": "### Wait Node\n**Why it exists** \nPrevents the workflow from running before the SDR finishes adding meeting details.\n\n**You can change** \n- Wait time duration \n- Replace with a conditional check instead of time-based waiting \n- Remove it if meeting data is always available immediately\n"
},
"typeVersion": 1
},
{
"id": "1a9710be-3ee3-483f-9049-7dc7cc2be836",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
272,
-368
],
"parameters": {
"height": 288,
"content": "### IF Stage Check\n**Why it exists** \nEnsures the workflow only runs for qualified deals and avoids unwanted executions.\n\n**You can change** \n- Stage ID value \n- Add multiple allowed stages \n- Add extra conditions like deal value or owner"
},
"typeVersion": 1
},
{
"id": "36b626ca-e6ec-4a5a-ba8c-b057ebb2796c",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
560,
-368
],
"parameters": {
"width": 192,
"height": 288,
"content": "### Extract Deal Info\n**Why it exists** \nPulls complete and reliable data directly from Pipedrive.\n\n**You can change** \n- Fields extracted from the deal \n- Add custom fields \n- Include organization or owner data"
},
"typeVersion": 1
},
{
"id": "326b576a-bbac-429b-9f74-620b7f08836a",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
800,
-384
],
"parameters": {
"color": 7,
"width": 192,
"height": 304,
"content": "### Set / Transform Data\n**Why it exists** \nCleans and prepares data so downstream tools receive correct formats.\n\n**You can change** \n- Time zone \n- Date and time calculations \n- Field names for CRM or calendar compatibility"
},
"typeVersion": 1
},
{
"id": "cad73aba-39c6-4805-9d09-4b3c08475d54",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
1040,
-368
],
"parameters": {
"height": 304,
"content": "### Create Calendar Event\n**Why it exists** \nCreates a single source of truth for the meeting and avoids double booking.\n\n**You can change** \n- Calendar selection \n- Meeting title and description \n- Replace Google Calendar with Outlook"
},
"typeVersion": 1
},
{
"id": "ea6a5a07-2b41-4896-aa47-bd3c45f8b134",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
1328,
-352
],
"parameters": {
"width": 208,
"height": 288,
"content": "### Send Email Reminder\n**Why it exists** \nConfirms the meeting with the client and reduces no-shows.\n\n**You can change** \n- Email wording \n- Sender account \n- Add attachments or CC internal users"
},
"typeVersion": 1
},
{
"id": "67dae77d-ee29-4d2c-8b1a-d63056bc62ed",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
1584,
-352
],
"parameters": {
"width": 208,
"height": 288,
"content": "### Send Slack Notification\n**Why it exists** \nKeeps the sales team informed without checking the CRM.\n\n**You can change** \n- Target channel \n- Message format \n- Replace Slack with Microsoft Teams or Discord\n"
},
"typeVersion": 1
},
{
"id": "dbcbccf4-af3b-4228-bdcb-67a3bf998e55",
"name": "Sticky Note9",
"type": "n8n-nodes-base.stickyNote",
"position": [
112,
-1152
],
"parameters": {
"color": 7,
"width": 1008,
"height": 640,
"content": "## [Video Tutorial](https://youtu.be/Y1Odi7odMQQ)\n@[youtube](Y1Odi7odMQQ)"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"availableInMCP": false,
"executionOrder": "v1"
},
"versionId": "e21b692c-e58a-47d1-a71d-ec48dd187c80",
"connections": {
"Extract deal info": {
"main": [
[
{
"node": "Get meeting link URL, Start time and end time",
"type": "main",
"index": 0
}
]
]
},
"Pipedrive Trigger": {
"main": [
[
{
"node": "Wait untill the SDR submit the google meeting link from Deals in pipedrive",
"type": "main",
"index": 0
}
]
]
},
"Send Email reminder to the client": {
"main": [
[
{
"node": "Send a reminder to SDR in specific channel",
"type": "main",
"index": 0
}
]
]
},
"If stage_id is 2 (Meeting Booking)": {
"main": [
[
{
"node": "Extract deal info",
"type": "main",
"index": 0
}
]
]
},
"Create a meeting and add you recipient": {
"main": [
[
{
"node": "Send Email reminder to the client",
"type": "main",
"index": 0
}
]
]
},
"Get meeting link URL, Start time and end time": {
"main": [
[
{
"node": "Create a meeting and add you recipient",
"type": "main",
"index": 0
}
]
]
},
"Wait untill the SDR submit the google meeting link from Deals in pipedrive": {
"main": [
[
{
"node": "If stage_id is 2 (Meeting Booking)",
"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.
gmailOAuth2googleCalendarOAuth2ApipipedriveApislackOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
CRM Automation, Revenue Operations, Sales Operations, Meeting Automation
Source: https://n8n.io/workflows/12970/ — 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.
Sync your Google Calendar events with Google Sheets and get daily Slack summaries with meeting statistics. FEATURES:
Loxone MCP Client - Integration Hub. Uses start, googleCalendar, slack, mcp. Event-driven trigger; 20 nodes.
This n8n workflow transforms your HR department from reactive to proactive by automatically monitoring 5 critical employee timelines and generating smart alerts before deadlines hit. Data Input → Empl
This workflow streamlines your property tour scheduling into two main automated flows: 0. Form Trigger (Property Tour Request): 🚀 The workflow initiates immediately when a prospective client fills out
Payment Recovery. Uses stripeTrigger, highLevel, dataTable, googleCalendar. Event-driven trigger; 40 nodes.