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 →
{
"name": "REFI-04 SendGrid Event Tracking",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "sendgrid-events",
"options": {
"rawBody": true
}
},
"id": "webhook",
"name": "SendGrid Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [
250,
300
]
},
{
"parameters": {
"jsCode": "// Parse SendGrid events and extract contact info\nconst events = $input.all();\nconst results = [];\n\nfor (const item of events) {\n const body = item.json.body || item.json;\n \n // SendGrid sends array of events\n const eventList = Array.isArray(body) ? body : [body];\n \n for (const event of eventList) {\n const contactId = event.contact_id || \n (event.custom_args && event.custom_args.contact_id);\n const campaign = event.campaign || \n (event.custom_args && event.custom_args.campaign);\n const emailId = event.email_id || \n (event.custom_args && event.custom_args.email_id);\n \n if (!contactId) continue;\n \n let scoreChange = 0;\n let tag = null;\n let urgency = 'normal';\n \n switch(event.event) {\n case 'open':\n scoreChange = 5;\n tag = 'refi-email-opened';\n break;\n case 'click':\n scoreChange = 10;\n tag = 'refi-email-clicked';\n \n // Check for intent in URL\n const url = event.url || '';\n if (url.includes('intent=lower-rate')) {\n tag = 'interested-lower-rate';\n scoreChange = 25;\n urgency = 'high';\n } else if (url.includes('intent=cash-out')) {\n tag = 'interested-cash-out';\n scoreChange = 25;\n urgency = 'high';\n } else if (url.includes('intent=debt-consol')) {\n tag = 'interested-debt-consol';\n scoreChange = 25;\n urgency = 'high';\n }\n break;\n case 'delivered':\n scoreChange = 0;\n break;\n case 'bounce':\n case 'dropped':\n tag = 'refi-email-failed';\n break;\n case 'unsubscribe':\n tag = 'unsubscribed';\n break;\n }\n \n if (contactId && (scoreChange > 0 || tag)) {\n results.push({\n contact_id: contactId,\n event_type: event.event,\n score_change: scoreChange,\n tag: tag,\n urgency: urgency,\n campaign: campaign,\n email_id: emailId,\n url: event.url,\n timestamp: event.timestamp || new Date().toISOString()\n });\n }\n }\n}\n\nreturn results.map(r => ({ json: r }));"
},
"id": "parse-events",
"name": "Parse SendGrid Events",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
450,
300
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "has-tag",
"leftValue": "={{ $json.tag }}",
"rightValue": "",
"operator": {
"type": "string",
"operation": "isNotEmpty"
}
}
],
"combinator": "and"
}
},
"id": "has-tag",
"name": "Has Tag to Add?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
650,
300
]
},
{
"parameters": {
"method": "POST",
"url": "=https://services.leadconnectorhq.com/contacts/{{ $json.contact_id }}/tags",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer {{ $env.GHL_API_KEY }}"
},
{
"name": "Version",
"value": "2021-07-28"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={ \"tags\": [\"{{ $json.tag }}\"] }"
},
"id": "add-tag-ghl",
"name": "Add Tag to GHL Contact",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
850,
200
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "is-intent",
"leftValue": "={{ $json.urgency }}",
"rightValue": "high",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
}
},
"id": "is-intent-click",
"name": "Is Intent Click?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
850,
400
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/sendMessage",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"chat_id\": \"{{ $env.TELEGRAM_CHAT_ID }}\",\n \"text\": \"\ud83d\udd25 REFI INTENT CLICK\\n\\nContact: {{ $json.contact_id }}\\nIntent: {{ $json.tag }}\\nScore: +{{ $json.score_change }} pts\\n\\nFollow up ASAP!\",\n \"parse_mode\": \"HTML\"\n}"
},
"id": "telegram-alert",
"name": "Send Telegram Alert",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
1050,
350
]
},
{
"parameters": {
"method": "GET",
"url": "=https://services.leadconnectorhq.com/contacts/{{ $json.contact_id }}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer {{ $env.GHL_API_KEY }}"
},
{
"name": "Version",
"value": "2021-07-28"
}
]
}
},
"id": "get-contact-for-email",
"name": "Get Contact for Email Alert",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
1050,
450
]
},
{
"parameters": {
"jsCode": "// Build email alert for team\nconst contact = $input.first().json.contact;\nconst eventData = $('Has Tag to Add?').first().json;\n\nconst intentLabels = {\n 'interested-lower-rate': 'Lower Monthly Payment',\n 'interested-cash-out': 'Cash Out / Home Equity',\n 'interested-debt-consol': 'Debt Consolidation'\n};\n\nconst intentLabel = intentLabels[eventData.tag] || eventData.tag;\n\nconst htmlBody = `\n<div style=\"font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;\">\n <div style=\"background: #8E4585; color: white; padding: 20px; text-align: center;\">\n <h1 style=\"margin: 0;\">\ud83d\udd25 HOT LEAD ALERT</h1>\n </div>\n <div style=\"padding: 20px; background: #f9f9f9;\">\n <table style=\"width: 100%; border-collapse: collapse;\">\n <tr>\n <td style=\"padding: 10px; border-bottom: 1px solid #ddd;\"><strong>Contact:</strong></td>\n <td style=\"padding: 10px; border-bottom: 1px solid #ddd;\">${contact.firstName || ''} ${contact.lastName || ''}</td>\n </tr>\n <tr>\n <td style=\"padding: 10px; border-bottom: 1px solid #ddd;\"><strong>Email:</strong></td>\n <td style=\"padding: 10px; border-bottom: 1px solid #ddd;\">${contact.email || 'N/A'}</td>\n </tr>\n <tr>\n <td style=\"padding: 10px; border-bottom: 1px solid #ddd;\"><strong>Phone:</strong></td>\n <td style=\"padding: 10px; border-bottom: 1px solid #ddd;\">${contact.phone || contact.mobilePhone || 'N/A'}</td>\n </tr>\n <tr style=\"background: #FFF3CD;\">\n <td style=\"padding: 10px; border-bottom: 1px solid #ddd;\"><strong>Intent:</strong></td>\n <td style=\"padding: 10px; border-bottom: 1px solid #ddd; font-weight: bold; color: #8E4585;\">${intentLabel}</td>\n </tr>\n <tr>\n <td style=\"padding: 10px; border-bottom: 1px solid #ddd;\"><strong>Lead Score:</strong></td>\n <td style=\"padding: 10px; border-bottom: 1px solid #ddd;\">+${eventData.score_change} points</td>\n </tr>\n <tr>\n <td style=\"padding: 10px;\"><strong>Campaign:</strong></td>\n <td style=\"padding: 10px;\">refi-jan26</td>\n </tr>\n </table>\n \n <div style=\"background: #8E4585; color: white; padding: 15px; margin-top: 20px; text-align: center;\">\n <strong>\u23f0 CALL WITHIN 1 HOUR</strong>\n </div>\n \n <p style=\"margin-top: 20px; font-size: 12px; color: #666;\">\n This lead clicked an intent link in the refinance campaign email.<br>\n They have shown HIGH INTEREST and should be contacted immediately.\n </p>\n </div>\n <div style=\"padding: 10px; text-align: center; font-size: 11px; color: #999;\">\n Sent via MortgageArchitect AI\n </div>\n</div>\n`;\n\nreturn [{\n json: {\n contact_id: contact.id,\n contact_name: `${contact.firstName || ''} ${contact.lastName || ''}`.trim(),\n contact_email: contact.email,\n contact_phone: contact.phone || contact.mobilePhone,\n intent: intentLabel,\n email_html: htmlBody,\n email_subject: `\ud83d\udd25 HOT LEAD: ${contact.firstName || 'Contact'} interested in ${intentLabel}`\n }\n}];"
},
"id": "build-email-alert",
"name": "Build Email Alert",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1250,
450
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.sendgrid.com/v3/mail/send",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer {{ $env.SENDGRID_API_KEY }}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"personalizations\": [{\n \"to\": [{\"email\": \"rmgsales@ccm.com\", \"name\": \"ROC Sales Team\"}]\n }],\n \"from\": {\"email\": \"info@rochomeloans.com\", \"name\": \"ROC Home Loans\"},\n \"reply_to\": {\"email\": \"roc@ccm.com\"},\n \"subject\": \"{{ $json.email_subject }}\",\n \"content\": [{\"type\": \"text/html\", \"value\": {{ JSON.stringify($json.email_html) }}}]\n}"
},
"id": "send-email-alert",
"name": "Send Email Alert to Team",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
1450,
450
]
},
{
"parameters": {
"jsCode": "// Build SMS message for Zapier-RingCentral\nconst data = $('Has Tag to Add?').first().json;\n\nconst smsTemplates = {\n 'interested-lower-rate': `Hey! Saw you're interested in lowering your rate. Many clients are saving $200-500/month. Text me a photo of your mortgage statement for a quick quote OR reply CALL ME. - Yauvan (617) 595-2500`,\n 'interested-cash-out': `Hey! Looking to tap into your home equity? Your home has likely gained value. Text me your statement for a same-day quote OR reply CALL ME. - Yauvan (617) 595-2500`,\n 'interested-debt-consol': `Hey! Consolidating debt into your mortgage can save thousands. Text your statement OR credit card statements. Reply CALL ME for analysis. - Yauvan (617) 595-2500`\n};\n\nreturn [{\n json: {\n contact_id: data.contact_id,\n sms_message: smsTemplates[data.tag] || 'Thanks for your interest! Reply CALL ME to chat. - Yauvan',\n tag: data.tag,\n intent_type: data.tag.replace('interested-', ''),\n campaign: 'refi-jan26'\n }\n}];"
},
"id": "build-sms",
"name": "Build SMS Message",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1050,
550
]
},
{
"parameters": {
"method": "GET",
"url": "=https://services.leadconnectorhq.com/contacts/{{ $json.contact_id }}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer {{ $env.GHL_API_KEY }}"
},
{
"name": "Version",
"value": "2021-07-28"
}
]
}
},
"id": "get-contact-phone",
"name": "Get Contact Phone from GHL",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
1250,
550
]
},
{
"parameters": {
"jsCode": "// Merge contact phone with SMS message\nconst contact = $input.first().json.contact;\nconst smsData = $('Build SMS Message').first().json;\n\nreturn [{\n json: {\n to_phone: contact.phone || contact.mobilePhone,\n to_name: contact.firstName || 'Friend',\n message: smsData.sms_message,\n contact_id: smsData.contact_id,\n intent_type: smsData.intent_type,\n campaign: smsData.campaign\n }\n}];"
},
"id": "merge-phone-sms",
"name": "Merge Phone with SMS",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1450,
550
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $env.ZAPIER_RINGCENTRAL_SMS_WEBHOOK }}",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"to_phone\": \"{{ $json.to_phone }}\",\n \"to_name\": \"{{ $json.to_name }}\",\n \"message\": \"{{ $json.message }}\",\n \"contact_id\": \"{{ $json.contact_id }}\",\n \"campaign\": \"{{ $json.campaign }}\",\n \"intent_type\": \"{{ $json.intent_type }}\"\n}"
},
"id": "send-sms-zapier",
"name": "Send SMS via Zapier-RingCentral",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
1650,
550
]
}
],
"connections": {
"SendGrid Webhook": {
"main": [
[
{
"node": "Parse SendGrid Events",
"type": "main",
"index": 0
}
]
]
},
"Parse SendGrid Events": {
"main": [
[
{
"node": "Has Tag to Add?",
"type": "main",
"index": 0
}
]
]
},
"Has Tag to Add?": {
"main": [
[
{
"node": "Add Tag to GHL Contact",
"type": "main",
"index": 0
}
],
[]
]
},
"Add Tag to GHL Contact": {
"main": [
[
{
"node": "Is Intent Click?",
"type": "main",
"index": 0
}
]
]
},
"Is Intent Click?": {
"main": [
[
{
"node": "Send Telegram Alert",
"type": "main",
"index": 0
},
{
"node": "Get Contact for Email Alert",
"type": "main",
"index": 0
},
{
"node": "Build SMS Message",
"type": "main",
"index": 0
}
],
[]
]
},
"Get Contact for Email Alert": {
"main": [
[
{
"node": "Build Email Alert",
"type": "main",
"index": 0
}
]
]
},
"Build Email Alert": {
"main": [
[
{
"node": "Send Email Alert to Team",
"type": "main",
"index": 0
}
]
]
},
"Build SMS Message": {
"main": [
[
{
"node": "Get Contact Phone from GHL",
"type": "main",
"index": 0
}
]
]
},
"Get Contact Phone from GHL": {
"main": [
[
{
"node": "Merge Phone with SMS",
"type": "main",
"index": 0
}
]
]
},
"Merge Phone with SMS": {
"main": [
[
{
"node": "Send SMS via Zapier-RingCentral",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"tags": [
{
"name": "refi-campaign"
},
{
"name": "sendgrid"
}
]
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
REFI-04 SendGrid Event Tracking. Uses httpRequest. Webhook trigger; 13 nodes.
Source: https://gist.github.com/TheArchitectAI/aef16ca117799ffe877d0423cb22abb5 — 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.
Automate WhatsApp communication for recruitment agencies with an interactive, structured customer experience. This workflow handles pricing inquiries, request submissions, tracking, complaints, and hu
Hectelion | Evaluation d'entreprise. Uses googleDrive, httpRequest, microsoftOutlook, googleSheets. Webhook trigger; 64 nodes.
Hectelion | NDA. Uses googleSheets, googleDrive, httpRequest, microsoftOutlook. Webhook trigger; 50 nodes.
This template turns Podium's conversation inbox into a full sales CRM with a custom funnel, AI message classification, automated drip follow-ups, daily admin reports, and a live Kanban dashboard. Six
Suspicious_login_detection. Uses postgres, httpRequest, noOp, html. Webhook trigger; 43 nodes.