Lead Scoring
Scores incoming leads, persists results, and alerts sales on hot ones.
aiswitchemail
Source
/**
* Scores incoming leads and persists results for reporting.
* High-scoring leads trigger an alert to the sales team.
*/
webhook new_lead {
label: "New Lead Webhook"
schema: @json {
{
"type": "object",
"required": ["email", "company", "source"],
"properties": {
"email": { "type": "string", "format": "email" },
"company": { "type": "string" },
"source": { "type": "string" },
"job_title": { "type": "string" },
"company_size": { "type": "string" }
}
}
}
}
workflow score_lead {
label: "Score Lead"
root {
type: code
label: "Extract lead"
code: @ts { return context.nodes.root.input }
outputSchema: @json {
{
"type": "object",
"properties": {
"email": { "type": "string" },
"company": { "type": "string" },
"source": { "type": "string" },
"job_title": { "type": "string" },
"company_size": { "type": "string" }
}
}
}
}
node score {
type: ai
label: "Score the lead"
kind: object
model: "google/gemini-2.5-flash"
prompt: @ts {
const lead = context.nodes.root.output
return "Score this B2B lead from 0-100 based on likelihood to convert.\n\nEmail: " + lead.email + "\nCompany: " + lead.company + "\nSource: " + lead.source + "\nJob title: " + (lead.job_title || "unknown") + "\nCompany size: " + (lead.company_size || "unknown")
}
schema: @json {
{
"type": "object",
"required": ["score", "reasoning", "tier"],
"properties": {
"score": { "type": "number", "minimum": 0, "maximum": 100 },
"reasoning": { "type": "string" },
"tier": { "type": "string", "enum": ["hot", "warm", "cold"] }
}
}
}
}
node route {
type: switch
label: "Route by score"
cases: ["hot", "other"]
router: @ts {
if (context.nodes.score.output.tier === "hot") return "hot"
return "other"
}
}
node alert_sales {
type: email
label: "Alert sales team"
from: @ts { return "[email protected]" }
to: @ts { return "[email protected]" }
subject: @ts {
return "Hot lead: " + context.nodes.root.output.company + " (Score: " + context.nodes.score.output.score + ")"
}
text: @ts {
const lead = context.nodes.root.output
const result = context.nodes.score.output
return "New hot lead!\n\nCompany: " + lead.company + "\nEmail: " + lead.email + "\nScore: " + result.score + "\nReason: " + result.reasoning
}
}
node log_result {
type: code
label: "Log score"
code: @ts {
return {
email: context.nodes.root.output.email,
company: context.nodes.root.output.company,
score: context.nodes.score.output.score,
tier: context.nodes.score.output.tier
}
}
}
flow {
root -> score
score -> route
route -["hot"]-> alert_sales
route -["other"]-> log_result
}
}
stream scored_leads {
label: "Scored leads"
workflow: score_lead
version: v1
versions: {
v1 {
schema: @json {
{
"type": "object",
"required": ["email", "company", "score", "tier"],
"properties": {
"email": { "type": "string" },
"company": { "type": "string" },
"score": { "type": "number" },
"tier": { "type": "string" }
}
}
}
condition: @ts { return true }
prepare: @ts {
const logged = context.output.log_result
if (logged) return logged
return {
email: context.nodes.root.output.email,
company: context.nodes.root.output.company,
score: context.nodes.score.output.score,
tier: context.nodes.score.output.tier
}
}
}
}
}
trigger on_lead {
webhook:new_lead -> score_lead
enabled: true
}
Flow
Trigger to workflow
new_leadwebhook
score_lead
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.
Workflow nodes
CODE
Code Node
Extract lead
AI
AI Node
Score the lead
SWITCH
Switch Node
Route by score
EMAIL
Email Node
Alert sales team
CODE
Code Node
Log score
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.