{
  "id": "0PCfE3TBU4QHOLJW",
  "name": "Real Estate Lead Capture & Instant AI Follow-Up",
  "tags": [],
  "nodes": [
    {
      "id": "578394e5-c49a-4298-8c7c-3841baf2826b",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        80,
        -48
      ],
      "parameters": {
        "width": 480,
        "height": 832,
        "content": "## Real Estate Lead Capture & Instant AI Follow-Up\n\n### How it works\n\nThis workflow captures a new real estate lead from a web form, enriches it with configured business and agent details, and standardizes the lead data. It then sends the lead context to an OpenAI-compatible AI service to generate an instant follow-up response and supporting agent summary. Finally, it emails the lead, notifies the agent, and logs the interaction to a Google Sheets-based CRM.\n\n### Setup steps\n\n- Configure the webhook endpoint and connect it to the lead capture form on the website.\n- Update the Settings node with the correct businessName, agentName, agentEmail, and bookingLink values.\n- Configure the AI request details, including the OpenAI-compatible endpoint URL, model, API key, and any required headers.\n- Connect Gmail credentials for both the lead reply and agent notification nodes.\n- Connect Google Sheets credentials and select the target spreadsheet and sheet for CRM logging.\n\n### Customization\n\nAdjust the normalization and AI prompt code to match the fields collected by the web form, the desired follow-up tone, qualification criteria, and CRM columns."
      },
      "typeVersion": 1
    },
    {
      "id": "7a4f0cc3-13df-49df-b98c-3a0cb8f0c6d5",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        640,
        224
      ],
      "parameters": {
        "color": 7,
        "width": 592,
        "height": 320,
        "content": "## Capture and prepare lead\n\nReceives a new real estate lead from the web form, applies business and agent settings, and normalizes the submitted lead details for downstream processing."
      },
      "typeVersion": 1
    },
    {
      "id": "94f940fc-ace5-40bd-8f90-437373086c3b",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1280,
        224
      ],
      "parameters": {
        "color": 7,
        "width": 592,
        "height": 320,
        "content": "## Generate AI follow-up\n\nBuilds the OpenAI-compatible request, sends the lead context to the AI endpoint, and parses the AI response into usable follow-up content and lead insights."
      },
      "typeVersion": 1
    },
    {
      "id": "a77f019a-900d-4280-a0c7-26e7d57aa9c5",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1920,
        -48
      ],
      "parameters": {
        "color": 7,
        "height": 768,
        "content": "## Send and record outcomes\n\nUses the parsed AI output to immediately email the lead, notify the agent, and log the lead plus follow-up details to a Google Sheets CRM."
      },
      "typeVersion": 1
    },
    {
      "id": "15110a04-2170-4a68-8d50-d2c27159bf19",
      "name": "When Lead Form Submitted",
      "type": "n8n-nodes-base.webhook",
      "position": [
        688,
        384
      ],
      "parameters": {
        "path": "realestate-lead",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2.1
    },
    {
      "id": "efea880d-241b-4035-93dc-e80ce7d109ad",
      "name": "Set Agent Details",
      "type": "n8n-nodes-base.set",
      "position": [
        896,
        384
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "13b764d7-c26c-438e-9c0c-e28b1fc4cd99",
              "name": "businessName",
              "type": "string",
              "value": "Sunrise Realty"
            },
            {
              "id": "c46aace0-7411-4cca-b1c8-9a89dee5dfcd",
              "name": "agentName",
              "type": "string",
              "value": "Alex"
            },
            {
              "id": "7c16bd8c-a130-433e-be2d-f660a95f9f53",
              "name": "agentEmail",
              "type": "string",
              "value": "user@example.com"
            },
            {
              "id": "bcaaf05e-6c36-4484-a5f4-168cbe4c2971",
              "name": "bookingLink",
              "type": "string",
              "value": "https://cal.com/your-link"
            },
            {
              "id": "cc87d037-8d8c-4980-8684-81ca70ed4fce",
              "name": "aiUrl",
              "type": "string",
              "value": "https://api.openai.com/v1/chat/completions"
            },
            {
              "id": "daef2bc1-ad46-44e0-932c-154c3a747d75",
              "name": "aiModel",
              "type": "string",
              "value": "gpt-4o-mini"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "733a944b-7536-41ca-8716-234d15a28553",
      "name": "Normalize Lead Data",
      "type": "n8n-nodes-base.code",
      "position": [
        1088,
        384
      ],
      "parameters": {
        "jsCode": "const j = $('When Lead Form Submitted').first().json;\nconst p = j.body || j;\nconst s = $('Set Agent Details').first().json;\nreturn [{ json: {\n  name: p.name || p.full_name || 'there',\n  email: p.email || '',\n  phone: p.phone || p.phone_number || '',\n  budget: p.budget || p.budget_range || '',\n  interest: p.interest || p.property_type || p.message || '',\n  timeline: p.timeline || '',\n  message: p.message || p.notes || '',\n  businessName: s.businessName, agentName: s.agentName, agentEmail: s.agentEmail,\n  bookingLink: s.bookingLink, aiUrl: s.aiUrl, aiModel: s.aiModel\n}}];"
      },
      "typeVersion": 2
    },
    {
      "id": "def0f3f2-63b2-47d2-be53-076844052aaf",
      "name": "Build AI Request Data",
      "type": "n8n-nodes-base.code",
      "position": [
        1328,
        384
      ],
      "parameters": {
        "jsCode": "const out = [];\nfor (const it of $input.all()) {\n  const j = it.json;\n  const prompt = 'You are the assistant for ' + j.businessName + ', a real estate agency. A new lead just came in. ' +\n    'First qualify them as HOT, WARM, or COLD from budget, timeline and intent. ' +\n    'Then write a warm, professional reply (4-6 sentences) from ' + (j.agentName || 'our team') + ' that thanks them, references their interest, answers helpfully, and invites them to book a viewing at this link: ' + j.bookingLink + '. ' +\n    'Return ONLY JSON with keys: score (HOT|WARM|COLD), reason (one line), replySubject, replyBody. ' +\n    'Lead -> name: ' + j.name + ', email: ' + j.email + ', phone: ' + j.phone + ', budget: ' + j.budget + ', interest: ' + j.interest + ', timeline: ' + j.timeline + ', message: ' + j.message;\n  const aiBody = JSON.stringify({ model: j.aiModel, messages: [{ role: 'user', content: prompt }], temperature: 0.5, stream: false, response_format: { type: 'json_object' } });\n  out.push({ json: { ...j, aiBody } });\n}\nreturn out;"
      },
      "typeVersion": 2
    },
    {
      "id": "d56682f9-0558-403f-890d-e280cf5a7573",
      "name": "Post to AI Endpoint",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        1520,
        384
      ],
      "parameters": {
        "url": "={{ $json.aiUrl }}",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ $json.aiBody }}",
        "sendBody": true,
        "specifyBody": "json"
      },
      "typeVersion": 4.2
    },
    {
      "id": "c2a485ba-2f46-4535-a9be-3f10f44a5f7b",
      "name": "Parse AI Response",
      "type": "n8n-nodes-base.code",
      "position": [
        1728,
        384
      ],
      "parameters": {
        "jsCode": "const prep = $('Build AI Request Data').all();\nconst res = $input.all();\nconst out = [];\nfor (let i = 0; i < res.length; i++) {\n  let txt = '';\n  try { txt = res[i].json.choices[0].message.content; } catch (e) {}\n  let p = { score: 'WARM', reason: '', replySubject: 'Thanks for reaching out', replyBody: '' };\n  try { p = JSON.parse(txt); } catch (e) {}\n  const j = (prep[i] && prep[i].json) ? prep[i].json : {};\n  out.push({ json: { ...j, score: String(p.score || 'WARM').toUpperCase(), reason: p.reason || '', replySubject: p.replySubject || 'Thanks for reaching out', replyBody: p.replyBody || ('Hi ' + j.name + ', thanks for your interest! Book a viewing here: ' + j.bookingLink) } });\n}\nreturn out;"
      },
      "typeVersion": 2
    },
    {
      "id": "63ed2db7-c33b-45ec-8890-ed7bc87978c9",
      "name": "Send Email to Lead",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1968,
        208
      ],
      "parameters": {
        "sendTo": "={{ $json.email }}",
        "message": "={{ $json.replyBody }}",
        "options": {},
        "subject": "={{ $json.replySubject }}",
        "emailType": "text"
      },
      "typeVersion": 2.2
    },
    {
      "id": "e547ddca-4625-4602-b636-1c009611daaa",
      "name": "Notify Agent via Email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1968,
        384
      ],
      "parameters": {
        "sendTo": "={{ $json.agentEmail }}",
        "message": "=A new lead just came in:\n\nName: {{ $json.name }}\nEmail: {{ $json.email }}\nPhone: {{ $json.phone }}\nBudget: {{ $json.budget }}\nInterest: {{ $json.interest }}\nTimeline: {{ $json.timeline }}\n\nAI verdict: {{ $json.score }} - {{ $json.reason }}",
        "options": {},
        "subject": "=\ud83c\udfe1 New {{ $json.score }} lead: {{ $json.name }}",
        "emailType": "text"
      },
      "typeVersion": 2.2
    },
    {
      "id": "1931e138-1733-40d9-8ddd-acb4a01bdad1",
      "name": "Log Details in CRM Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "onError": "continueRegularOutput",
      "position": [
        1968,
        560
      ],
      "parameters": {
        "columns": {
          "value": {
            "name": "={{ $json.name }}",
            "email": "={{ $json.email }}",
            "phone": "={{ $json.phone }}",
            "score": "={{ $json.score }}",
            "budget": "={{ $json.budget }}",
            "reason": "={{ $json.reason }}",
            "interest": "={{ $json.interest }}",
            "timeline": "={{ $json.timeline }}"
          },
          "schema": [
            {
              "id": "name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "phone",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "phone",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "budget",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "budget",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "interest",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "interest",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "timeline",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "timeline",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "score",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "score",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "reason",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "reason",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": []
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Leads"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "PASTE_YOUR_GOOGLE_SHEET_URL"
        }
      },
      "typeVersion": 4.7
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "060f9db3-2c31-46e4-80e0-12431109964f",
  "connections": {
    "Parse AI Response": {
      "main": [
        [
          {
            "node": "Send Email to Lead",
            "type": "main",
            "index": 0
          },
          {
            "node": "Notify Agent via Email",
            "type": "main",
            "index": 0
          },
          {
            "node": "Log Details in CRM Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Agent Details": {
      "main": [
        [
          {
            "node": "Normalize Lead Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize Lead Data": {
      "main": [
        [
          {
            "node": "Build AI Request Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post to AI Endpoint": {
      "main": [
        [
          {
            "node": "Parse AI Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build AI Request Data": {
      "main": [
        [
          {
            "node": "Post to AI Endpoint",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When Lead Form Submitted": {
      "main": [
        [
          {
            "node": "Set Agent Details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}