{
  "name": "Vetted 01 · Website lead form to CRM contact + instant alert",
  "nodes": [
    {
      "parameters": {
        "content": "## Create HubSpot contacts from website form leads with Slack alerts\n\nTurns each website form submission into a HubSpot contact and a Slack alert. If HubSpot is down, the lead is emailed to you, so none are lost.\n\n### How it works\n1. A Webhook node receives the form post (JSON or form-encoded).\n2. The lead is cleaned up. An invalid email or a filled hidden spam-trap field gets a 400 reply and creates nothing.\n3. HubSpot creates or updates the contact by email, with 3 retries.\n4. Slack posts the new lead to your channel and the form gets a success reply.\n5. If HubSpot still fails, Gmail sends you the full lead instead.\n\n### Setup\n1. Open **Configure me** and set your email, Slack channel and lead-source label.\n2. Connect HubSpot (private app token with contact write access), Slack and Gmail.\n3. Point your website form at the **Lead form webhook** production URL (POST) with fields `email`, `first_name`, `last_name`, `phone`, `message` and an empty hidden field named `website`.\n4. Send one test submission, check each node's output, then activate.\n\n### Customization\n- Swap Slack for Microsoft Teams or an SMS node; the error path does not change.\n- Add a HubSpot lifecycle stage or lead status in the contact node's additional fields.\n\nTested on: **Not yet tested**\n\nFull guide: [Vetted Authority](https://vettedauthority.com/templates/lead-form-to-crm)",
        "height": 880,
        "width": 560,
        "color": 1
      },
      "id": "49b2a0fd-03bb-4317-a2aa-ef1e92b3a8ee",
      "name": "Overview",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -680,
        -420
      ]
    },
    {
      "parameters": {
        "content": "## 1. Receive and check the lead\nYour settings, clean-up and spam trap. Bad submissions get a 400 reply.",
        "height": 520,
        "width": 900,
        "color": 7
      },
      "id": "83c533e9-9c36-47ea-a4c6-40760da2910e",
      "name": "Section 1",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -60,
        -140
      ]
    },
    {
      "parameters": {
        "content": "## 2. Save, alert and reply\nHubSpot retries 3 times. If it still fails, the lead is emailed to you.",
        "height": 440,
        "width": 680,
        "color": 7
      },
      "id": "e383649b-4d88-4223-a765-0df57861271d",
      "name": "Section 2",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        900,
        -300
      ]
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "vetted-lead-form",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "328a7da4-5033-4daa-a852-e167c0d56af7",
      "name": "Lead form webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        0,
        0
      ],
      "webhookId": "f8db0476-776a-4853-abeb-f2c038d33f77"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "dac10d95-a67c-4bc8-a952-60496202aa2d",
              "name": "ownerEmail",
              "value": "you@yourbusiness.example",
              "type": "string"
            },
            {
              "id": "095d54ab-c543-4461-a13e-f3e39d311483",
              "name": "slackChannel",
              "value": "#YOUR_LEADS_CHANNEL",
              "type": "string"
            },
            {
              "id": "10e7c85f-c753-4706-aa1d-aef376d4890d",
              "name": "leadSourceLabel",
              "value": "Website form",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "bf0478a3-aa3d-426b-a15f-8a17d559d2ff",
      "name": "Configure me",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        240,
        0
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "ce3a31f7-71f1-46a4-a129-785dce6d4fb0",
              "name": "email",
              "value": "={{ ($('Lead form webhook').item.json.body.email || '').trim().toLowerCase() }}",
              "type": "string"
            },
            {
              "id": "b1d0b267-5072-4c1d-a5e0-54a0fa0cc8ae",
              "name": "firstName",
              "value": "={{ ($('Lead form webhook').item.json.body.first_name || '').trim() }}",
              "type": "string"
            },
            {
              "id": "a1bb60c0-2702-4044-a76c-9ce5f2e05723",
              "name": "lastName",
              "value": "={{ ($('Lead form webhook').item.json.body.last_name || '').trim() }}",
              "type": "string"
            },
            {
              "id": "8f697ce7-f112-43ac-a348-521aaea75f13",
              "name": "phone",
              "value": "={{ ($('Lead form webhook').item.json.body.phone || '').trim() }}",
              "type": "string"
            },
            {
              "id": "d72fb36c-1326-46b3-aba7-5f4aea8fb5ce",
              "name": "message",
              "value": "={{ ($('Lead form webhook').item.json.body.message || '').toString().slice(0, 2000) }}",
              "type": "string"
            },
            {
              "id": "3dfed958-2d99-4120-a8f5-16cb46bebdb8",
              "name": "honeypot",
              "value": "={{ $('Lead form webhook').item.json.body.website || '' }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "b52c01c1-28f0-4e3c-af3b-b707c7efcad3",
      "name": "Normalize lead",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        480,
        0
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose",
            "version": 2
          },
          "conditions": [
            {
              "id": "9bbb05c1-2b5e-49c1-a229-36464c151472",
              "leftValue": "={{ $json.email }}",
              "rightValue": "^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$",
              "operator": {
                "type": "string",
                "operation": "regex"
              }
            },
            {
              "id": "781202b3-c735-491e-a1a4-b5a89e03991e",
              "leftValue": "={{ $json.honeypot }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "empty",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "looseTypeValidation": true,
        "options": {}
      },
      "id": "fae08048-ba8e-4e9d-ade2-6642a1b533d2",
      "name": "Valid lead?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        720,
        0
      ]
    },
    {
      "parameters": {
        "authentication": "appToken",
        "resource": "contact",
        "operation": "upsert",
        "email": "={{ $json.email }}",
        "additionalFields": {
          "firstName": "={{ $json.firstName }}",
          "lastName": "={{ $json.lastName }}",
          "phoneNumber": "={{ $json.phone }}"
        }
      },
      "id": "0aaccb23-a52a-4f27-a42c-cccdee964437",
      "name": "Upsert HubSpot contact",
      "type": "n8n-nodes-base.hubspot",
      "typeVersion": 2.1,
      "position": [
        960,
        -180
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 5000,
      "onError": "continueErrorOutput"
    },
    {
      "parameters": {
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $('Configure me').first().json.slackChannel }}"
        },
        "text": "=New lead from {{ $('Configure me').first().json.leadSourceLabel }}: {{ $('Normalize lead').item.json.firstName }} {{ $('Normalize lead').item.json.lastName }} <{{ $('Normalize lead').item.json.email }}>\n{{ $('Normalize lead').item.json.phone }}\n> {{ $('Normalize lead').item.json.message }}",
        "otherOptions": {}
      },
      "id": "d83092f4-6493-48df-adb8-05c6833dd967",
      "name": "Slack alert",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.3,
      "position": [
        1200,
        -180
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 5000,
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "sendTo": "={{ $('Configure me').first().json.ownerEmail }}",
        "subject": "=Lead NOT saved to HubSpot: {{ $('Normalize lead').item.json.email }}",
        "emailType": "text",
        "message": "=HubSpot rejected or timed out on this lead after 3 tries. Add it by hand.\n\nName: {{ $('Normalize lead').item.json.firstName }} {{ $('Normalize lead').item.json.lastName }}\nEmail: {{ $('Normalize lead').item.json.email }}\nPhone: {{ $('Normalize lead').item.json.phone }}\nMessage: {{ $('Normalize lead').item.json.message }}\n\nError: {{ $json.error?.message || 'see the n8n execution log' }}",
        "options": {
          "appendAttribution": false
        }
      },
      "id": "84121188-18e3-4b63-ad67-3acfedce3748",
      "name": "Email lead to owner (CRM failed)",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1200,
        0
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 5000,
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ { ok: true } }}",
        "options": {
          "responseCode": 200
        }
      },
      "id": "19ce1b2c-eab3-4bf2-a626-023d192628f2",
      "name": "Respond OK",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        1440,
        -180
      ]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ { ok: false, error: 'Please enter a valid email address.' } }}",
        "options": {
          "responseCode": 400
        }
      },
      "id": "fcbcc86c-c345-40d3-a4c1-79de767f062d",
      "name": "Respond rejected",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        720,
        240
      ]
    }
  ],
  "connections": {
    "Lead form webhook": {
      "main": [
        [
          {
            "node": "Configure me",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Configure me": {
      "main": [
        [
          {
            "node": "Normalize lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize lead": {
      "main": [
        [
          {
            "node": "Valid lead?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Valid lead?": {
      "main": [
        [
          {
            "node": "Upsert HubSpot contact",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond rejected",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upsert HubSpot contact": {
      "main": [
        [
          {
            "node": "Slack alert",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Email lead to owner (CRM failed)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack alert": {
      "main": [
        [
          {
            "node": "Respond OK",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Email lead to owner (CRM failed)": {
      "main": [
        [
          {
            "node": "Respond OK",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "pinData": {},
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "saveManualExecutions": true,
    "callerPolicy": "workflowsFromSameOwner"
  },
  "meta": {
    "templateCredsSetupCompleted": false
  }
}
