{
  "nodes": [
    {
      "id": "defe3eb5-a816-498f-aa9f-db5497a1ae85",
      "name": "Webhook Trigger",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -1760,
        576
      ],
      "parameters": {
        "path": "website-lead",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2.1
    },
    {
      "id": "7a3ef9e5-f744-40c9-8a5e-f6d499367f9e",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1872,
        480
      ],
      "parameters": {
        "color": 7,
        "width": 336,
        "height": 528,
        "content": "## Webhook Trigger node\nThis is your \u201cform endpoint\u201d. Your website (or Postman) will send POST JSON here.\n\n\n\n\n\n\n\n\n\n\n\n\nSend a POST request to the webhook URL with JSON body:\n\n```json\n{\n  \"firstName\": \"John\",\n  \"lastName\": \"Doe\",\n  \"email\": \"john@example.com\",\n  \"company\": \"johnscompany\",\n  \"message\": \"Need help...\",\n  \"source\": \"contact_page\",\n  \"enrich\": false,\n  \"destination\": \"sheets\"\n}\n"
      },
      "typeVersion": 1
    },
    {
      "id": "4af97ba0-be13-4b29-a275-367da6fe5895",
      "name": "Normalize leads",
      "type": "n8n-nodes-base.set",
      "position": [
        -1248,
        576
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "fdafa238-d50d-4b8f-993d-a89173abcad6",
              "name": "lead.email",
              "type": "string",
              "value": "={{($json.email?.toLowerCase().trim()) || ($json.body[0].email?.trim())}}"
            },
            {
              "id": "e701fe0b-2b52-4002-874f-72ef91bdc2f3",
              "name": "lead.firstName",
              "type": "string",
              "value": "={{$json.firstName?.trim() || $json.body[0].firstName.trim()}}"
            },
            {
              "id": "ba254dae-3cf6-4c8b-b453-4129190f1d38",
              "name": "lead.lastName",
              "type": "string",
              "value": "={{$json.lastName?.trim()  || $json.body[0].lastName.trim()}}"
            },
            {
              "id": "759d2055-3464-42ba-a40c-8b8b1e32522b",
              "name": "lead.name",
              "type": "string",
              "value": "={{ ($json.body[0].firstName) + ' ' +  ($json.body[0].lastName)\n|| ($json.body.firstName) + ' ' +  ($json.body.lastName) \n|| ($json.firstName) + ' ' +  ($json.lastName)}}\n"
            },
            {
              "id": "ade16815-f24f-421f-935a-72054353c124",
              "name": "lead.company",
              "type": "string",
              "value": "={{$json.company?.trim() || $json.body[0].company?.trim()}}"
            },
            {
              "id": "146f39b2-ef44-437c-aa73-1e91db1903c6",
              "name": "lead.message",
              "type": "string",
              "value": "={{($json.message?.trim()) || ($json.body[0].message?.trim())}}"
            },
            {
              "id": "818ff320-014f-441b-b4b6-14cd36eab141",
              "name": "lead.source",
              "type": "string",
              "value": "={{$json.source || $json.body[0].source || 'unknown'}}"
            },
            {
              "id": "ed6c5892-2c83-4e10-aced-c797b4824423",
              "name": "lead.destination",
              "type": "string",
              "value": "={{$json.destination || $json.body[0].destination?.trim() || 'sheets'}}"
            },
            {
              "id": "cb32a8c5-1a7c-4fab-850e-abcf0f2639ac",
              "name": "lead.receivedAt",
              "type": "string",
              "value": "={{$now}}"
            },
            {
              "id": "20bb589c-f01d-4bdb-bf40-2de87b1db963",
              "name": "lead.enrich",
              "type": "boolean",
              "value": "={{ $json.enrich  || $json.body[0].enrich}}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "00bfb2a3-fb48-497b-8fdd-cbaf2c190c5c",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1520,
        480
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 256,
        "content": "## Normalize And Validate Lead\nReal data is messy. Trim spaces, lowercase email, create a consistent object once.\n\n\n\n\n\n\n\n\n\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "b908d026-0f74-4449-8d1a-d8440a045efe",
      "name": "Code - Validate Lead",
      "type": "n8n-nodes-base.code",
      "position": [
        -1040,
        576
      ],
      "parameters": {
        "jsCode": "const lead = $json.lead || {};\n\nconst missingFields = [];\nif (!lead.email) missingFields.push(\"email\");\nif (!lead.message) missingFields.push(\"message\");\n\nif (!lead.firstName && !lead.lastName && !lead.company) {\n  missingFields.push(\"firstName/lastName/company (at least one)\");\n}\n\n// Basic spam checks (optional, but useful)\nconst isLikelySpam =\n  typeof lead.message === \"string\" &&\n  lead.message.length < 5; // too short, suspicious\n\nconst isValid = missingFields.length === 0 && !isLikelySpam;\n\nreturn [\n  {\n    json: {\n      lead,\n      isValid,\n      missingFields,\n      isLikelySpam,\n      errorMessage: !isValid\n        ? (missingFields.length > 0\n            ? `Missing required fields: ${missingFields.join(\", \")}`\n            : \"Message looks too short / suspicious.\")\n        : null,\n    },\n  },\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "677ccaee-9604-4267-b622-3ea26b566434",
      "name": "IF node \u2014 Is Valid?",
      "type": "n8n-nodes-base.if",
      "position": [
        -816,
        576
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "7119a1cf-066b-4c44-a97f-41a72f531d85",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{$json.isValid}}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "0ddc6d37-18a3-4899-b4f6-54cafd1861ad",
      "name": "Respond to Webhook \u2014 400 Bad Request (invalid path)",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        -528,
        688
      ],
      "parameters": {
        "options": {
          "responseCode": 400
        },
        "respondWith": "json",
        "responseBody": "={\n  \"ok\": false,\n  \"error\": \"{{$json.errorMessage}}\",\n  \"missingFields\": \"{{$json.missingFields}}\"\n}\n"
      },
      "typeVersion": 1.5
    },
    {
      "id": "7f6197a0-365e-4425-930d-6e8a8ce5e9af",
      "name": "IF node \u2014 Enrichment enabled?",
      "type": "n8n-nodes-base.if",
      "position": [
        -528,
        448
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "4755a7b1-b4cd-45a4-9e67-4e326818404d",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.lead.enrich }}",
              "rightValue": ""
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.3
    },
    {
      "id": "451bec77-001a-44ca-ade7-400b2bcffad1",
      "name": "HTTP Request - Enrich (Optional)",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        -256,
        432
      ],
      "parameters": {
        "url": "https://example.com",
        "method": "POST",
        "options": {
          "timeout": 20000
        }
      },
      "typeVersion": 4.3,
      "alwaysOutputData": true
    },
    {
      "id": "8bd7d0f0-d09e-461a-88e9-3ebe7bca9bdc",
      "name": "Set - Merge Enrichment into lead",
      "type": "n8n-nodes-base.set",
      "position": [
        304,
        464
      ],
      "parameters": {
        "include": "except",
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "0ad79814-a5dc-4aa9-a479-08fb75096372",
              "name": "=lead.enrichment",
              "type": "string",
              "value": "={{ $json.data || null}}"
            }
          ]
        },
        "excludeFields": "data",
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "597e8af4-d5c1-4947-af3d-1b2480986995",
      "name": "Switch - Choose destination (Sheets vs HubSpot)",
      "type": "n8n-nodes-base.switch",
      "position": [
        576,
        464
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "Google Sheets",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "85fcd379-6b3c-477b-8cc1-8f5517305c9e",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{($json.lead.destination || 'sheets').toLowerCase()}}",
                    "rightValue": "sheets"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "HubSpot",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "ffb2d932-ab47-4a0f-8b7b-25e011abd92b",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{($json.lead.destination || 'sheets').toLowerCase()}}",
                    "rightValue": "hubspot"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.4
    },
    {
      "id": "5767a86b-99db-4fd5-bf40-5d4c116f87d4",
      "name": "Google Sheets- Lookup by email",
      "type": "n8n-nodes-base.googleSheets",
      "onError": "continueRegularOutput",
      "position": [
        896,
        352
      ],
      "parameters": {
        "columns": {
          "value": {
            "name": "={{$json.lead.name}}",
            "email": "={{$json.lead.email}}",
            "source": "={{$json.lead.source}}",
            "status": "New",
            "company": "={{$json.lead.company}}",
            "message": "={{$json.lead.message}}",
            "updatedAt": "={{$now}}",
            "enrichment": "={{JSON.stringify($json.lead.enrichment || null)}}",
            "receivedAt": "={{$json.lead.receivedAt || $now}}",
            "destination": "={{$json.lead.destination}}"
          },
          "schema": [
            {
              "id": "email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "company",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "company",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "message",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "message",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "source",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "source",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "destination",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "destination",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "enrichment",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "enrichment",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "updatedAt",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "updatedAt",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "receivedAt",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "receivedAt",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "email"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "dda6f43a-ecf0-4664-acfc-3db36362d17f",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        880,
        -112
      ],
      "parameters": {
        "color": 7,
        "width": 608,
        "height": 288,
        "content": "## Example sheet pattern\n```\nreceivedAt \u2192 ={{$json.lead.receivedAt || $now}}\nname \u2192 ={{$json.lead.name}}\nemail \u2192 ={{$json.lead.email}}\ncompany \u2192 ={{$json.lead.company}}\nmessage \u2192 ={{$json.lead.message}}\nsource \u2192 ={{$json.lead.source}}\ndestination \u2192 ={{$json.lead.destination}}\nenrichment \u2192 ={{JSON.stringify($json.lead.enrichment || null)}}\nupdatedAt \u2192 ={{$now}}\nstatus \u2192 New\n```"
      },
      "typeVersion": 1
    },
    {
      "id": "01f3f746-e727-44be-b178-c520fcb214ed",
      "name": "Set - Snapshot data",
      "type": "n8n-nodes-base.set",
      "position": [
        -256,
        272
      ],
      "parameters": {
        "options": {},
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "dd12a7d4-a64c-40a1-bd50-bcc40327fc0b",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        -48,
        288
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2
    },
    {
      "id": "682bd14c-2020-4641-b4b4-e5b5ccc01333",
      "name": "IF - Sheets update Failed?",
      "type": "n8n-nodes-base.if",
      "position": [
        1088,
        352
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "072eb98f-acf5-4424-8cf4-33c433f7e546",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{$json.error?.message}}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "c9cfeab2-aed5-4f36-b061-5e2a78798517",
      "name": "Slack - update failed",
      "type": "n8n-nodes-base.slack",
      "position": [
        1312,
        224
      ],
      "parameters": {
        "text": "=={{ `\u274c Google Sheets update failed for a new row \nerror details: ${$json.error || $json.errorMessage || \"-\"}\n\nlead data:\nName: ${$json.name ?? \"-\"}\nEmail: ${$json.email ?? \"-\"}\nCompany: ${$json.company ?? \"-\"}\nStatus: ${$json.status ?? \"-\"}\nDestination: ${$json.destination ?? \"-\"}\nReceived: ${$json.receivedAt ?? \"-\"}\nUpdated: ${$json.updatedAt ?? \"-\"}\nMessage:${$json.message ?? \"-\"}\n\nEnrichment (first 300 chars):\n${($json.enrichment ?? \"\").toString().slice(0, 300)}${(($json.enrichment ?? \"\").toString().length > 300 ? \"...\" : \"\")}` }}",
        "user": {
          "__rl": true,
          "mode": "list",
          "value": "U0A672GG97E",
          "cachedResultName": "defitetra"
        },
        "select": "user",
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "typeVersion": 2.4
    },
    {
      "id": "875946be-f203-4863-b5a6-6cd53d29432a",
      "name": "Slack - Successfully updated",
      "type": "n8n-nodes-base.slack",
      "position": [
        1312,
        368
      ],
      "parameters": {
        "text": "=={{ `\u2705 Google Sheets updated successfully with a new lead. \nLead details:\n\nName: ${$json.name ?? \"-\"}\nEmail: ${$json.email ?? \"-\"}\nCompany: ${$json.company ?? \"-\"}\nStatus: ${$json.status ?? \"-\"}\nDestination: ${$json.destination ?? \"-\"}\nReceived: ${$json.receivedAt ?? \"-\"}\nUpdated: ${$json.updatedAt ?? \"-\"}\nMessage:${$json.message ?? \"-\"}\n\nEnrichment (first 300 chars):\n${($json.enrichment ?? \"\").toString().slice(0, 300)}${(($json.enrichment ?? \"\").toString().length > 300 ? \"...\" : \"\")}` }}",
        "user": {
          "__rl": true,
          "mode": "list",
          "value": "U0A672GG97E",
          "cachedResultName": "defitetra"
        },
        "select": "user",
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "typeVersion": 2.4
    },
    {
      "id": "75b7dd2d-82a4-43b3-a919-8e9f87e1c974",
      "name": "Hubspot - Create/Update contacts",
      "type": "n8n-nodes-base.hubspot",
      "onError": "continueRegularOutput",
      "position": [
        896,
        560
      ],
      "parameters": {
        "email": "={{ $json.lead.email }}",
        "options": {},
        "additionalFields": {}
      },
      "typeVersion": 2.2
    },
    {
      "id": "dc890918-1c7a-40c1-91cc-3d6264df6b26",
      "name": "IF - HubSpot Failed?",
      "type": "n8n-nodes-base.if",
      "position": [
        1088,
        560
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "072eb98f-acf5-4424-8cf4-33c433f7e546",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{$json.error?.message || $json.error}}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "4f1b0f45-4f50-4950-8b21-7d2a3f15ad3b",
      "name": "Slack - HubSpot Successfully updated",
      "type": "n8n-nodes-base.slack",
      "position": [
        1312,
        688
      ],
      "parameters": {
        "text": "=={{ `\u2705 HubSpot updated successfully with a new lead. \nLead details:\n\nName: ${$json.name ?? \"-\"}\nEmail: ${$json.email ?? \"-\"}\nCompany: ${$json.company ?? \"-\"}\nStatus: ${$json.status ?? \"-\"}\nDestination: ${$json.destination ?? \"-\"}\nReceived: ${$json.receivedAt ?? \"-\"}\nUpdated: ${$json.updatedAt ?? \"-\"}\nMessage:${$json.message ?? \"-\"}\n\nEnrichment (first 300 chars):\n${($json.enrichment ?? \"\").toString().slice(0, 300)}${(($json.enrichment ?? \"\").toString().length > 300 ? \"...\" : \"\")}` }}",
        "user": {
          "__rl": true,
          "mode": "list",
          "value": "U0A672GG97E",
          "cachedResultName": "defitetra"
        },
        "select": "user",
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "typeVersion": 2.4
    },
    {
      "id": "37eaee93-074a-4f8d-81e3-1a85549b0f3a",
      "name": "Slack - HubSpot update failed",
      "type": "n8n-nodes-base.slack",
      "position": [
        1312,
        544
      ],
      "parameters": {
        "text": "=\u274c HubSpot write failed\nEmail: {{$json.lead.email}}\nError: {{$json.error.message}}\n",
        "user": {
          "__rl": true,
          "mode": "list",
          "value": "U0A672GG97E",
          "cachedResultName": "defitetra"
        },
        "select": "user",
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "typeVersion": 2.4
    },
    {
      "id": "b2372856-de49-4a6d-abc2-7ab93053b4d0",
      "name": "Respond to Webhook - 500 - Sheets",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1504,
        224
      ],
      "parameters": {
        "options": {
          "responseCode": 500
        },
        "respondWith": "json",
        "responseBody": "{\n  \"ok\": false,\n  \"destination\": \"sheets\",\n  \"error\": \"sheets write failed\"\n}\n"
      },
      "typeVersion": 1.5
    },
    {
      "id": "efec202d-2400-4f00-bef2-5c8ba396e77e",
      "name": "Respond to Webhook - 500 - HubSpot",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1504,
        544
      ],
      "parameters": {
        "options": {
          "responseCode": 500
        },
        "respondWith": "json",
        "responseBody": "{\n  \"ok\": false,\n  \"destination\": \"hubspot\",\n  \"error\": \"HubSpot write failed\"\n}\n"
      },
      "typeVersion": 1.5
    },
    {
      "id": "dcdad04e-3a8b-413d-855b-0ff5fd701328",
      "name": "Respond to Webhook - 200 - Sheets",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1504,
        368
      ],
      "parameters": {
        "options": {
          "responseCode": 200
        },
        "respondWith": "json",
        "responseBody": "{\n  \"ok\": true,\n  \"destination\": \"sheets\",\n  \"message\": \"sheets write successful\"\n}\n"
      },
      "typeVersion": 1.5
    },
    {
      "id": "1fc24732-4de6-4381-aa4b-c72dbe450727",
      "name": "Respond to Webhook - 200 - HubSpot",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1504,
        688
      ],
      "parameters": {
        "options": {
          "responseCode": 200
        },
        "respondWith": "json",
        "responseBody": "{\n  \"ok\": true,\n  \"destination\": \"hubspot\",\n  \"message\": \"hubspot write successful\"\n}\n"
      },
      "typeVersion": 1.5
    },
    {
      "id": "39016202-1bed-4448-96fa-f7e1548c9a85",
      "name": "Parse Webhook body",
      "type": "n8n-nodes-base.code",
      "position": [
        -1456,
        576
      ],
      "parameters": {
        "jsCode": "// If body arrives as a JSON string (text/plain), parse it. - To make sure that the next nodes received normalized data object\nconst b = $json.body;\n\nif (typeof b === \"string\") {\n  try {\n    const parsed = JSON.parse(b);\n    return [{ json: { ...$json, ...parsed } }];\n  } catch (e) {\n    return [{ json: { ...$json, parseError: \"Invalid JSON in body\", rawBody: b } }];\n  }\n}\n\nreturn [{ json: $json }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "44cbf381-bd5e-40a0-a8fd-650ad1799f6f",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -592,
        144
      ],
      "parameters": {
        "color": 7,
        "width": 784,
        "height": 496,
        "content": "## Enrichment check\nCheck if enrichment is enabled, if yes, then the enrichment is done through third party service like Clearbit/Hunter. And then merged along the snapshot data.\nIn the HTTP Node, change ```url: https://example.com/``` to enrichment provider url"
      },
      "typeVersion": 1
    },
    {
      "id": "c9ee2a87-5a44-4907-b111-f502598210b8",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        224,
        368
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "height": 272,
        "content": "Merge enrichment data along with the lead data, because HTTP node, looses the Input lead data. "
      },
      "typeVersion": 1
    },
    {
      "id": "dd4dc7b0-0a49-4354-9f1a-c4baf123fc24",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        496,
        368
      ],
      "parameters": {
        "color": 7,
        "width": 304,
        "height": 272,
        "content": "Switch cases, based on destination where to save the lead data, ```Google Sheets``` OR  ```HubSpot```"
      },
      "typeVersion": 1
    },
    {
      "id": "115e38cd-8b50-4337-abc3-f985de3c3969",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2688,
        -48
      ],
      "parameters": {
        "color": 7,
        "width": 784,
        "height": 1056,
        "content": "## What this workflow does\n\n1. **Receives a lead** via **Webhook (POST)** (from your website form, Postman, etc.)\n2. **Parses the body** (handles both JSON and `text/plain` JSON strings)\n3. **Normalizes** fields (trim, lowercase email, defaults)\n4. **Validates** required fields and spam-like input\n   - Invalid \u2192 returns **400** and stops\n5. **Optional enrichment**\n   - If enabled \u2192 calls an HTTP enrichment endpoint (placeholder by default)\n   - Merges enrichment back into the lead (because HTTP nodes don't preserve input automatically)\n6. **Routes lead** based on `destination`:\n   - `sheets` \u2192 Upsert (append or update) in Google Sheets\n   - `hubspot` \u2192 Upsert (create or update) contact in HubSpot\n7. **Slack alerts**\n   - Success alert on update\n   - Failure alert on update failure\n8. **Responds to webhook**\n   - `200 OK` on success\n   - `500` on storage failure (Sheets/HubSpot)\n\n---\n\n## Workflow diagram (high level)\n\n- **Webhook Trigger**\n- Parse Webhook Body\n- Normalize Leads\n- Validate Lead\n- IF Is Valid?\n  - \u274c false \u2192 Respond 400\n  - \u2705 true \u2192 IF Enrichment enabled?\n    - \u2705 true \u2192 Snapshot + HTTP Enrich \u2192 Merge \u2192 Merge Enrichment into lead\n    - \u274c false \u2192 (continues without enrichment)\n- Switch: destination (`sheets` vs `hubspot`)\n  - Sheets branch:\n    - Google Sheets Upsert by email\n    - IF Sheets update failed?\n      - \u274c Slack failure + Respond 500\n      - \u2705 Slack success + Respond 200\n  - HubSpot branch:\n    - HubSpot Create/Update contact\n    - IF HubSpot failed?\n      - \u274c Slack failure + Respond 500\n      - \u2705 Slack success + Respond 200\n\n"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Merge": {
      "main": [
        [
          {
            "node": "Set - Merge Enrichment into lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize leads": {
      "main": [
        [
          {
            "node": "Code - Validate Lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook Trigger": {
      "main": [
        [
          {
            "node": "Parse Webhook body",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Webhook body": {
      "main": [
        [
          {
            "node": "Normalize leads",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set - Snapshot data": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code - Validate Lead": {
      "main": [
        [
          {
            "node": "IF node \u2014 Is Valid?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF - HubSpot Failed?": {
      "main": [
        [
          {
            "node": "Slack - HubSpot update failed",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Slack - HubSpot Successfully updated",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF node \u2014 Is Valid?": {
      "main": [
        [
          {
            "node": "IF node \u2014 Enrichment enabled?",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond to Webhook \u2014 400 Bad Request (invalid path)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack - update failed": {
      "main": [
        [
          {
            "node": "Respond to Webhook - 500 - Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF - Sheets update Failed?": {
      "main": [
        [
          {
            "node": "Slack - update failed",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Slack - Successfully updated",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack - Successfully updated": {
      "main": [
        [
          {
            "node": "Respond to Webhook - 200 - Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack - HubSpot update failed": {
      "main": [
        [
          {
            "node": "Respond to Webhook - 500 - HubSpot",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets- Lookup by email": {
      "main": [
        [
          {
            "node": "IF - Sheets update Failed?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF node \u2014 Enrichment enabled?": {
      "main": [
        [
          {
            "node": "Set - Snapshot data",
            "type": "main",
            "index": 0
          },
          {
            "node": "HTTP Request - Enrich (Optional)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Set - Merge Enrichment into lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request - Enrich (Optional)": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Hubspot - Create/Update contacts": {
      "main": [
        [
          {
            "node": "IF - HubSpot Failed?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set - Merge Enrichment into lead": {
      "main": [
        [
          {
            "node": "Switch - Choose destination (Sheets vs HubSpot)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack - HubSpot Successfully updated": {
      "main": [
        [
          {
            "node": "Respond to Webhook - 200 - HubSpot",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch - Choose destination (Sheets vs HubSpot)": {
      "main": [
        [
          {
            "node": "Google Sheets- Lookup by email",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Hubspot - Create/Update contacts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}