Examples
Four Function node examples: JSON transformation, custom pricing engine, multi-rule data validation, and string/regex extraction.
Example 1: Parse and Transform a Complex JSON Payload
// Script property:
const raw = context.input;
// Flatten the nested order response into a flat document
const order = raw.data.order;
const customer = raw.data.order.customer;
const items = raw.data.order.line_items;
return {
order_id: order.id,
order_date: order.created_at,
customer_id: customer.id,
customer_email: customer.email,
customer_name: `${customer.first_name} ${customer.last_name}`.trim(),
total_amount: order.total_price,
currency: order.currency,
item_count: items.length,
items: items.map(item => ({
sku: item.variant_id,
title: item.title,
quantity: item.quantity,
unit_price: item.price,
subtotal: (item.quantity * parseFloat(item.price)).toFixed(2)
})),
fulfillment_status: order.fulfillment_status ?? "pending",
tags: order.tags ? order.tags.split(",").map(t => t.trim()) : []
};
Expected outcome: The deeply nested Shopify-style order response is transformed into a clean, flat MongoDB document. The downstream MongoDB/insertOne node receives exactly the structure required — no additional DataMapping needed.
Example 2: Custom Business Logic Calculation (Pricing Engine)
// Script property:
const cart = context.vars.cart_items;
const pricingTier = context.vars.customer_tier; // "bronze", "silver", "gold", "platinum"
const promoCode = context.vars.promo_code;
const region = context.vars.customer_region;
// Tier discount rates
const tierDiscounts = { bronze: 0, silver: 0.05, gold: 0.10, platinum: 0.15 };
const tierDiscount = tierDiscounts[pricingTier] ?? 0;
// Calculate subtotal
const subtotal = cart.reduce((sum, item) => sum + (item.price * item.quantity), 0);
// Apply tier discount
let discountAmount = subtotal * tierDiscount;
// Apply promo code (if applicable)
const promoCodes = { "SAVE10": 0.10, "LAUNCH20": 0.20, "VIP30": 0.30 };
const promoDiscount = promoCodes[promoCode] ?? 0;
const promoAmount = subtotal * promoDiscount;
// Total discount (capped at 40% to prevent stacking abuse)
const totalDiscountRate = Math.min(tierDiscount + promoDiscount, 0.40);
const totalDiscount = subtotal * totalDiscountRate;
// Tax rates by region
const taxRates = { "US-CA": 0.0975, "US-NY": 0.08875, "UK": 0.20, "EU": 0.21 };
const taxRate = taxRates[region] ?? 0;
const discountedSubtotal = subtotal - totalDiscount;
const taxAmount = discountedSubtotal * taxRate;
const finalTotal = discountedSubtotal + taxAmount;
return {
subtotal: parseFloat(subtotal.toFixed(2)),
tier_discount_pct: (tierDiscount * 100).toFixed(0) + "%",
promo_discount_pct: (promoDiscount * 100).toFixed(0) + "%",
total_discount: parseFloat(totalDiscount.toFixed(2)),
discounted_subtotal: parseFloat(discountedSubtotal.toFixed(2)),
tax_rate: taxRate,
tax_amount: parseFloat(taxAmount.toFixed(2)),
final_total: parseFloat(finalTotal.toFixed(2)),
currency: "USD",
pricing_tier: pricingTier,
promo_applied: promoCode || null
};
Expected outcome: A complete price breakdown object is returned. The downstream order creation node receives
data.final_total as the charge amount. All discount and tax logic is encapsulated in one testable script, making it easy to update pricing rules without modifying the workflow structure.Example 3: Data Validation with Multiple Rules Returning Structured Errors
// Script property:
const data = context.input;
const errors = [];
// Required field checks
if (!data.email || !data.email.includes("@")) {
errors.push({ field: "email", code: "INVALID_EMAIL", message: "A valid email address is required." });
}
if (!data.first_name || data.first_name.trim().length < 2) {
errors.push({ field: "first_name", code: "TOO_SHORT", message: "First name must be at least 2 characters." });
}
if (!data.phone) {
errors.push({ field: "phone", code: "MISSING", message: "Phone number is required." });
}
// Business rule checks
if (data.age !== undefined && (data.age < 18 || data.age > 120)) {
errors.push({ field: "age", code: "OUT_OF_RANGE", message: "Age must be between 18 and 120." });
}
if (data.country && !["US", "UK", "CA", "AU"].includes(data.country)) {
errors.push({ field: "country", code: "UNSUPPORTED_REGION", message: `Country '${data.country}' is not supported.` });
}
if (data.credit_limit !== undefined && data.credit_limit > 50000 && data.account_type !== "premium") {
errors.push({ field: "credit_limit", code: "LIMIT_EXCEEDED", message: "Credit limits above $50,000 require a premium account type." });
}
return {
valid: errors.length === 0,
error_count: errors.length,
errors: errors,
validated_at: new Date().toISOString()
};
Expected outcome: The script always routes to the success port — the validation result is returned as structured data. A downstream IfCondition node checks
data.valid === true to decide whether to proceed with the insert or route to a rejection handler that sends the data.errors array back to the user.Example 4: String Manipulation and Regex Extraction
// Script property:
const rawAddress = context.input.address_text || "";
// Normalise whitespace
const cleaned = rawAddress.replace(/\s+/g, " ").trim();
// Extract US ZIP code (5 or 9 digit)
const zipMatch = cleaned.match(/\b(\d{5}(?:-\d{4})?)\b/);
const postalCode = zipMatch ? zipMatch[1] : null;
// Extract US state abbreviation (2 uppercase letters before ZIP)
const stateMatch = cleaned.match(/\b([A-Z]{2})\s+\d{5}/);
const state = stateMatch ? stateMatch[1] : null;
// Extract city (word(s) before state abbreviation)
const cityMatch = state
? cleaned.match(new RegExp(`([A-Za-z\\s]+?)\\s*,?\\s*${state}\\b`))
: null;
const city = cityMatch ? cityMatch[1].trim() : null;
// Remainder is street address (everything before city)
const streetEnd = city ? cleaned.indexOf(city) : cleaned.length;
const street = cleaned.slice(0, streetEnd).replace(/,$/, "").trim();
// Generate URL-safe slug from company name (for subdomain use)
const companySlug = (context.vars.company_name || "")
.toLowerCase()
.replace(/[^a-z0-9]+/g, "-")
.replace(/^-|-$/g, "");
return {
raw: rawAddress,
street: street || null,
city: city || null,
state: state || null,
postal_code: postalCode || null,
parsed: !!(street && city && state && postalCode),
company_slug: companySlug
};
Expected outcome: A free-text address like "123 Main St, Springfield, IL 62701" is parsed into
{ street: "123 Main St", city: "Springfield", state: "IL", postal_code: "62701", parsed: true }. The parsed boolean lets downstream nodes detect incomplete addresses and route to a data-quality review step.