{
  "name": "YA-RE-26: Real Estate Lead Qualification & Routing Engine",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "real-estate-lead-intake",
        "responseMode": "responseNode",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [180, 300],
      "id": "node-webhook-lead-intake",
      "name": "Webhook: Inbound Lead Intake"
    },
    {
      "parameters": {
        "jsCode": "// Step 1: E.164 Phone Normalization & Syntax Validation\nconst raw = $input.first().json.body || $input.first().json;\n\nconst rawPhone = String(raw.phone || raw.telephone || '').trim();\nconst rawEmail = String(raw.email || '').trim().toLowerCase();\nconst rawName = String(raw.name || raw.full_name || 'Valued Client').trim();\n\n// Normalize phone to E.164 (MENA coverage: Egypt +20, KSA +966, UAE +971)\nlet cleanedPhone = rawPhone.replace(/[^0-9+]/g, '');\nif (cleanedPhone.startsWith('00')) {\n  cleanedPhone = '+' + cleanedPhone.slice(2);\n} else if (cleanedPhone.startsWith('0') && cleanedPhone.length === 11) {\n  cleanedPhone = '+20' + cleanedPhone.slice(1); // Default Egypt mobile\n} else if (!cleanedPhone.startsWith('+') && cleanedPhone.length >= 9) {\n  cleanedPhone = '+' + cleanedPhone;\n}\n\nconst isValidPhone = /^\\+[1-9]\\d{8,14}$/.test(cleanedPhone);\nconst isValidEmail = rawEmail.length === 0 || /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/.test(rawEmail);\nconst isValid = isValidPhone && rawName.length > 1;\n\nreturn [{\n  json: {\n    intake_id: `in_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`,\n    raw_payload: raw,\n    contact: {\n      name: rawName,\n      phone: cleanedPhone,\n      email: rawEmail,\n      is_valid_phone: isValidPhone,\n      is_valid_email: isValidEmail\n    },\n    is_valid_submission: isValid,\n    intake_timestamp: new Date().toISOString()\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [380, 300],
      "id": "node-code-normalization",
      "name": "Code: Phone & Data Normalization"
    },
    {
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{ $json.is_valid_submission }}",
              "value2": true
            }
          ]
        }
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [580, 300],
      "id": "node-if-validation",
      "name": "IF: Valid Lead Submission"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://YOUR_LOGGING_ENDPOINT/api/v1/lead-intake-errors",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_LOGGING_TOKEN"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"event\": \"INVALID_LEAD_REJECTED\",\n  \"intake_id\": \"{{ $json.intake_id }}\",\n  \"error_reason\": \"Malformed phone number or empty name\",\n  \"raw_contact\": {{ JSON.stringify($json.contact) }},\n  \"timestamp\": \"{{ $json.intake_timestamp }}\"\n}",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [780, 480],
      "id": "node-log-validation-error",
      "name": "HTTP: Log Validation Error"
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={\n  \"status\": \"error\",\n  \"message\": \"Invalid phone format or contact details\",\n  \"intake_id\": \"{{ $('Code: Phone & Data Normalization').item.json.intake_id }}\"\n}",
        "options": {
          "responseCode": 400
        }
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [980, 480],
      "id": "node-respond-validation-error",
      "name": "Respond: Invalid Lead 400"
    },
    {
      "parameters": {
        "jsCode": "// Step 2: SHA-256 Deduplication Fingerprint & Frequency Check\nconst crypto = require('crypto');\nconst item = $input.first().json;\nconst phone = item.contact.phone;\nconst email = item.contact.email || 'no_email';\n\nconst dedupeKey = `${phone}_${email}`;\nconst leadHash = crypto.createHash('sha256').update(dedupeKey).digest('hex');\n\nreturn [{\n  json: {\n    ...item,\n    dedupe: {\n      fingerprint: leadHash,\n      is_duplicate: false\n    }\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [780, 220],
      "id": "node-code-dedupe",
      "name": "Code: Deduplication Hash Engine"
    },
    {
      "parameters": {
        "jsCode": "// Step 3: UTM Parameter Enrichment & Project Taxonomy Mapping\nconst item = $input.first().json;\nconst raw = item.raw_payload;\n\nconst projectMapping = {\n  'north_coast': 'Ras El Hekma / Sahel Phase 1',\n  'new_cairo': 'Fifth Settlement Flagship',\n  'riyadh_north': 'North Riyadh Masterplan',\n  'dubai_waterfront': 'Dubai Marina Waterfront'\n};\n\nconst projectKey = String(raw.project || raw.project_interest || 'general').toLowerCase().trim();\nconst resolvedProject = projectMapping[projectKey] || raw.project || 'General Off-Plan Project';\nconst statedBudget = String(raw.budget || raw.budget_range || '5M - 10M EGP').trim();\nconst inquiryType = String(raw.inquiry_type || raw.buyer_type || 'Investor').trim();\n\n// Qualification Tier Matrix\nlet qualificationTier = 'STANDARD';\nif (statedBudget.includes('20M') || statedBudget.includes('50M') || inquiryType.toLowerCase().includes('bulk')) {\n  qualificationTier = 'VIP_TIER_A';\n} else if (inquiryType.toLowerCase().includes('broker') || raw.is_broker === true) {\n  qualificationTier = 'BROKER_CHANNEL';\n}\n\nreturn [{\n  json: {\n    ...item,\n    project: {\n      resolved_name: resolvedProject,\n      stated_budget: statedBudget,\n      inquiry_type: inquiryType,\n      tier: qualificationTier\n    },\n    utm: {\n      source: raw.utm_source || 'meta_ads',\n      medium: raw.utm_medium || 'cpc',\n      campaign: raw.utm_campaign || 'off_plan_q3',\n      content: raw.utm_content || 'video_3d_chalet',\n      term: raw.utm_term || ''\n    }\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [980, 220],
      "id": "node-code-enrichment",
      "name": "Code: UTM & Project Enrichment"
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.project.tier }}",
                    "rightValue": "VIP_TIER_A",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "Tier A: High-Ticket VIP"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.project.tier }}",
                    "rightValue": "BROKER_CHANNEL",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "Tier C: Broker Channel"
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra"
        }
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.2,
      "position": [1180, 220],
      "id": "node-switch-routing-rules",
      "name": "Switch: Qualification Routing Rules"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://YOUR_CRM_BASE_URL/api/v1/leads/vip-assign",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_CRM_API_KEY_HERE"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"lead_id\": \"{{ $json.intake_id }}\",\n  \"name\": \"{{ $json.contact.name }}\",\n  \"phone\": \"{{ $json.contact.phone }}\",\n  \"email\": \"{{ $json.contact.email }}\",\n  \"project\": \"{{ $json.project.resolved_name }}\",\n  \"budget\": \"{{ $json.project.stated_budget }}\",\n  \"tier\": \"VIP_TIER_A\",\n  \"assigned_team\": \"Senior_Sales_Director_Pool\",\n  \"sla_minutes\": 5,\n  \"utm_source\": \"{{ $json.utm.source }}\",\n  \"utm_campaign\": \"{{ $json.utm.campaign }}\"\n}",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [1420, 100],
      "id": "node-crm-vip-assign",
      "name": "HTTP: CRM VIP Team Assignment"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://graph.facebook.com/v19.0/YOUR_WHATSAPP_PHONE_NUMBER_ID/messages",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_WHATSAPP_SYSTEM_TOKEN"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"messaging_product\": \"whatsapp\",\n  \"to\": \"{{ $('Code: Phone & Data Normalization').item.json.contact.phone }}\",\n  \"type\": \"template\",\n  \"template\": {\n    \"name\": \"developer_vip_welcome_ar\",\n    \"language\": { \"code\": \"ar\" },\n    \"components\": [\n      {\n        \"type\": \"body\",\n        \"parameters\": [\n          { \"type\": \"text\", \"text\": \"{{ $('Code: Phone & Data Normalization').item.json.contact.name }}\" }\n        ]\n      }\n    ]\n  }\n}",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [1640, 100],
      "id": "node-whatsapp-ack",
      "name": "HTTP: WhatsApp Instant Acknowledgment"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://YOUR_CRM_BASE_URL/api/v1/leads/broker-triage",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_CRM_API_KEY_HERE"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"lead_id\": \"{{ $json.intake_id }}\",\n  \"name\": \"{{ $json.contact.name }}\",\n  \"phone\": \"{{ $json.contact.phone }}\",\n  \"email\": \"{{ $json.contact.email }}\",\n  \"tier\": \"BROKER_CHANNEL\",\n  \"assigned_team\": \"Channel_Partners_Desk\"\n}",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [1420, 220],
      "id": "node-crm-broker-assign",
      "name": "HTTP: CRM Broker Triage Assignment"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://YOUR_CRM_BASE_URL/api/v1/leads/standard-assign",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_CRM_API_KEY_HERE"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"lead_id\": \"{{ $json.intake_id }}\",\n  \"name\": \"{{ $json.contact.name }}\",\n  \"phone\": \"{{ $json.contact.phone }}\",\n  \"email\": \"{{ $json.contact.email }}\",\n  \"project\": \"{{ $json.project.resolved_name }}\",\n  \"budget\": \"{{ $json.project.stated_budget }}\",\n  \"tier\": \"STANDARD\",\n  \"assigned_team\": \"Project_Specialist_Queue\",\n  \"sla_minutes\": 15,\n  \"utm_source\": \"{{ $json.utm.source }}\"\n}",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [1420, 340],
      "id": "node-crm-standard-assign",
      "name": "HTTP: CRM Specialist Assignment"
    },
    {
      "parameters": {
        "jsCode": "// Step 4: Audit & Telemetry Logging\nconst intakeId = $('Code: Phone & Data Normalization').item.json.intake_id;\nconst tier = $('Code: UTM & Project Enrichment').item.json.project.tier;\nconst project = $('Code: UTM & Project Enrichment').item.json.project.resolved_name;\n\nreturn [{\n  json: {\n    intake_id: intakeId,\n    tier,\n    project,\n    routed_status: 'SUCCESS',\n    timestamp: new Date().toISOString()\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [1860, 220],
      "id": "node-code-audit-log",
      "name": "Code: Audit & Telemetry Logger"
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={\n  \"status\": \"success\",\n  \"intake_id\": \"{{ $json.intake_id }}\",\n  \"tier\": \"{{ $json.tier }}\",\n  \"routed_at\": \"{{ $json.timestamp }}\"\n}",
        "options": {
          "responseCode": 200
        }
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [2060, 220],
      "id": "node-respond-routed-success",
      "name": "Respond: Lead Routed Confirmation"
    }
  ],
  "connections": {
    "Webhook: Inbound Lead Intake": {
      "main": [
        [
          {
            "node": "Code: Phone & Data Normalization",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code: Phone & Data Normalization": {
      "main": [
        [
          {
            "node": "IF: Valid Lead Submission",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF: Valid Lead Submission": {
      "main": [
        [
          {
            "node": "Code: Deduplication Hash Engine",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "HTTP: Log Validation Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP: Log Validation Error": {
      "main": [
        [
          {
            "node": "Respond: Invalid Lead 400",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code: Deduplication Hash Engine": {
      "main": [
        [
          {
            "node": "Code: UTM & Project Enrichment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code: UTM & Project Enrichment": {
      "main": [
        [
          {
            "node": "Switch: Qualification Routing Rules",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch: Qualification Routing Rules": {
      "main": [
        [
          {
            "node": "HTTP: CRM VIP Team Assignment",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "HTTP: CRM Broker Triage Assignment",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "HTTP: CRM Specialist Assignment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP: CRM VIP Team Assignment": {
      "main": [
        [
          {
            "node": "HTTP: WhatsApp Instant Acknowledgment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP: WhatsApp Instant Acknowledgment": {
      "main": [
        [
          {
            "node": "Code: Audit & Telemetry Logger",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP: CRM Broker Triage Assignment": {
      "main": [
        [
          {
            "node": "Code: Audit & Telemetry Logger",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP: CRM Specialist Assignment": {
      "main": [
        [
          {
            "node": "Code: Audit & Telemetry Logger",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code: Audit & Telemetry Logger": {
      "main": [
        [
          {
            "node": "Respond: Lead Routed Confirmation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "1.0.0",
  "meta": {
    "templateCredsSetupCompleted": false,
    "instanceId": "yehia-ahmed-re-playbook"
  },
  "tags": [
    {
      "name": "Deterministic Automation"
    },
    {
      "name": "Lead Routing"
    },
    {
      "name": "CRM Distribution"
    },
    {
      "name": "Validation & Error Logging"
    }
  ]
}