Envío automático de recordatorios de renovación de clientes de GoHighLevel a Gmail y Slack

Avanzado

Este es unCRMflujo de automatización del dominio deautomatización que contiene 19 nodos.Utiliza principalmente nodos como If, Code, Gmail, Merge, Slack. Envío automático de recordatorios de renovación de clientes de GoHighLevel a Gmail, Slack y Google Sheets

Requisitos previos
  • Cuenta de Google y credenciales de API de Gmail
  • Bot Token de Slack o URL de Webhook
  • Credenciales de API de Google Sheets

Categoría

Vista previa del flujo de trabajo
Visualización de las conexiones entre nodos, con soporte para zoom y panorámica
Exportar flujo de trabajo
Copie la siguiente configuración JSON en n8n para importar y usar este flujo de trabajo
{
  "id": "zAhUYo1pPedFF2vq",
  "meta": {
    "instanceId": "8443f10082278c46aa5cf3acf8ff0f70061a2c58bce76efac814b16290845177",
    "templateCredsSetupCompleted": true
  },
  "name": "Automate Client Renewal Alerts from GoHighLevel to Gmail and Slack",
  "tags": [],
  "nodes": [
    {
      "id": "e89a6dcb-42d4-4674-bd3d-2f91b86231b2",
      "name": "Nota adhesiva",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3120,
        -64
      ],
      "parameters": {
        "color": 4,
        "width": 420,
        "height": 656,
        "content": "## 🔄 Client Retention Renewal Reminder Workflow\n\nAutomatically identifies clients with contracts expiring within 10 days and sends personalized renewal reminders.\n\n### What This Workflow Does:\n- **Runs daily at 9 AM** to check for expiring contracts\n- **Fetches all contacts** from GoHighLevel CRM\n- **Filters clients** whose contracts expire in 0-10 days\n- **Sends renewal emails** to clients via Gmail\n- **Notifies account managers** via Slack\n- **Logs all activities** to Google Sheets for tracking\n\n### Business Benefits:\n- ✅ Never miss a renewal opportunity\n- ✅ Improve client retention rates\n- ✅ Automate manual follow-up tasks\n- ✅ Track renewal campaign effectiveness\n\n### Requirements:\n- GoHighLevel account with custom fields:\n  - Contract End Date field\n  - Account Manager field\n- Gmail account for sending emails\n- Slack workspace for notifications\n- Google Sheets for logging"
      },
      "typeVersion": 1
    },
    {
      "id": "9ffba3e1-2389-47df-8257-708871c6c5e4",
      "name": "Nota adhesiva1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2656,
        -208
      ],
      "parameters": {
        "color": 5,
        "width": 280,
        "height": 240,
        "content": "## ⏰ Schedule Trigger Setup\n\nRuns daily at 9:00 AM server time.\n\n**Configuration:**\n- Cron: `0 9 * * *`\n- Frequency: Every day\n- Time: 9:00 AM\n\n**Why 9 AM?**\nEarly morning execution ensures:\n- Emails arrive during business hours\n- Account managers have full day to respond\n- Prevents weekend/holiday issues"
      },
      "typeVersion": 1
    },
    {
      "id": "94e0e170-fe29-42a6-9926-d052fbc28fd5",
      "name": "Programar diariamente a las 9 AM",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -2560,
        48
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 9 * * *"
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "05b63bb3-1942-4f24-9d53-3b3f2a25a7f5",
      "name": "Nota adhesiva2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2432,
        240
      ],
      "parameters": {
        "color": 5,
        "width": 280,
        "height": 396,
        "content": "## 📥 Fetch Contacts from CRM\n\n**Setup Instructions:**\n1. Connect your GoHighLevel account\n2. Set limit to 50 (or adjust based on needs)\n3. Ensure API permissions include contact read access\n\n**Required Custom Fields:**\n- Contract End Date (Date field)\n- Account Manager (Text field)\n\n**Note:** Increase limit if you have more than 50 active clients"
      },
      "typeVersion": 1
    },
    {
      "id": "5e3e0e62-267e-4728-a4ae-f92581607f06",
      "name": "Obtener contactos desde GoHighLevel",
      "type": "n8n-nodes-base.highLevel",
      "position": [
        -2336,
        48
      ],
      "parameters": {
        "filters": {},
        "options": {},
        "operation": "getAll",
        "requestOptions": {}
      },
      "credentials": {
        "highLevelOAuth2Api": {
          "id": "N9Q1X1RWUjvRIRbt",
          "name": "HighLevel account 2"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "9e665b65-003d-430d-a7f7-48228b7dcad8",
      "name": "Nota adhesiva3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2208,
        -272
      ],
      "parameters": {
        "color": 5,
        "width": 260,
        "height": 292,
        "content": "## 🔍 Validate Data Quality\n\nEnsures contacts have custom fields before processing.\n\n**Why This Matters:**\n- Prevents errors in downstream nodes\n- Filters out incomplete contact records\n- Improves workflow reliability"
      },
      "typeVersion": 1
    },
    {
      "id": "eb37756d-3de4-4d63-8215-b4e8520bcb5e",
      "name": "Verificar si tiene campos personalizados",
      "type": "n8n-nodes-base.if",
      "position": [
        -2112,
        48
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "58341a8d-2417-47e1-b29b-be575b270c35",
              "operator": {
                "type": "array",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.customFields }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "f102174e-cba7-4d13-a322-f2327d9f1449",
      "name": "Nota adhesiva4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1936,
        208
      ],
      "parameters": {
        "color": 5,
        "width": 280,
        "height": 404,
        "content": "## 🎯 Filter Expiring Contracts\n\n**Logic:**\n- Finds Contract End Date field\n- Calculates days until expiry\n- Filters: 0-10 days remaining\n\n**Customization:**\nChange `daysUntilExpiry <= 10` to adjust reminder window:\n- 7 days = 1 week notice\n- 14 days = 2 weeks notice\n- 30 days = 1 month notice\n\n**Important:** Update field IDs to match YOUR GoHighLevel custom fields"
      },
      "typeVersion": 1
    },
    {
      "id": "6f9a5a69-8ce9-46c1-88f2-d12a44a3f319",
      "name": "Filtrar código de renovaciones",
      "type": "n8n-nodes-base.code",
      "position": [
        -1888,
        48
      ],
      "parameters": {
        "jsCode": "// Get current date at midnight for accurate day comparison\nconst today = new Date();\ntoday.setHours(0, 0, 0, 0);\n\n// Array to store filtered contacts\nconst filteredContacts = [];\n\n// Process each contact from input\nfor (const contact of $input.all()) {\n  const item = contact.json;\n  \n  // Check if contact has customFields\n  if (!item.customFields || !Array.isArray(item.customFields)) {\n    continue;\n  }\n  \n  // TODO: Replace with YOUR custom field ID for Contract End Date\n  const contractEndField = item.customFields.find(\n    field => field.id === 'YOUR_CONTRACT_END_DATE_FIELD_ID'\n  );\n  \n  // Skip if no contract end date exists\n  if (!contractEndField || !contractEndField.value) {\n    continue;\n  }\n  \n  // Parse contract end date (timestamp in milliseconds)\n  const contractEndDate = new Date(contractEndField.value);\n  contractEndDate.setHours(0, 0, 0, 0);\n  \n  // Calculate days until expiry\n  const daysUntilExpiry = Math.ceil(\n    (contractEndDate - today) / (1000 * 60 * 60 * 24)\n  );\n  \n  // Filter: expires within next 10 days (0-10 days)\n  if (daysUntilExpiry >= 0 && daysUntilExpiry <= 10) {\n    \n    // TODO: Replace with YOUR custom field ID for Account Manager\n    const accountManagerField = item.customFields.find(\n      field => field.id === 'YOUR_ACCOUNT_MANAGER_FIELD_ID'\n    );\n    \n    // Format the contract end date for display\n    const formattedDate = contractEndDate.toLocaleDateString('en-US', {\n      year: 'numeric',\n      month: 'long',\n      day: 'numeric'\n    });\n    \n    // Create enriched contact object\n    filteredContacts.push({\n      json: {\n        // Original contact data\n        id: item.id,\n        contactName: item.contactName,\n        firstName: item.firstName || 'N/A',\n        lastName: item.lastName || 'N/A',\n        email: item.email || 'No email on file',\n        companyName: item.companyName || 'N/A',\n        phone: item.phone,\n        \n        // Contract information\n        contractEndDate: formattedDate,\n        contractEndDateRaw: contractEndDate.toISOString(),\n        contractEndTimestamp: contractEndField.value,\n        daysUntilExpiry: daysUntilExpiry,\n        \n        // Account manager info\n        accountManager: accountManagerField?.value || 'Unassigned',\n        \n        // Additional fields for workflow\n        allCustomFields: item.customFields,\n        tags: item.tags || [],\n        source: item.source\n      }\n    });\n  }\n}\n\n// Return filtered contacts\nreturn filteredContacts;"
      },
      "typeVersion": 2
    },
    {
      "id": "6f7a46e5-115c-4bef-9cc7-e30b96b1b94d",
      "name": "Verificar expiración en 10 días",
      "type": "n8n-nodes-base.filter",
      "position": [
        -1664,
        48
      ],
      "parameters": {
        "conditions": {
          "number": [
            {
              "value1": "={{ $json.daysUntilExpiry }}",
              "value2": 10,
              "operation": "smallerEqual"
            }
          ],
          "string": [
            {
              "value1": "={{ $json.contractEndDate }}",
              "operation": "isNotEmpty"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "3b9392da-852b-4692-bfac-5c177bbda695",
      "name": "Nota adhesiva5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1536,
        -400
      ],
      "parameters": {
        "color": 5,
        "width": 280,
        "height": 340,
        "content": "## 📧 Send Client Email\n\n**Setup:**\n1. Connect Gmail account\n2. Replace recipient with: `={{ $json.email }}`\n3. Customize email template\n\n**Email Variables:**\n- `firstName` - Client first name\n- `lastName` - Client last name\n- `contractEndDate` - Formatted expiry date\n- `companyName` - Company name\n\n**Best Practice:** Test email with your own address first"
      },
      "typeVersion": 1
    },
    {
      "id": "17f722d7-781c-41d4-bd15-b84b187df947",
      "name": "Enviar correo de renovación vía Gmail",
      "type": "n8n-nodes-base.gmail",
      "position": [
        -1440,
        -48
      ],
      "webhookId": "c62251a2-e50a-4f59-8e3e-d35403ca9d82",
      "parameters": {
        "sendTo": "={{ $json.email }}",
        "message": "=Hi {{ $json.firstName }} {{ $json.lastName }},\n\nThis is a friendly reminder that your contract with us is set to expire on {{ $json.contractEndDate }}.\n\nWe'd love to continue working with you! Please let us know if you'd like to discuss renewal options.\n\nYour account manager will be reaching out shortly.\n\nBest regards,\nYour Team",
        "options": {},
        "subject": "Important: Your Contract Renewal is Coming Up"
      },
      "typeVersion": 2.1
    },
    {
      "id": "3e716197-e31d-49d9-8c3e-b1ba215bed06",
      "name": "Nota adhesiva6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1488,
        304
      ],
      "parameters": {
        "color": 5,
        "width": 280,
        "height": 384,
        "content": "## 📢 Slack Team Notification\n\n**Setup:**\n1. Connect Slack workspace\n2. Select channel for renewal alerts\n3. Customize message format\n\n**Recommended Channels:**\n- #renewals\n- #account-management\n- #sales-alerts\n\n**Note:** Ensure all account managers have access to the selected channel"
      },
      "typeVersion": 1
    },
    {
      "id": "79b9f0dd-1fd1-4562-b93e-99e3bc111aeb",
      "name": "Enviar alerta de Slack al equipo",
      "type": "n8n-nodes-base.slack",
      "position": [
        -1440,
        144
      ],
      "webhookId": "2d02c3a0-61c7-4742-b2d5-665e3ad8dab8",
      "parameters": {
        "text": "=🔔 *Contract Renewal Alert*\n\n*Client:* {{ $json.firstName }} {{ $json.lastName }}\n*Email:* {{ $json.email }}\n*Company:* {{ $json.companyName || \"N/A\" }}\n*Contract Expires:* {{ $json.contractEndDate }}\n*Days Remaining:* {{ $json.daysUntilExpiry }}\n*Account Manager:* {{ $json.accountManager }}\n\n✅ Renewal email has been sent to client.\n📋 Please follow up within 3 business days.",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_SLACK_CHANNEL_ID",
          "cachedResultName": "Select your renewals channel"
        },
        "otherOptions": {}
      },
      "typeVersion": 2.1
    },
    {
      "id": "f3448850-b573-416a-b34c-8e1e7d985151",
      "name": "Combinar resultados de correo y Slack",
      "type": "n8n-nodes-base.merge",
      "position": [
        -1216,
        48
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combinationMode": "mergeByPosition"
      },
      "typeVersion": 2.1
    },
    {
      "id": "96ae9e61-3ffc-4f04-b6ac-2a58495dc455",
      "name": "Nota adhesiva7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1072,
        -272
      ],
      "parameters": {
        "color": 5,
        "width": 260,
        "height": 296,
        "content": "## 📊 Generate Summary Report\n\nCreates execution summary with:\n- Total reminders sent\n- Timestamp of execution\n- Success status\n\n**Used for:**\n- Tracking workflow performance\n- Logging to Google Sheets\n- Debugging issues"
      },
      "typeVersion": 1
    },
    {
      "id": "c61d0e08-0b24-4be6-bbcd-b58de927212a",
      "name": "Generar informe resumen",
      "type": "n8n-nodes-base.code",
      "position": [
        -992,
        48
      ],
      "parameters": {
        "jsCode": "const totalReminders = $input.all().length;\nconst timestamp = new Date().toLocaleString();\n\nreturn {\n  json: {\n    summary: `Renewal Reminder Workflow Completed`,\n    totalRemindersSent: totalReminders,\n    timestamp: timestamp,\n    message: `${totalReminders} renewal reminder(s) sent successfully on ${timestamp}`\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "9e39598a-d4f0-43e9-9885-a306371772e1",
      "name": "Nota adhesiva8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -752,
        256
      ],
      "parameters": {
        "color": 5,
        "width": 280,
        "height": 268,
        "content": "## 📝 Log to Google Sheets\n\n**Setup:**\n1. Create a Google Sheet for tracking\n2. Add columns: summary, totalRemindersSent, timestamp, message\n3. Connect your Google account\n4. Select your spreadsheet and sheet\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "ace3170b-c470-4458-b601-db08918f1572",
      "name": "Registrar resultados en Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -768,
        48
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [
            {
              "id": "summary",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "totalRemindersSent",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "totalRemindersSent",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "timestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "message",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "message",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "autoMapInputData",
          "matchingColumns": []
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "Sheet1",
          "cachedResultName": "Select sheet name"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID",
          "cachedResultName": "Select your tracking sheet"
        }
      },
      "typeVersion": 4.7
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "180a6f20-55ff-43e1-bbd0-85e6eebaf0bb",
  "connections": {
    "6f9a5a69-8ce9-46c1-88f2-d12a44a3f319": {
      "main": [
        [
          {
            "node": "6f7a46e5-115c-4bef-9cc7-e30b96b1b94d",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "94e0e170-fe29-42a6-9926-d052fbc28fd5": {
      "main": [
        [
          {
            "node": "5e3e0e62-267e-4728-a4ae-f92581607f06",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "eb37756d-3de4-4d63-8215-b4e8520bcb5e": {
      "main": [
        [
          {
            "node": "6f9a5a69-8ce9-46c1-88f2-d12a44a3f319",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "c61d0e08-0b24-4be6-bbcd-b58de927212a": {
      "main": [
        [
          {
            "node": "ace3170b-c470-4458-b601-db08918f1572",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "79b9f0dd-1fd1-4562-b93e-99e3bc111aeb": {
      "main": [
        [
          {
            "node": "f3448850-b573-416a-b34c-8e1e7d985151",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "17f722d7-781c-41d4-bd15-b84b187df947": {
      "main": [
        [
          {
            "node": "f3448850-b573-416a-b34c-8e1e7d985151",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "f3448850-b573-416a-b34c-8e1e7d985151": {
      "main": [
        [
          {
            "node": "c61d0e08-0b24-4be6-bbcd-b58de927212a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "6f7a46e5-115c-4bef-9cc7-e30b96b1b94d": {
      "main": [
        [
          {
            "node": "17f722d7-781c-41d4-bd15-b84b187df947",
            "type": "main",
            "index": 0
          },
          {
            "node": "79b9f0dd-1fd1-4562-b93e-99e3bc111aeb",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5e3e0e62-267e-4728-a4ae-f92581607f06": {
      "main": [
        [
          {
            "node": "eb37756d-3de4-4d63-8215-b4e8520bcb5e",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Preguntas frecuentes

¿Cómo usar este flujo de trabajo?

Copie el código de configuración JSON de arriba, cree un nuevo flujo de trabajo en su instancia de n8n y seleccione "Importar desde JSON", pegue la configuración y luego modifique la configuración de credenciales según sea necesario.

¿En qué escenarios es adecuado este flujo de trabajo?

Avanzado - CRM

¿Es de pago?

Este flujo de trabajo es completamente gratuito, puede importarlo y usarlo directamente. Sin embargo, tenga en cuenta que los servicios de terceros utilizados en el flujo de trabajo (como la API de OpenAI) pueden requerir un pago por su cuenta.

Información del flujo de trabajo
Nivel de dificultad
Avanzado
Número de nodos19
Categoría1
Tipos de nodos10
Descripción de la dificultad

Adecuado para usuarios avanzados, flujos de trabajo complejos con 16+ nodos

Autor
Rahul Joshi

Rahul Joshi

@rahul08

Rahul Joshi is a seasoned technology leader specializing in the n8n automation tool and AI-driven workflow automation. With deep expertise in building open-source workflow automation and self-hosted automation platforms, he helps organizations eliminate manual processes through intelligent n8n ai agent automation solutions.

Enlaces externos
Ver en n8n.io

Compartir este flujo de trabajo

Categorías

Categorías: 34