This workflow corresponds to n8n.io template #8823 — we link there as the canonical source.
This workflow follows the Agent → Gmail Trigger 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": "foRLAgU7DfocKDuI",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Gmail \u2192 Zendesk: AI-Enriched Ticketing with Urgency Prioritization + Sheets Logging",
"tags": [],
"nodes": [
{
"id": "da98ac4e-67b4-4719-96dc-82dd69dc323e",
"name": "Gmail Trigger",
"type": "n8n-nodes-base.gmailTrigger",
"position": [
0,
0
],
"parameters": {
"simple": false,
"filters": {
"labelIds": [
"Label_7215267856143431312"
]
},
"options": {},
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
}
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "f8d28ce5-3c4c-4ba3-9534-aaf8aa10a01a",
"name": "Create Zendesk Ticket",
"type": "n8n-nodes-base.zendesk",
"position": [
848,
0
],
"parameters": {
"description": "={{ $json.output.description }}",
"additionalFields": {
"tags": "={{ $json.output.priority }}",
"subject": "={{ $json.output.subject }}"
}
},
"credentials": {
"zendeskApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "b4b1f7a4-0a31-4cd5-bfa2-78b5596e0c86",
"name": "Format Sheet Data",
"type": "n8n-nodes-base.code",
"position": [
1072,
0
],
"parameters": {
"jsCode": "// Prepare data for Google Sheets logging\nconst inputData = $input.first().json;\nconst ticketData = $node[\"Create Zendesk Ticket\"].json;\n\n// Extract Zendesk subdomain from the API URL or construct the agent URL\nlet agentTicketUrl = '';\nif (ticketData.url) {\n // Extract subdomain from API URL (e.g., https://softwarecompany-66332.zendesk.com/api/v2/tickets/123.json)\n const urlMatch = ticketData.url.match(/https:\\/\\/(.*?)\\.zendesk\\.com/);\n if (urlMatch) {\n const subdomain = urlMatch[1];\n agentTicketUrl = `https://${subdomain}.zendesk.com/agent/tickets/${ticketData.id}`;\n } else {\n // Fallback: construct from ticket ID (replace 'your-subdomain' with actual subdomain)\n agentTicketUrl = `https://softwarecompany-66332.zendesk.com/agent/tickets/${ticketData.id}`;\n }\n} else {\n // Fallback if no URL is provided\n agentTicketUrl = `https://softwarecompany-66332.zendesk.com/agent/tickets/${ticketData.id}`;\n}\n\nreturn {\n ticket_id: ticketData.id,\n ticket_url: agentTicketUrl,\n api_url: ticketData.url, // Keep original API URL for reference\n subject: ticketData.subject,\n requester_name: inputData.requester_name,\n requester_email: inputData.requester_email,\n source_channel: inputData.source,\n original_id: inputData.original_id,\n priority: ticketData.priority,\n status: ticketData.status,\n created_timestamp: new Date().toISOString(),\n zendesk_created_at: ticketData.created_at,\n description_preview: inputData.description.substring(0, 100) + (inputData.description.length > 100 ? '...' : ''),\n tags: ticketData.tags ? ticketData.tags.join(', ') : ''\n};"
},
"typeVersion": 2
},
{
"id": "80545193-9805-41f2-9a3d-a2740d943650",
"name": "Normalize Gmail Data",
"type": "n8n-nodes-base.code",
"position": [
224,
0
],
"parameters": {
"jsCode": "// Normalize data from Gmail\nif ($input.first().json.source === undefined) {\n const gmailData = $input.first().json;\n \n // Extract email and name from the 'from' object structure\n let requesterEmail = '';\n let requesterName = '';\n \n if (gmailData.from && gmailData.from.value && gmailData.from.value[0]) {\n requesterEmail = gmailData.from.value[0].address || '';\n requesterName = gmailData.from.value[0].name || gmailData.from.value[0].address || '';\n }\n \n // Use plain text first, fallback to textAsHtml if text not available, avoid html\n let description = '';\n if (gmailData.text) {\n description = gmailData.text;\n } else if (gmailData.textAsHtml) {\n // Strip HTML tags from textAsHtml to get plain text\n description = gmailData.textAsHtml.replace(/<[^>]*>/g, '').replace(/'/g, \"'\").replace(/"/g, '\"').replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&');\n } else {\n description = 'No description provided';\n }\n \n // Check if it's urgent based on subject or content\n const isUrgent = (gmailData.subject && gmailData.subject.toLowerCase().includes('urgent')) || \n (description && description.toLowerCase().includes('urgent'));\n \n return {\n source: 'gmail',\n subject: gmailData.subject || 'No Subject',\n description: description,\n requester_email: requesterEmail,\n requester_name: requesterName,\n priority: isUrgent ? 'urgent' : 'normal',\n timestamp: new Date().toISOString(),\n original_id: gmailData.id,\n raw_data: gmailData\n };\n}\n\nreturn $input.first().json;"
},
"typeVersion": 2
},
{
"id": "863bd681-6a7d-464c-a3d4-29df6459f531",
"name": "Azure OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatAzureOpenAi",
"position": [
480,
224
],
"parameters": {
"model": "gpt-4o-mini",
"options": {}
},
"credentials": {
"azureOpenAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "d5ff38ae-3b60-4517-9a3f-a725787d5d1e",
"name": "Structured Output Parser",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
608,
224
],
"parameters": {
"jsonSchemaExample": "{\n\t\"subject\": \" \",\n\t\"description\": \" \",\n \"priority\": \"normal\"\n}"
},
"typeVersion": 1.3
},
{
"id": "cb6a9454-90e1-47da-8a72-a4ccc2892d63",
"name": "Log to Google Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
1296,
0
],
"parameters": {
"columns": {
"value": {
"Tags": "={{ $json.tags }}",
"Status": "={{ $json.status }}",
"Subject": "={{ $json.subject }}",
"Priority": "={{ $json.priority }}",
"Ticket ID": "={{ $json.ticket_id }}",
"Ticket URL": "={{ $json.ticket_url }}",
"Created Timestamp": "={{ $json.created_timestamp }}",
"Zendesk Created At": "={{ $json.zendesk_created_at }}",
"Description Preview": "={{ $json.description_preview }}"
},
"schema": [
{
"id": "Ticket ID",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Ticket ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Ticket URL",
"type": "string",
"display": true,
"required": false,
"displayName": "Ticket URL",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Subject",
"type": "string",
"display": true,
"required": false,
"displayName": "Subject",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Requester Name",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Requester Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Requester Email",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Requester Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Source Channel",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Source Channel",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Original ID",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Original ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Priority",
"type": "string",
"display": true,
"required": false,
"displayName": "Priority",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Status",
"type": "string",
"display": true,
"required": false,
"displayName": "Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Created Timestamp",
"type": "string",
"display": true,
"required": false,
"displayName": "Created Timestamp",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Zendesk Created At",
"type": "string",
"display": true,
"required": false,
"displayName": "Zendesk Created At",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Description Preview",
"type": "string",
"display": true,
"required": false,
"displayName": "Description Preview",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Tags",
"type": "string",
"display": true,
"required": false,
"displayName": "Tags",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Ticket ID"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1pz1aP0OIULFoEJCI6VWged3jq1W7870btV2QOC4vn1o/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1pz1aP0OIULFoEJCI6VWged3jq1W7870btV2QOC4vn1o",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1pz1aP0OIULFoEJCI6VWged3jq1W7870btV2QOC4vn1o/edit?usp=drivesdk",
"cachedResultName": "zendesk tickets"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4
},
{
"id": "90b394e5-2c06-4465-b297-d2dea19809b2",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-352,
-32
],
"parameters": {
"height": 192,
"content": "## Gmail Trigger\nWatches a specified Gmail inbox/label for new messages. Captures sender, subject, timestamp, thread ID, and raw body/HTML for downstream processing and urgency assessment."
},
"typeVersion": 1
},
{
"id": "78578cb1-e1aa-4ed9-bc49-378ab0ae414c",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
144,
-288
],
"parameters": {
"height": 240,
"content": "## Normalize Gmail Data\nCleans and standardizes the incoming email: strips signatures/quotes, extracts plain text, detects language, and maps fields (from, to, cc, subject, body, attachments) into a consistent schema for AI parsing and prioritization."
},
"typeVersion": 1
},
{
"id": "cf4a6d75-f9f9-430a-ad4c-b138aecdcdd4",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
496,
384
],
"parameters": {
"height": 256,
"content": "## Chat Model\nUses Azure OpenAI to analyze the normalized email and produce structured insights: issue summary, category, requested action, and an urgency score/class (Critical/High/Medium/Low) based on keywords, sender context, timestamps, and SLA hints."
},
"typeVersion": 1
},
{
"id": "7ace00b5-95a6-47b1-bc15-0cc406997363",
"name": "AI Agent for Task Prioritization",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
448,
0
],
"parameters": {
"text": "=You are an assistant that converts incoming emails into task metadata.\n\nInputs:\n- email_subject: string\n- email_description: string (can include bullet points, deadlines, owners)\n\nGoals:\nFrom the inputs, produce:\n1) task_subject: A clear, action-oriented subject (\u2264120 chars), preserving critical keywords from email_subject.\n2) task_description: A concise, well-structured description (3\u20138 bullet points). Include scope, deliverables, due date/time if present, owners/reviewers, and any channels/tools mentioned. Preserve key details without adding new facts.\n3) task_priority: One of [\"urgent\",\"normal\"] using these rules:\n - \"urgent\" if the email includes explicit urgency or near-term deadlines (e.g., \"today\", \"tomorrow\", \"<=48h\", \"ASAP\", \"urgent\", \"immediately\") or high-impact incidents/outages.\n - Otherwise \"normal\".\n\nStyle:\n- Use crisp, professional language.\n- Normalize whitespace and fix obvious typos.\n- Do not invent data.\n\n\nNow process:\nemail_subject = \"{{ $json.subject }}\"\nemail_description = \"{{ $json.description }}\"",
"options": {},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 2.1
},
{
"id": "889ec0b1-e694-41ff-add2-e24046960316",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
768,
-304
],
"parameters": {
"height": 256,
"content": "## Create Zendesk Ticket\nCreates a Zendesk ticket using the structured data: requester, subject, description, tags, and priority set from urgency classification (Critical \u2192 urgent, High \u2192 high, etc.). Adds category and SLA hints to custom fields."
},
"typeVersion": 1
},
{
"id": "073e6228-e9c2-433f-a5b4-5519c149ce3e",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
992,
176
],
"parameters": {
"height": 192,
"content": "## Format Sheet Data\nPrepares a clean row for Google Sheets: received_at, sender, subject, summary, category, priority_by_urgency, zendesk_ticket_id, status, and processing time. Normalizes values for consistent reporting."
},
"typeVersion": 1
},
{
"id": "c836b9fb-2153-41ae-9517-29c24e166792",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
1248,
-288
],
"parameters": {
"height": 208,
"content": "## Log to Google Sheets\nAppends or updates the tracking sheet with each processed email and its urgency priority. Enables auditing, SLA monitoring, and trend analysis across tickets."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "d011873d-949e-46cc-a604-f7a866270079",
"connections": {
"Gmail Trigger": {
"main": [
[
{
"node": "Normalize Gmail Data",
"type": "main",
"index": 0
}
]
]
},
"Format Sheet Data": {
"main": [
[
{
"node": "Log to Google Sheets",
"type": "main",
"index": 0
}
]
]
},
"Normalize Gmail Data": {
"main": [
[
{
"node": "AI Agent for Task Prioritization",
"type": "main",
"index": 0
}
]
]
},
"Create Zendesk Ticket": {
"main": [
[
{
"node": "Format Sheet Data",
"type": "main",
"index": 0
}
]
]
},
"Azure OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Agent for Task Prioritization",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Structured Output Parser": {
"ai_outputParser": [
[
{
"node": "AI Agent for Task Prioritization",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"AI Agent for Task Prioritization": {
"main": [
[
{
"node": "Create Zendesk Ticket",
"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.
azureOpenAiApigmailOAuth2googleSheetsOAuth2ApizendeskApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Turn incoming Gmail messages into structured Zendesk tickets, enriched by Azure OpenAI, and log key details to Google Sheets for tracking. Ideal for IT Support teams needing fast, consistent intake and documentation. ⚡ Fetches new emails via Gmail Trigger. ✉️ Normalizes Gmail…
Source: https://n8n.io/workflows/8823/ — 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 intelligently analyzes incoming Gmail emails, classifies intent using GPT-4, and sends real-time Slack notifications while logging structured data into Google Sheets. It provides a smart
CV → Match → Screen → Decide, all automated
Enterprise-grade resume screening automation built for production environments. This workflow combines intelligent AI analysis with comprehensive error handling to ensure reliable processing of candid
This n8n workflow automates email management by classifying incoming messages, drafting replies, and sending alerts—all powered by AI.
This workflow automates invoice processing directly from your email inbox.