Branching Status Snippets
Custom Code Snippets — Branching & Status
Copy-paste examples for emitting a clean status value that a downstream Condition step can branch on. The pattern is always the same: do the comparison in code, return a single status string, and let the Condition step handle the routing.
Why split logic this way? It keeps the conditions readable in the workflow UI ("if status = ‘platinum'"), and it lets you tweak the cutoffs without rebuilding nested condition trees.
Tier a customer by lifetime value
const ltv = Number(record.lifetime_value) || 0;
let tier;
if (ltv >= 10000) tier = "platinum";
else if (ltv >= 2500) tier = "gold";
else if (ltv >= 500) tier = "silver";
else tier = "bronze";
returnData("tier", tier);
returnData("tier_label", Str.capitalize(tier));
A downstream condition node can branch on tier.
Welcome message by user age in app
const created = (loggedInUser && loggedInUser.created_at) || null;
if (!created) {
returnData("status", "anonymous");
return;
}
const days = DateTime.diffDays(created, DateTime.now());
let status, copy;
if (days < 1) {
status = "first_day";
copy = `Welcome! Let's set up your account.`;
} else if (days < 30) {
status = "new";
copy = `Welcome back, ${Str.capitalize(loggedInUser.first_name || "friend")}.`;
} else if (days < 365) {
status = "active";
copy = `Good to see you again.`;
} else {
status = "veteran";
copy = `Thanks for being with us ${Num.round(days / 365, 1)} years!`;
}
returnData("status", status);
returnData("copy", copy);
Coalesce — first non-empty value wins
const display = params["preferred_name"]
|| record.nickname
|| record.first_name
|| loggedInUser.email
|| "there";
returnData("display_name", display);
Priority from keywords in the body
// Auto-priority for support tickets, before/while waiting for AI triage.
const text = (record.body || "").toLowerCase();
let priority;
if (/(outage|down|cannot login|losing money)/.test(text)) priority = "high";
else if (/(slow|error|broken|bug)/.test(text)) priority = "medium";
else priority = "low";
returnData("priority", priority);
Validate a state-machine transition
// Inputs: from (record_val current status), to (custom_val proposed status)
const allowed = {
draft: ["submitted"],
submitted: ["approved", "rejected"],
approved: ["shipped"],
rejected: ["draft"],
shipped: []
};
const from = String(params["from"] || record.status || "");
const to = String(params["to"] || "");
const okMoves = allowed[from] || [];
const ok = okMoves.includes(to);
returnData("ok", ok);
returnData("status", ok ? to : from);
returnData("error", ok ? null : `Cannot move ${from} -> ${to}. Allowed: ${okMoves.join(", ") || "(none)"}`);
Route a lead by region
// Sets `team` so the next step can assign the right group.
const country = String(record.country || "").toUpperCase();
const state = String(record.state || "").toUpperCase();
let team;
if (country !== "US") team = "international";
else if (["CA","WA","OR","NV","AZ"].includes(state)) team = "west";
else if (["TX","NY","NJ","MA","FL"].includes(state)) team = "east";
else team = "central";
returnData("team", team);
Deal stage from amount + days open
const amount = Number(record.amount) || 0;
const daysOpen = record.opened_at
? DateTime.diffDays(record.opened_at, DateTime.now())
: 0;
let stage;
if (amount >= 50000 && daysOpen < 30) stage = "hot_enterprise";
else if (amount >= 50000) stage = "stalled_enterprise";
else if (daysOpen > 60) stage = "stale";
else if (daysOpen < 7) stage = "fresh";
else stage = "active";
returnData("stage", stage);
Combine flags into a single status
// Inputs: paid, shipped, signed_for (all booleans)
const paid = !!params["paid"];
const shipped = !!params["shipped"];
const signed = !!params["signed_for"];
let status;
if (signed) status = "delivered";
else if (shipped) status = "in_transit";
else if (paid) status = "awaiting_shipment";
else status = "awaiting_payment";
returnData("status", status);
Letter grade from a numeric score
const score = Number(params["score"]) || 0;
let letter;
if (score >= 90) letter = "A";
else if (score >= 80) letter = "B";
else if (score >= 70) letter = "C";
else if (score >= 60) letter = "D";
else letter = "F";
returnData("letter", letter);
returnData("passed", score >= 60);
Multi-criteria approval check
// Auto-approve a refund only if all conditions hold.
const amount = Number(record.amount) || 0;
const orderAge = record.ordered_at ? DateTime.diffDays(record.ordered_at, DateTime.now()) : 999;
const reason = String(record.reason || "").toLowerCase();
const reasons = [];
if (amount > 100) reasons.push("amount over $100");
if (orderAge > 30) reasons.push("order over 30 days old");
if (!["damaged","wrong_item","not_received"].includes(reason)) reasons.push("reason needs review");
const autoApprove = reasons.length === 0;
returnData("auto_approve", autoApprove);
returnData("review_reasons", reasons);
returnData("decision_branch", autoApprove ? "approve" : "manual_review");
Feature-flag a user into a beta cohort
// Stable bucketing — the same user always lands in the same group.
const id = String(loggedInUser.id || "");
const sample = Number(getAppVariable("beta_sample_pct", 10)); // % rollout
let hash = 0;
for (let i = 0; i < id.length; i++) hash = ((hash << 5) - hash + id.charCodeAt(i)) | 0;
const bucket = Math.abs(hash) % 100;
const inBeta = bucket < sample;
returnData("in_beta", inBeta);
returnData("variant", inBeta ? "beta" : "control");
Fail-open vs fail-closed branching
// When an upstream API fails, decide whether to keep going or stop.
const upstream = params["api_response"] || {};
const ok = upstream && upstream.status === "ok";
if (ok) {
returnData("branch", "continue");
returnData("data", upstream.data || {});
return;
}
// Fail-closed: stop, alert. Switch to "continue" with defaults if you'd rather fail-open.
console.error("Upstream failed", upstream);
returnData("branch", "halt");
returnData("error", upstream.error || "Upstream did not return ok");
We'd love to hear your feedback.