{
  "name": "Lead Follow-Up Automator",
  "nodes": [
    {
      "parameters": {
        "content": "## Lead Follow-Up Automator\nA demo workflow by FlowForge AI. Test it by sending a POST request to the webhook with `name`, `email`, and optional `source` fields.",
        "height": 180,
        "width": 340,
        "color": 4
      },
      "id": "7c3a8dcb-3cc6-4ffb-9f39-1cb5695a9001",
      "name": "Demo Overview",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -460,
        -340
      ]
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "lead-followup-automator",
        "responseMode": "lastNode",
        "responseData": "firstEntryJson",
        "options": {
          "responseCode": 200,
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "application/json"
              }
            ]
          }
        }
      },
      "id": "a0c9d861-3223-4f19-b27d-1bdb6c2ee001",
      "name": "Webhook Trigger",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        -240,
        40
      ],
      "webhookId": "7f8d4fe0-ec7c-4334-8f42-307d9f386b0e"
    },
    {
      "parameters": {
        "content": "## 1. Webhook Trigger\nReceives lead submissions from any form or test request. Expected JSON: `{ \"name\": \"Ada Lovelace\", \"email\": \"ada@example.com\", \"source\": \"Website\" }`.",
        "height": 190,
        "width": 330,
        "color": 7
      },
      "id": "6465c4c9-306a-4759-a629-4b8d31a45001",
      "name": "Webhook Note",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -360,
        230
      ]
    },
    {
      "parameters": {
        "jsCode": "const incoming = $input.first().json;\nconst body = incoming.body ?? incoming;\nconst name = String(body.name ?? body.Name ?? '').trim();\nconst email = String(body.email ?? body.Email ?? '').trim();\nconst source = String(body.source ?? body.Source ?? 'Website form').trim();\n\nif (!name || !email) {\n  return [{\n    json: {\n      status: 'error',\n      error: {\n        node: 'Normalize Lead',\n        message: 'Missing required fields: name and email are required.'\n      },\n      receivedAt: new Date().toISOString(),\n      rawLead: body\n    }\n  }];\n}\n\nreturn [{\n  json: {\n    Name: name,\n    Email: email,\n    Date: new Date().toISOString(),\n    Source: source,\n    status: 'ready'\n  }\n}];"
      },
      "id": "b5e38541-369e-4261-95e8-9133b34d8001",
      "name": "Normalize Lead",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        20,
        40
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose",
            "version": 2
          },
          "conditions": [
            {
              "id": "valid-lead-status",
              "leftValue": "={{ $json.status }}",
              "rightValue": "ready",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "11a19cb1-8d4c-44fd-9ca0-c2fe097fc001",
      "name": "Lead Data Valid?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        280,
        40
      ]
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "resource": "sheet",
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "YOUR_GOOGLE_SHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Leads",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Name": "={{ $json.Name }}",
            "Email": "={{ $json.Email }}",
            "Date": "={{ $json.Date }}",
            "Source": "={{ $json.Source }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "Name",
              "displayName": "Name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "Email",
              "displayName": "Email",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "Date",
              "displayName": "Date",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "Source",
              "displayName": "Source",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "id": "c356c8fe-4e27-46db-a3c6-58dd252aa001",
      "name": "Append Lead to Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.7,
      "position": [
        560,
        -80
      ],
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "YOUR_GOOGLE_SHEETS_CREDENTIAL",
          "name": "YOUR_GOOGLE_SHEETS_CREDENTIAL"
        }
      },
      "continueOnFail": true
    },
    {
      "parameters": {
        "content": "## 2. Google Sheets\nAppends a new row with `Name`, `Email`, `Date`, and `Source`. Replace `YOUR_GOOGLE_SHEET_ID`, choose the `Leads` tab, and connect Google Sheets OAuth.",
        "height": 190,
        "width": 330,
        "color": 5
      },
      "id": "6d5f4eaa-65c2-4e69-97f4-06b7cf3b4001",
      "name": "Sheets Note",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        470,
        -340
      ]
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "resource": "message",
        "operation": "send",
        "sendTo": "={{ $('Normalize Lead').first().json.Email }}",
        "subject": "={{ `Welcome to FlowForge AI, ${$('Normalize Lead').first().json.Name}!` }}",
        "emailType": "html",
        "message": "={{ `<p>Hi ${$('Normalize Lead').first().json.Name},</p><p>Thanks for reaching out to FlowForge AI. We received your request from <strong>${$('Normalize Lead').first().json.Source}</strong> and will follow up shortly.</p><p>In the meantime, reply to this email if you want to share more details about the workflow you want automated.</p><p>— The FlowForge AI team</p>` }}",
        "options": {
          "appendAttribution": false
        }
      },
      "id": "de4ec8c4-e63d-42ad-965a-38b72b2ea001",
      "name": "Send Gmail Welcome Email",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.2,
      "position": [
        840,
        -80
      ],
      "credentials": {
        "gmailOAuth2": {
          "id": "YOUR_GMAIL_CREDENTIAL",
          "name": "YOUR_GMAIL_CREDENTIAL"
        }
      },
      "continueOnFail": true
    },
    {
      "parameters": {
        "content": "## 3. Gmail\nSends a personalized welcome email to the lead using the `name` and `email` fields from the webhook payload.",
        "height": 170,
        "width": 330,
        "color": 6
      },
      "id": "d592cb71-4f2c-42fd-a539-6d6731d5b001",
      "name": "Gmail Note",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        760,
        -340
      ]
    },
    {
      "parameters": {
        "authentication": "accessToken",
        "resource": "message",
        "operation": "post",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "value": "#new-leads",
          "mode": "name"
        },
        "messageType": "text",
        "text": "={{ `🔔 New lead: ${$('Normalize Lead').first().json.Name} (${$('Normalize Lead').first().json.Email})` }}",
        "otherOptions": {
          "includeLinkToWorkflow": false
        }
      },
      "id": "f418f4de-8e4e-4cbb-8136-0e09bc3ea001",
      "name": "Notify Slack New Lead",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.5,
      "position": [
        1120,
        -80
      ],
      "credentials": {
        "slackApi": {
          "id": "YOUR_SLACK_CREDENTIAL",
          "name": "YOUR_SLACK_CREDENTIAL"
        }
      },
      "continueOnFail": true
    },
    {
      "parameters": {
        "content": "## 4. Slack\nPosts `🔔 New lead: {{name}} ({{email}})` to `#new-leads` using a Slack bot token credential.",
        "height": 170,
        "width": 330,
        "color": 3
      },
      "id": "cd961567-f11f-4ab6-a26b-31808e9aa001",
      "name": "Slack Note",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1040,
        -340
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose",
            "version": 2
          },
          "conditions": [
            {
              "id": "normalizer-error",
              "leftValue": "={{ $('Normalize Lead').first().json.error?.message || '' }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              }
            },
            {
              "id": "sheets-error",
              "leftValue": "={{ $('Append Lead to Google Sheets').first().json.error?.message || '' }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              }
            },
            {
              "id": "gmail-error",
              "leftValue": "={{ $('Send Gmail Welcome Email').first().json.error?.message || '' }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              }
            },
            {
              "id": "slack-error",
              "leftValue": "={{ $('Notify Slack New Lead').first().json.error?.message || '' }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              }
            }
          ],
          "combinator": "or"
        },
        "options": {}
      },
      "id": "a0a044df-ea2a-491b-a5cf-4de6c5805001",
      "name": "Did Any Step Fail?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1400,
        -80
      ]
    },
    {
      "parameters": {
        "jsCode": "const errors = [];\nconst checks = [\n  'Normalize Lead',\n  'Append Lead to Google Sheets',\n  'Send Gmail Welcome Email',\n  'Notify Slack New Lead',\n];\n\nfor (const nodeName of checks) {\n  try {\n    const item = $(nodeName).first().json;\n    if (item.error) {\n      errors.push({\n        node: nodeName,\n        message: item.error.message ?? JSON.stringify(item.error),\n      });\n    }\n  } catch (error) {\n    errors.push({ node: nodeName, message: error.message });\n  }\n}\n\nconst lead = (() => {\n  try { return $('Normalize Lead').first().json; } catch { return {}; }\n})();\n\nconsole.error('Lead Follow-Up Automator error', { errors, lead });\n\nreturn [{\n  json: {\n    status: 'error_logged',\n    loggedAt: new Date().toISOString(),\n    errors,\n    lead\n  }\n}];"
      },
      "id": "09b4e1a3-4786-4869-8bf4-a4745c246001",
      "name": "Log Error Details",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1680,
        -200
      ]
    },
    {
      "parameters": {
        "jsCode": "const lead = $('Normalize Lead').first().json;\nreturn [{\n  json: {\n    status: 'success',\n    message: `Lead follow-up completed for ${lead.Name} (${lead.Email}).`,\n    lead\n  }\n}];"
      },
      "id": "84ba5160-1124-4075-b997-94b6c9d1e001",
      "name": "Return Success Summary",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1680,
        40
      ]
    },
    {
      "parameters": {
        "content": "## 5. Error Handler\nThe IF node checks whether validation, Sheets, Gmail, or Slack returned an `error`. If yes, the Code node logs the details for debugging.",
        "height": 190,
        "width": 360,
        "color": 2
      },
      "id": "fe864a50-0f0e-41ee-9ee6-d255772f2001",
      "name": "Error Handler Note",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1350,
        -440
      ]
    },
    {
      "parameters": {
        "content": "## Test payload\n`curl -X POST https://YOUR_N8N_HOST/webhook-test/lead-followup-automator -H 'Content-Type: application/json' -d '{\"name\":\"Ada Lovelace\",\"email\":\"ada@example.com\",\"source\":\"Website\"}'`",
        "height": 170,
        "width": 520,
        "color": 1
      },
      "id": "655501d4-502d-4345-b877-7d58f7609001",
      "name": "Testing Note",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -260,
        -520
      ]
    }
  ],
  "connections": {
    "Webhook Trigger": {
      "main": [
        [
          {
            "node": "Normalize Lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize Lead": {
      "main": [
        [
          {
            "node": "Lead Data Valid?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Lead Data Valid?": {
      "main": [
        [
          {
            "node": "Append Lead to Google Sheets",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Log Error Details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append Lead to Google Sheets": {
      "main": [
        [
          {
            "node": "Send Gmail Welcome Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Gmail Welcome Email": {
      "main": [
        [
          {
            "node": "Notify Slack New Lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notify Slack New Lead": {
      "main": [
        [
          {
            "node": "Did Any Step Fail?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Did Any Step Fail?": {
      "main": [
        [
          {
            "node": "Log Error Details",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Return Success Summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "saveManualExecutions": true,
    "saveDataErrorExecution": "all",
    "saveDataSuccessExecution": "all"
  },
  "staticData": null,
  "pinData": {},
  "active": false,
  "versionId": "2e78c9f3-f4c2-47de-b072-17230fe04001",
  "meta": {
    "templateCredsSetupCompleted": false,
    "instanceId": "flowforge-ai-demo"
  },
  "tags": []
}
