{
  "id": "hqQSZC40uc2RLEQR",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Real Estate Lead Capture and Auto Reply",
  "tags": [],
  "nodes": [
    {
      "id": "7a587904-7ad4-4b04-b01d-070eb969de85",
      "name": "New Property Inquiry",
      "type": "n8n-nodes-base.webhook",
      "position": [
        160,
        1648
      ],
      "parameters": {
        "path": "property-inquiry",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "f816d6b9-8807-47ee-abb6-3a2ff76f6195",
      "name": "Structure Lead",
      "type": "n8n-nodes-base.set",
      "position": [
        416,
        1648
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "070e0a69-d6ab-437a-a56a-9076a542e130",
              "name": "name",
              "type": "string",
              "value": "={{$json.body.name}}"
            },
            {
              "id": "6b37cab5-e3eb-4f2b-b4a2-81147daee13b",
              "name": "email",
              "type": "string",
              "value": "={{$json.body.email}}"
            },
            {
              "id": "2e92c8c9-a2c4-4de5-8c2a-fc57b0a152f6",
              "name": "phone",
              "type": "string",
              "value": "={{$json.body.phone}}"
            },
            {
              "id": "9eb7c91b-241b-4110-a4b7-69eb16b5c357",
              "name": "property",
              "type": "string",
              "value": "={{$json.body.property_id}}"
            },
            {
              "id": "bb31404a-840a-446d-9e4e-30d3c58e549d",
              "name": "message",
              "type": "string",
              "value": "={{$json.body.message}}"
            },
            {
              "id": "a1b2c3d4-0001-4aaa-8aaa-+1234567890",
              "name": "source",
              "type": "string",
              "value": "={{$json.body.source || 'website'}}"
            },
            {
              "id": "a1b2c3d4-0001-4aaa-8aaa-+1234567890",
              "name": "submitted_at",
              "type": "string",
              "value": "={{$now.toISO()}}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "6a54f4b6-4150-4c60-9a18-aae67c76a38b",
      "name": "Validate Lead Input",
      "type": "n8n-nodes-base.if",
      "position": [
        672,
        1648
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "v1",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{$json.name}}",
              "rightValue": ""
            },
            {
              "id": "v2",
              "operator": {
                "type": "string",
                "operation": "regex"
              },
              "leftValue": "={{$json.email}}",
              "rightValue": "^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$"
            },
            {
              "id": "v3",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{$json.phone}}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "9bc7b64f-5c8a-4657-b574-e3cba6859793",
      "name": "Format Rejection Reason",
      "type": "n8n-nodes-base.set",
      "position": [
        864,
        1872
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "rej-0001",
              "name": "status",
              "type": "string",
              "value": "rejected"
            },
            {
              "id": "rej-0002",
              "name": "reason",
              "type": "string",
              "value": "={{ !$json.name ? 'Missing name' : (!$json.email || !$json.email.includes('@')) ? 'Invalid email' : 'Missing phone number' }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "a7a89cb3-0a11-4152-b8ea-57f87756ee55",
      "name": "Reject Inquiry",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1056,
        1872
      ],
      "parameters": {
        "options": {
          "responseCode": 400
        },
        "respondWith": "json",
        "responseBody": "={{ { \"status\": \"rejected\", \"reason\": $json.reason } }}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "c924429e-2c78-4530-aa47-a1433761dac2",
      "name": "Normalize Lead Data",
      "type": "n8n-nodes-base.code",
      "position": [
        928,
        1568
      ],
      "parameters": {
        "jsCode": "const item = $input.first().json;\nconst email = String(item.email || '').trim().toLowerCase();\nconst phone = String(item.phone || '').replace(/[^0-9+]/g, '');\nreturn [{ json: { ...item, email, phone } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "611dbadf-3a37-48c9-8942-1a7aa4cfb7c8",
      "name": "Classify Lead Interest",
      "type": "n8n-nodes-base.code",
      "position": [
        1440,
        1552
      ],
      "parameters": {
        "jsCode": "const item = $input.first().json;\nconst text = `${item.message || ''} ${item.property || ''}`.toLowerCase();\nconst hotKeywords = ['luxury', 'urgent', 'cash buyer', 'today', 'asap', 'pre-approved'];\nconst isHot = hotKeywords.some(k => text.includes(k));\nreturn [{ json: { ...item, lead_priority: isHot ? 'high' : 'standard' } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "fea65326-1693-4493-89fb-d6c84dc21617",
      "name": "Upsert Lead in CRM Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1840,
        1552
      ],
      "parameters": {
        "columns": {
          "value": {
            "Name": "={{ $json.name }}",
            "Email": "={{ $json.email }}",
            "Phone": "={{ $json.phone }}",
            "Source": "={{ $json.source }}",
            "Message": "={{ $json.message }}",
            "Priority": "={{ $json.lead_priority }}",
            "Property": "={{ $json.property }}",
            "Submitted At": "={{ $json.submitted_at }}"
          },
          "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": false
            },
            {
              "id": "Phone",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Phone",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Property",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Property",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Message",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Message",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Source",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Source",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Priority",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Priority",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Submitted At",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Submitted At",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Email"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1EV68pHdgAY4B5vTAk2djVSGEfXWhaXpSSy2GNjdCjYU/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1CG98ZH-GqK0Fy-r7swB6AJwDAkWbonpg_J-VXgpTZgY",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1CG98ZH-GqK0Fy-r7swB6AJwDAkWbonpg_J-VXgpTZgY/edit?usp=drivesdk",
          "cachedResultName": "Gre tests"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "2b8b931d-a1f1-405f-8500-70e8ba5d068b",
      "name": "Is High Priority Lead",
      "type": "n8n-nodes-base.if",
      "position": [
        2256,
        1552
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "p1",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{$json.lead_priority}}",
              "rightValue": "high"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "fc079153-1291-4e3f-ab7d-cd4e99fb4206",
      "name": "Send Priority Auto Reply",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2512,
        1408
      ],
      "parameters": {
        "sendTo": "={{ $('Structure Lead').item.json.email }}",
        "message": "Hi {{$('Structure Lead').item.json.name}}, thanks for your interest in property {{$('Structure Lead').item.json.property}}. Because of the details you shared, we're flagging this as a priority inquiry and a senior agent will reach out within the hour.",
        "options": {},
        "subject": "We're prioritizing your inquiry on property {{$('Structure Lead').item.json.property}}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "ccc49377-5752-40d0-9209-557d6aff5e53",
      "name": "Notify Senior Agent",
      "type": "n8n-nodes-base.slack",
      "position": [
        2768,
        1408
      ],
      "parameters": {
        "text": "PRIORITY lead: {{$('Structure Lead').item.json.name}} ({{$('Structure Lead').item.json.email}}) asking about {{$('Structure Lead').item.json.property}}. Message: {{$('Structure Lead').item.json.message}}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0B4D54BBFB",
          "cachedResultName": "price-drop"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "typeVersion": 2.3
    },
    {
      "id": "d63198d4-4466-4b11-87d3-ea75ad901487",
      "name": "Send Auto Reply to Lead",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2512,
        1696
      ],
      "parameters": {
        "sendTo": "={{ $('Structure Lead').item.json.email }}",
        "message": "Hi {{$('Structure Lead').item.json.name}}, thank you for reaching out. An agent will contact you shortly about property {{$('Structure Lead').item.json.property}}.",
        "options": {},
        "subject": "Thanks for your interest in property {{$('Structure Lead').item.json.property}}"
      },
      "typeVersion": 2.1
    },
    {
      "id": "61e9f52f-2167-4e29-8959-54c78bf5f534",
      "name": "Notify Agent Team",
      "type": "n8n-nodes-base.slack",
      "position": [
        2768,
        1696
      ],
      "parameters": {
        "text": "New property lead: {{$('Structure Lead').item.json.name}} ({{$('Structure Lead').item.json.email}}) asking about {{$('Structure Lead').item.json.property}}.",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0B4D54BBFB",
          "cachedResultName": "price-drop"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "typeVersion": 2.3
    },
    {
      "id": "29840eae-b0d2-40b8-af17-47f72b251f3c",
      "name": "Merge Notification Branches",
      "type": "n8n-nodes-base.merge",
      "position": [
        2992,
        1552
      ],
      "parameters": {
        "mode": "chooseBranch",
        "output": "={{1}}"
      },
      "typeVersion": 3.2
    },
    {
      "id": "382d9aaf-7641-4546-930e-4735204ff1b3",
      "name": "Confirm Inquiry",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        3280,
        1552
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={{ { \"status\": \"received\" } }}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "3058765d-cd18-4ab7-beb6-f7184ebcde65",
      "name": "Workflow Error Trigger",
      "type": "n8n-nodes-base.errorTrigger",
      "position": [
        672,
        2128
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "0ce432ee-036c-48ba-8972-53f5bee945e9",
      "name": "Alert Team on Workflow Failure",
      "type": "n8n-nodes-base.slack",
      "position": [
        928,
        2128
      ],
      "parameters": {
        "text": "Real Estate Lead Capture workflow failed: {{$json.execution.error.message}}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0B4D54BBFB",
          "cachedResultName": "price-drop"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "typeVersion": 2.3
    },
    {
      "id": "42834f29-381c-4291-a8c9-d6cd68e9942e",
      "name": "Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -624,
        1200
      ],
      "parameters": {
        "color": 7,
        "width": 560,
        "height": 1300,
        "content": "## \ud83c\udfe1 Real Estate Lead Capture and Auto Reply\n\nCaptures property inquiries from your website, validates and normalizes the data, upserts the lead into your CRM sheet (no duplicate rows on repeat inquiries), routes hot leads to a senior agent, and confirms receipt back to your site. A built-in error alert flags any failed run.\n\n**Perfect for:** real estate agents and brokerage teams.\n\n---\n\n## How it works\n\n1. **New Property Inquiry** \u2014 webhook that receives the website inquiry form.\n2. **Structure Lead** \u2014 organizes name, email, phone, property, message, source, and submission time.\n3. **Validate Lead Input** \u2014 checks that name, a valid email, and a phone number are present.\n4. **Format Rejection Reason** / **Reject Inquiry** \u2014 *(invalid path)* returns a clear 400 error to your site explaining what's missing.\n5. **Normalize Lead Data** \u2014 lowercases the email and strips formatting from the phone number.\n6. **Classify Lead Interest** \u2014 scans the message and property for keywords (luxury, urgent, cash buyer) to flag hot leads.\n7. **Upsert Lead in CRM Sheet** \u2014 appends a new row, or updates the existing row, matched on email, so a repeat inquiry never creates a duplicate.\n8. **Is High Priority Lead** \u2014 branches based on the priority flag.\n9. **Send Priority Auto Reply** / **Notify Senior Agent** \u2014 *(high priority path)* faster-turnaround email and a senior agent Slack alert.\n10. **Send Auto Reply to Lead** / **Notify Agent Team** \u2014 *(standard path)* the regular acknowledgement email and team alert.\n11. **Merge Notification Branches** \u2014 waits for whichever path ran, then continues once.\n12. **Confirm Inquiry** \u2014 returns a success response to the website.\n13. **Workflow Error Trigger** / **Alert Team on Workflow Failure** \u2014 *(error path)* posts to Slack if any step in this workflow throws an error.\n\n---\n\n## Setup (~15 min)\n\n1. **Webhook** \u2014 connect your site form to the *New Property Inquiry* URL.\n2. **Google Sheets** \u2014 connect your account and your own CRM sheet id in *Upsert Lead in CRM Sheet*; add Email, Name, Phone, Property, Message, Source, Priority, Submitted At as column headers.\n3. **Gmail** \u2014 connect Gmail in *Send Auto Reply to Lead* and *Send Priority Auto Reply*, and edit the wording.\n4. **Slack** \u2014 connect Slack and set the channels in *Notify Agent Team*, *Notify Senior Agent*, and *Alert Team on Workflow Failure*.\n> Replace the placeholder sheet id and channel ids below with your own before publishing \u2014 never submit a template with a real personal spreadsheet id or channel id."
      },
      "typeVersion": 1
    },
    {
      "id": "c1bb4571-e043-4d0d-98b2-bfa4ece730e8",
      "name": "1\ufe0f\u20e3 Inquiry Intake & Validation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        80,
        1328
      ],
      "parameters": {
        "color": 5,
        "width": 1176,
        "height": 760,
        "content": "## 1\ufe0f\u20e3 Inquiry Intake & Validation\n\nThe **New Property Inquiry** webhook receives form submissions and **Structure Lead** maps them into clean, named fields. **Validate Lead Input** checks that a name, valid email, and phone number were actually provided; invalid submissions are explained in **Format Rejection Reason** and turned away by **Reject Inquiry** with a 400 response, instead of silently creating a broken CRM row."
      },
      "typeVersion": 1
    },
    {
      "id": "060facc4-2fb2-4bff-9d1a-ca0c505aa025",
      "name": "2\ufe0f\u20e3 Normalize & Save to CRM",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1296,
        1344
      ],
      "parameters": {
        "color": 3,
        "width": 832,
        "height": 480,
        "content": "## 2\ufe0f\u20e3 Normalize & Save to CRM\n\n**Normalize Lead Data** cleans up the email and phone formatting, and **Classify Lead Interest** scores the inquiry for urgency keywords. **Upsert Lead in CRM Sheet** then writes the row, updating the existing lead instead of duplicating it if this person has inquired before."
      },
      "typeVersion": 1
    },
    {
      "id": "603fdadd-a404-4876-9861-42d1e73db35e",
      "name": "3\ufe0f\u20e3 Route by Priority",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2144,
        1216
      ],
      "parameters": {
        "color": 6,
        "width": 992,
        "height": 696,
        "content": "## 3\ufe0f\u20e3 Route by Priority\n\n**Is High Priority Lead** branches on the urgency score. Priority leads get a faster **Send Priority Auto Reply** email and go straight to **Notify Senior Agent**; everyone else gets the standard **Send Auto Reply to Lead** and **Notify Agent Team** alert. **Merge Notification Branches** waits for whichever path ran before continuing."
      },
      "typeVersion": 1
    },
    {
      "id": "13be88d2-f1ef-49dd-9ecd-6d693cb9e127",
      "name": "4\ufe0f\u20e3 Confirm & Error Handling",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3152,
        1312
      ],
      "parameters": {
        "color": 4,
        "width": 480,
        "height": 604,
        "content": "## 4\ufe0f\u20e3 Confirm & Error Handling\n\n**Confirm Inquiry** returns a success response to your website once notifications are sent. Separately, **Workflow Error Trigger** catches any unhandled failure anywhere in this workflow and **Alert Team on Workflow Failure** posts it to Slack so a bad run never goes unnoticed."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "bb989380-cd6c-4213-9cf5-9d38f6d40307",
  "nodeGroups": [],
  "connections": {
    "Structure Lead": {
      "main": [
        [
          {
            "node": "Validate Lead Input",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notify Agent Team": {
      "main": [
        [
          {
            "node": "Merge Notification Branches",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Normalize Lead Data": {
      "main": [
        [
          {
            "node": "Classify Lead Interest",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notify Senior Agent": {
      "main": [
        [
          {
            "node": "Merge Notification Branches",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Lead Input": {
      "main": [
        [
          {
            "node": "Normalize Lead Data",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Format Rejection Reason",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "New Property Inquiry": {
      "main": [
        [
          {
            "node": "Structure Lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is High Priority Lead": {
      "main": [
        [
          {
            "node": "Send Priority Auto Reply",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send Auto Reply to Lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Classify Lead Interest": {
      "main": [
        [
          {
            "node": "Upsert Lead in CRM Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Workflow Error Trigger": {
      "main": [
        [
          {
            "node": "Alert Team on Workflow Failure",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Rejection Reason": {
      "main": [
        [
          {
            "node": "Reject Inquiry",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Auto Reply to Lead": {
      "main": [
        [
          {
            "node": "Notify Agent Team",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Priority Auto Reply": {
      "main": [
        [
          {
            "node": "Notify Senior Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upsert Lead in CRM Sheet": {
      "main": [
        [
          {
            "node": "Is High Priority Lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Notification Branches": {
      "main": [
        [
          {
            "node": "Confirm Inquiry",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}