WebhookView on GitHub
Feedback Survey Processor
Processes NPS surveys, routes detractors for follow-up, and persists all scores.
aiswitchresend
Source
/**
* Processes NPS survey responses. Calculates sentiment, routes
* detractors for follow-up, and persists all scores.
*/
webhook nps_response {
label: "NPS Response"
schema: @json {
{
"type": "object",
"required": ["email", "score", "feedback"],
"properties": {
"email": { "type": "string", "format": "email" },
"score": { "type": "number", "minimum": 0, "maximum": 10 },
"feedback": { "type": "string" }
}
}
}
}
workflow process_nps {
label: "Process NPS Response"
root {
type: code
label: "Parse response"
code: @ts {
const input = context.nodes.root.input
const category = input.score >= 9 ? "promoter" : input.score >= 7 ? "passive" : "detractor"
return {
email: input.email,
score: input.score,
feedback: input.feedback,
category: category
}
}
outputSchema: @json {
{
"type": "object",
"properties": {
"email": { "type": "string" },
"score": { "type": "number" },
"feedback": { "type": "string" },
"category": { "type": "string" }
}
}
}
}
node route {
type: switch
label: "Route by category"
cases: ["detractor", "other"]
router: @ts {
if (context.nodes.root.output.category === "detractor") return "detractor"
return "other"
}
}
node analyze_detractor {
type: ai
label: "Analyze detractor feedback"
kind: object
model: "google/gemini-2.5-flash"
prompt: @ts {
return "A customer gave an NPS score of " + context.nodes.root.output.score + "/10. Analyze their feedback and suggest a recovery action.\n\nFeedback: " + context.nodes.root.output.feedback
}
schema: @json {
{
"type": "object",
"required": ["root_cause", "suggested_action"],
"properties": {
"root_cause": { "type": "string" },
"suggested_action": { "type": "string" },
"urgency": { "type": "string", "enum": ["high", "medium", "low"] }
}
}
}
}
node followup_email {
type: email
label: "Send follow-up"
from: @ts { return "[email protected]" }
to: @ts { return "[email protected]" }
subject: @ts { return "We heard you - let us make it right" }
text: @ts {
return "We noticed your recent experience was not up to our standards. We take your feedback seriously and would love to chat about how we can improve. Reply to this email and we will get back to you within 24 hours."
}
}
node log_score {
type: code
label: "Log score"
code: @ts {
return {
email: context.nodes.root.output.email,
score: context.nodes.root.output.score,
category: context.nodes.root.output.category
}
}
}
flow {
root -> route
route -["detractor"]-> analyze_detractor
analyze_detractor -> followup_email
route -["other"]-> log_score
}
}
stream nps_scores {
label: "NPS scores"
workflow: process_nps
version: v1
versions: {
v1 {
schema: @json {
{
"type": "object",
"required": ["email", "score", "category"],
"properties": {
"email": { "type": "string" },
"score": { "type": "number" },
"category": { "type": "string" }
}
}
}
condition: @ts { return true }
prepare: @ts {
const logged = context.output.log_score
if (logged) return logged
return {
email: context.nodes.root.output.email,
score: context.nodes.root.output.score,
category: context.nodes.root.output.category
}
}
}
}
}
trigger on_nps {
webhook:nps_response -> process_nps
enabled: true
}
Flow
Trigger to workflow
Workflow nodes