{
  "name": "Website Lead Rescue Desk: Score, SLA, Sheet, and Gmail Routing",
  "tags": [
    {
      "name": "lead-intake"
    },
    {
      "name": "sales-ops"
    },
    {
      "name": "sla-routing"
    }
  ],
  "nodes": [
    {
      "id": "workflow-note",
      "name": "Workflow Notes",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1120,
        -360
      ],
      "parameters": {
        "width": 520,
        "height": 760,
        "content": "## Website Lead Rescue Desk\n\nUse this when website leads go stale because form payloads are inconsistent, urgency is unclear, and the right person is not notified quickly.\n\nFlow:\n1. Receive a website/form lead payload.\n2. Normalize contact, company, source, budget, page, and message fields.\n3. Reject incomplete submissions with a structured webhook response.\n4. Score intent from pricing/demo/urgent/integration language plus contact quality.\n5. Set an SLA bucket and dedupe key.\n6. Append an audit row to Google Sheets.\n7. Route hot leads to a sales Gmail alert, medium leads to a review queue, and low-priority leads to a normal response.\n\nReplace placeholder Google Sheets and Gmail credentials before production use. No private credentials or customer data are included."
      },
      "typeVersion": 1
    },
    {
      "id": "lead-webhook",
      "name": "Lead Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -520,
        0
      ],
      "parameters": {
        "path": "lead-rescue-desk",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "normalize-payload",
      "name": "Normalize Payload",
      "type": "n8n-nodes-base.set",
      "position": [
        -320,
        0
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "received-at",
              "name": "received_at",
              "type": "string",
              "value": "={{ $now.toISO() }}"
            },
            {
              "id": "lead-name",
              "name": "name",
              "type": "string",
              "value": "={{ ($json.body?.name || $json.name || $json.body?.full_name || $json.full_name || '').trim() }}"
            },
            {
              "id": "lead-email",
              "name": "email",
              "type": "string",
              "value": "={{ ($json.body?.email || $json.email || '').toLowerCase().trim() }}"
            },
            {
              "id": "lead-phone",
              "name": "phone",
              "type": "string",
              "value": "={{ ($json.body?.phone || $json.phone || '').trim() }}"
            },
            {
              "id": "lead-company",
              "name": "company",
              "type": "string",
              "value": "={{ ($json.body?.company || $json.company || $json.body?.organization || $json.organization || '').trim() }}"
            },
            {
              "id": "lead-message",
              "name": "message",
              "type": "string",
              "value": "={{ ($json.body?.message || $json.message || $json.body?.details || $json.details || '').trim() }}"
            },
            {
              "id": "lead-budget",
              "name": "budget",
              "type": "string",
              "value": "={{ ($json.body?.budget || $json.budget || '').trim() }}"
            },
            {
              "id": "lead-timeline",
              "name": "requested_timeline",
              "type": "string",
              "value": "={{ ($json.body?.timeline || $json.timeline || $json.body?.requested_timeline || $json.requested_timeline || '').trim() }}"
            },
            {
              "id": "lead-page",
              "name": "page_url",
              "type": "string",
              "value": "={{ ($json.body?.page_url || $json.page_url || $json.body?.url || $json.url || '').trim() }}"
            },
            {
              "id": "lead-source",
              "name": "source",
              "type": "string",
              "value": "={{ ($json.body?.source || $json.source || $json.body?.utm_source || $json.utm_source || 'website').trim() }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "has-contact",
      "name": "Has Contact?",
      "type": "n8n-nodes-base.if",
      "position": [
        -120,
        0
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "boolean": [
            {
              "value1": "={{ Boolean(($json.email || '').includes('@') || ($json.phone || '').length >= 7) }}",
              "value2": true
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "missing-contact-response",
      "name": "Build Missing Contact Response",
      "type": "n8n-nodes-base.set",
      "position": [
        80,
        220
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "missing-ok",
              "name": "ok",
              "type": "boolean",
              "value": "={{ false }}"
            },
            {
              "id": "missing-status",
              "name": "status",
              "type": "string",
              "value": "needs_contact"
            },
            {
              "id": "missing-message",
              "name": "response_message",
              "type": "string",
              "value": "Please include a valid email address or phone number so the team can follow up."
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "respond-missing-contact",
      "name": "Respond Missing Contact",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        300,
        220
      ],
      "parameters": {
        "options": {
          "responseCode": 400
        },
        "respondWith": "json",
        "responseBody": "={{ { ok: $json.ok, status: $json.status, message: $json.response_message } }}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "score-lead",
      "name": "Score Lead and SLA",
      "type": "n8n-nodes-base.set",
      "position": [
        80,
        -80
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "intent-matches",
              "name": "intent_matches",
              "type": "number",
              "value": "={{ (($json.message || '') + ' ' + ($json.requested_timeline || '') + ' ' + ($json.budget || '')).match(/pricing|quote|proposal|demo|urgent|asap|this week|call|integration|crm|revenue|sales|budget|deadline/gi)?.length || 0 }}"
            },
            {
              "id": "lead-score",
              "name": "lead_score",
              "type": "number",
              "value": "={{ Math.min(100, ((($json.message || '') + ' ' + ($json.requested_timeline || '') + ' ' + ($json.budget || '')).match(/pricing|quote|proposal|demo|urgent|asap|this week|call|integration|crm|revenue|sales|budget|deadline/gi)?.length || 0) * 15 + (($json.email || '').includes('@') ? 20 : 0) + (($json.company || '').length ? 10 : 0) + (($json.budget || '').length ? 15 : 0) + (($json.page_url || '').length ? 5 : 0)) }}"
            },
            {
              "id": "sla",
              "name": "sla_bucket",
              "type": "string",
              "value": "={{ Math.min(100, ((($json.message || '') + ' ' + ($json.requested_timeline || '') + ' ' + ($json.budget || '')).match(/pricing|quote|proposal|demo|urgent|asap|this week|call|integration|crm|revenue|sales|budget|deadline/gi)?.length || 0) * 15 + (($json.email || '').includes('@') ? 20 : 0) + (($json.company || '').length ? 10 : 0) + (($json.budget || '').length ? 15 : 0) + (($json.page_url || '').length ? 5 : 0)) >= 70 ? '15-minute sales alert' : Math.min(100, ((($json.message || '') + ' ' + ($json.requested_timeline || '') + ' ' + ($json.budget || '')).match(/pricing|quote|proposal|demo|urgent|asap|this week|call|integration|crm|revenue|sales|budget|deadline/gi)?.length || 0) * 15 + (($json.email || '').includes('@') ? 20 : 0) + (($json.company || '').length ? 10 : 0) + (($json.budget || '').length ? 15 : 0) + (($json.page_url || '').length ? 5 : 0)) >= 40 ? 'same-day review' : 'next business day' }}"
            },
            {
              "id": "priority",
              "name": "priority",
              "type": "string",
              "value": "={{ Math.min(100, ((($json.message || '') + ' ' + ($json.requested_timeline || '') + ' ' + ($json.budget || '')).match(/pricing|quote|proposal|demo|urgent|asap|this week|call|integration|crm|revenue|sales|budget|deadline/gi)?.length || 0) * 15 + (($json.email || '').includes('@') ? 20 : 0) + (($json.company || '').length ? 10 : 0) + (($json.budget || '').length ? 15 : 0) + (($json.page_url || '').length ? 5 : 0)) >= 70 ? 'hot' : Math.min(100, ((($json.message || '') + ' ' + ($json.requested_timeline || '') + ' ' + ($json.budget || '')).match(/pricing|quote|proposal|demo|urgent|asap|this week|call|integration|crm|revenue|sales|budget|deadline/gi)?.length || 0) * 15 + (($json.email || '').includes('@') ? 20 : 0) + (($json.company || '').length ? 10 : 0) + (($json.budget || '').length ? 15 : 0) + (($json.page_url || '').length ? 5 : 0)) >= 40 ? 'review' : 'normal' }}"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "dedupe-key",
      "name": "Build Dedupe Key",
      "type": "n8n-nodes-base.set",
      "position": [
        300,
        -80
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "dedupe",
              "name": "dedupe_key",
              "type": "string",
              "value": "={{ [($json.email || $json.phone || 'unknown').toLowerCase(), ($json.company || 'no-company').toLowerCase(), $now.toFormat('yyyy-LL-dd')].join('|') }}"
            },
            {
              "id": "owner",
              "name": "routing_owner",
              "type": "string",
              "value": "={{ $json.priority === 'hot' ? 'sales' : $json.priority === 'review' ? 'ops-review' : 'nurture' }}"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "append-audit-row",
      "name": "Append Lead Audit Row",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        520,
        -80
      ],
      "parameters": {
        "columns": {
          "value": {
            "name": "={{ $json.name }}",
            "email": "={{ $json.email }}",
            "phone": "={{ $json.phone }}",
            "budget": "={{ $json.budget }}",
            "source": "={{ $json.source }}",
            "company": "={{ $json.company }}",
            "message": "={{ $json.message }}",
            "page_url": "={{ $json.page_url }}",
            "priority": "={{ $json.priority }}",
            "dedupe_key": "={{ $json.dedupe_key }}",
            "lead_score": "={{ $json.lead_score }}",
            "sla_bucket": "={{ $json.sla_bucket }}",
            "received_at": "={{ $json.received_at }}",
            "routing_owner": "={{ $json.routing_owner }}",
            "intent_matches": "={{ $json.intent_matches }}",
            "requested_timeline": "={{ $json.requested_timeline }}"
          },
          "mappingMode": "defineBelow"
        },
        "options": {},
        "operation": "append",
        "sheetName": "Lead audit",
        "documentId": "YOUR_SPREADSHEET_ID"
      },
      "typeVersion": 4.5
    },
    {
      "id": "hot-lead-check",
      "name": "Hot Lead?",
      "type": "n8n-nodes-base.if",
      "position": [
        740,
        -80
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "number": [
            {
              "value1": "={{ $json.lead_score }}",
              "value2": 70,
              "operation": "largerEqual"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "build-hot-alert",
      "name": "Build Hot Lead Alert",
      "type": "n8n-nodes-base.set",
      "position": [
        960,
        -240
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "alert-subject",
              "name": "alert_subject",
              "type": "string",
              "value": "={{ '[HOT lead ' + $json.lead_score + '] ' + ($json.company || $json.name || $json.email || 'Website lead') }}"
            },
            {
              "id": "alert-body",
              "name": "alert_body",
              "type": "string",
              "value": "={{ 'Lead score: ' + $json.lead_score + '\\nSLA: ' + $json.sla_bucket + '\\nOwner: ' + $json.routing_owner + '\\nName: ' + $json.name + '\\nEmail: ' + $json.email + '\\nPhone: ' + $json.phone + '\\nCompany: ' + $json.company + '\\nBudget: ' + $json.budget + '\\nTimeline: ' + $json.requested_timeline + '\\nSource: ' + $json.source + '\\nPage: ' + $json.page_url + '\\n\\nMessage:\\n' + $json.message }}"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "send-hot-alert",
      "name": "Send Hot Lead Gmail Alert",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1180,
        -240
      ],
      "parameters": {
        "sendTo": "sales@example.com",
        "message": "={{ $json.alert_body }}",
        "subject": "={{ $json.alert_subject }}"
      },
      "typeVersion": 2.1
    },
    {
      "id": "review-lead-check",
      "name": "Needs Human Review?",
      "type": "n8n-nodes-base.if",
      "position": [
        960,
        20
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "number": [
            {
              "value1": "={{ $json.lead_score }}",
              "value2": 40,
              "operation": "largerEqual"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "send-review-alert",
      "name": "Send Review Queue Gmail Alert",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1180,
        20
      ],
      "parameters": {
        "sendTo": "ops-review@example.com",
        "message": "={{ 'Review this same-day lead.\\nScore: ' + $json.lead_score + '\\nSLA: ' + $json.sla_bucket + '\\nName: ' + $json.name + '\\nEmail: ' + $json.email + '\\nCompany: ' + $json.company + '\\nMessage: ' + $json.message }}",
        "subject": "={{ '[Review lead ' + $json.lead_score + '] ' + ($json.company || $json.name || $json.email || 'Website lead') }}"
      },
      "typeVersion": 2.1
    },
    {
      "id": "respond-success",
      "name": "Respond Success",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1420,
        -80
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={{ { ok: true, priority: $json.priority, lead_score: $json.lead_score, sla: $json.sla_bucket, routing_owner: $json.routing_owner } }}"
      },
      "typeVersion": 1.1
    }
  ],
  "settings": {
    "executionOrder": "v1"
  },
  "updatedAt": "2026-06-02T00:00:00.000Z",
  "versionId": "tinyops-lead-rescue-desk-v2",
  "staticData": null,
  "connections": {
    "Hot Lead?": {
      "main": [
        [
          {
            "node": "Build Hot Lead Alert",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Needs Human Review?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Contact?": {
      "main": [
        [
          {
            "node": "Score Lead and SLA",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Build Missing Contact Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Lead Webhook": {
      "main": [
        [
          {
            "node": "Normalize Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Dedupe Key": {
      "main": [
        [
          {
            "node": "Append Lead Audit Row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize Payload": {
      "main": [
        [
          {
            "node": "Has Contact?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Score Lead and SLA": {
      "main": [
        [
          {
            "node": "Build Dedupe Key",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Needs Human Review?": {
      "main": [
        [
          {
            "node": "Send Review Queue Gmail Alert",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond Success",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Hot Lead Alert": {
      "main": [
        [
          {
            "node": "Send Hot Lead Gmail Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append Lead Audit Row": {
      "main": [
        [
          {
            "node": "Hot Lead?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Hot Lead Gmail Alert": {
      "main": [
        [
          {
            "node": "Respond Success",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Review Queue Gmail Alert": {
      "main": [
        [
          {
            "node": "Respond Success",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Missing Contact Response": {
      "main": [
        [
          {
            "node": "Respond Missing Contact",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "triggerCount": 1
}