{
  "id": "JRe4TvueoMMH4FVd",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Create Zendesk Tickets from Gmail and Log to Google Sheets with Gmail, Zendesk, and Google Sheets",
  "tags": [],
  "nodes": [
    {
      "id": "b03d5eff-2f3b-4e15-a51e-23eb72c9e75c",
      "name": "Gmail Trigger",
      "type": "n8n-nodes-base.gmailTrigger",
      "position": [
        0,
        -192
      ],
      "parameters": {
        "simple": false,
        "filters": {
          "labelIds": [
            "Label_7215267856143431312"
          ]
        },
        "options": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        }
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "85a31be9-8035-4b6c-b929-ef4f67888658",
      "name": "Create Zendesk Ticket",
      "type": "n8n-nodes-base.zendesk",
      "position": [
        432,
        -192
      ],
      "parameters": {
        "description": "={{ $json.description }}",
        "additionalFields": {
          "tags": "={{ $json.priority }}",
          "subject": "={{ $json.subject }}"
        }
      },
      "credentials": {
        "zendeskApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "581ccd96-d11d-436d-86d4-a4162da65f32",
      "name": "Format Sheet Data",
      "type": "n8n-nodes-base.code",
      "position": [
        656,
        -192
      ],
      "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": "076cea59-4b20-40b8-ab61-61c23c0e5b42",
      "name": "Log to Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        880,
        -192
      ],
      "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": "033dae10-a4ed-435c-9fcf-67c911603189",
      "name": "Normalize Gmail Data",
      "type": "n8n-nodes-base.code",
      "position": [
        208,
        -192
      ],
      "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(/&apos;/g, \"'\").replace(/&quot;/g, '\"').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&amp;/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": "4543e98f-003c-43ab-8638-24c5e7e4f3e8",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -352,
        -240
      ],
      "parameters": {
        "width": 272,
        "height": 208,
        "content": "## Gmail Trigger\nListens for new emails from the configured Gmail account/label and emits each message once with headers, subject, body (plain/HTML), sender, recipients, timestamp, and attachment metadata for downstream processing."
      },
      "typeVersion": 1
    },
    {
      "id": "895dac87-ef0d-4285-9dcb-5573ad09a273",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        96,
        -480
      ],
      "parameters": {
        "width": 272,
        "height": 208,
        "content": "## Normalize Gmail Data\nTransforms the raw Gmail payload into a consistent schema (e.g., requesterEmail, subject, bodyText/bodyHtml, threadId, messageId, labels, attachments[]) to ensure reliable field mapping across subsequent nodes."
      },
      "typeVersion": 1
    },
    {
      "id": "6c123420-9b3e-403e-81cd-1f731406156e",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        352,
        -16
      ],
      "parameters": {
        "width": 272,
        "height": 224,
        "content": "## Create Zendesk Ticket (create: ticket)\nCreates a Zendesk ticket using normalized fields: requester (email), subject, description (plain text or HTML), optional priority/tags/group/assignee. Outputs ticketId, ticketUrl, status, and requesterId for logging."
      },
      "typeVersion": 1
    },
    {
      "id": "c9671dc8-391d-4579-a6b9-853946c169b5",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        560,
        -496
      ],
      "parameters": {
        "width": 272,
        "height": 224,
        "content": "## Format Sheet Data\nBuilds a tidy row object combining Gmail and Zendesk outputs (e.g., timestamp, requesterEmail, subject, ticketId, ticketUrl, status, threadId, labels, workflowRunId). Ensures column order and default values match the Sheet schema."
      },
      "typeVersion": 1
    },
    {
      "id": "dff72fb5-c0cb-478e-b9a9-5bde17971ecf",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        800,
        -16
      ],
      "parameters": {
        "width": 272,
        "height": 224,
        "content": "## Log to Google Sheets \nWrites the row to the target spreadsheet\u2014appending new records or updating existing ones using a unique key (e.g., messageId or ticketId). Confirms success and surfaces any write conflicts or missing columns."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "4c9e7438-d87c-45ec-b738-a12e69424dc7",
  "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": "Create Zendesk Ticket",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Zendesk Ticket": {
      "main": [
        [
          {
            "node": "Format Sheet Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}