Code Task¶
Overview¶
The Code Task executes custom JavaScript code within your workflow. Use it for complex calculations, data transformations, conditional logic, and operations that aren't available in standard tasks.
When to use this task:
- Complex mathematical calculations
- Advanced data transformation and parsing
- Custom business logic implementation
- JSON manipulation and restructuring
- String processing and formatting
- Array operations and filtering
- Date/time calculations
- API response processing
Key Features:
- Full JavaScript ES6+ support
- Access to all workflow variables
- Return multiple output fields
- NPM libraries available
- Timeout protection
- Error handling and debugging
- Synchronous execution
[SCREENSHOT NEEDED: Code task editor showing JavaScript code with syntax highlighting]
Quick Start¶
- Add Code task to workflow
- Write JavaScript code
- Access workflow data via
inputobject - Return results via
returnstatement - Test execution
- Save
Simple Example:
// Calculate discount
const total = parseFloat(input.task_46001_order_total);
const discount = total > 100 ? total * 0.1 : 0;
return {
discount_amount: discount,
final_total: total - discount
};
Accessing Workflow Data¶
The input Object¶
All workflow variables are available in the input object:
Syntax:
Example:
// From Match to Client task (ID: 15001)
const email = input.task_15001_email;
const firstName = input.task_15001_first_name;
const contactId = input.task_15001_contact_id;
// From Webhook In task (ID: 46001)
const orderTotal = parseFloat(input.task_46001_total);
const items = JSON.parse(input.task_46001_items || '[]');
Type Conversion¶
Workflow variables come as strings. Convert as needed:
Numbers:
const age = parseInt(input.task_15001_age);
const price = parseFloat(input.task_46001_price);
const quantity = Number(input.task_46001_quantity);
Booleans:
const isVIP = input.task_15001_is_vip === 'true';
const hasDiscount = Boolean(input.task_46001_discount_code);
Dates:
JSON:
const metadata = JSON.parse(input.task_46001_metadata || '{}');
const items = JSON.parse(input.task_46001_items || '[]');
Handling Missing Data¶
Always handle potentially undefined values:
// Safe access with defaults
const phone = input.task_15001_phone || '';
const score = parseInt(input.task_15001_score) || 0;
const tags = input.task_15001_tags || 'Unknown';
// Check before using
if (input.task_15001_email) {
const email = input.task_15001_email.toLowerCase();
}
// Optional chaining (ES2020)
const value = input.task_15001?.custom_field ?? 'default';
Returning Data¶
Return Object¶
Return an object with your output fields:
Example:
return {
calculated_total: 150.50,
is_eligible: true,
status_message: 'Approved',
processed_date: new Date().toISOString()
};
Access in next task:
Multiple Return Values¶
Return as many fields as needed:
const subtotal = 100;
const tax = subtotal * 0.15;
const shipping = 10;
const total = subtotal + tax + shipping;
return {
subtotal: subtotal,
tax: tax,
tax_rate: 0.15,
shipping: shipping,
total: total,
currency: 'ZAR'
};
Return Arrays¶
const emails = ['john@example.com', 'jane@example.com'];
return {
email_list: JSON.stringify(emails),
count: emails.length
};
Note: Stringify arrays/objects for return.
Return Early¶
Exit function early based on conditions:
// Validation check
if (!input.task_15001_email) {
return {
error: true,
message: 'Email required'
};
}
// Continue with normal logic
const email = input.task_15001_email.toLowerCase();
return {
email: email,
domain: email.split('@')[1]
};
Common Operations¶
String Manipulation¶
const name = input.task_15001_name;
return {
uppercase: name.toUpperCase(),
lowercase: name.toLowerCase(),
title_case: name.replace(/\b\w/g, l => l.toUpperCase()),
initials: name.split(' ').map(n => n[0]).join(''),
length: name.length,
first_word: name.split(' ')[0]
};
Array Operations¶
const items = JSON.parse(input.task_46001_items);
return {
total_items: items.length,
first_item: items[0],
last_item: items[items.length - 1],
item_names: items.map(i => i.name).join(', '),
total_price: items.reduce((sum, i) => sum + i.price, 0),
expensive_items: items.filter(i => i.price > 50).length
};
Date Calculations¶
const orderDate = new Date(input.task_46001_order_date);
const today = new Date();
const daysSince = Math.floor((today - orderDate) / (1000 * 60 * 60 * 24));
return {
order_date: orderDate.toISOString(),
days_since_order: daysSince,
is_recent: daysSince <= 7,
formatted_date: orderDate.toLocaleDateString('en-ZA')
};
Mathematical Calculations¶
const quantity = parseInt(input.task_46001_quantity);
const price = parseFloat(input.task_46001_price);
const discount = parseFloat(input.task_46001_discount) || 0;
const subtotal = quantity * price;
const discountAmount = subtotal * (discount / 100);
const tax = (subtotal - discountAmount) * 0.15;
const total = subtotal - discountAmount + tax;
return {
quantity: quantity,
unit_price: price.toFixed(2),
subtotal: subtotal.toFixed(2),
discount_percent: discount,
discount_amount: discountAmount.toFixed(2),
tax: tax.toFixed(2),
total: total.toFixed(2)
};
Conditional Logic¶
const score = parseInt(input.task_15001_lead_score);
const status = input.task_15001_status;
const tags = input.task_15001_tags || '';
let rating, priority;
if (score >= 80) {
rating = 'Hot';
priority = 1;
} else if (score >= 50) {
rating = 'Warm';
priority = 2;
} else {
rating = 'Cold';
priority = 3;
}
const isVIP = tags.includes('VIP') || tags.includes('Premium');
const needsFollowUp = rating === 'Hot' || isVIP;
return {
lead_rating: rating,
priority: priority,
is_vip: isVIP,
needs_followup: needsFollowUp,
recommended_action: needsFollowUp ? 'Call immediately' : 'Email follow-up'
};
JSON Processing¶
const rawData = JSON.parse(input.task_46001_webhook_data);
// Extract nested fields
const customerId = rawData.customer?.id || 'unknown';
const items = rawData.order?.items || [];
const shipping = rawData.order?.shipping?.address || {};
// Transform structure
const simplified = {
customer_id: customerId,
customer_email: rawData.customer?.email,
order_total: items.reduce((sum, item) => sum + (item.price * item.quantity), 0),
item_count: items.length,
shipping_city: shipping.city,
shipping_country: shipping.country
};
return simplified;
Real-World Examples¶
Example 1: Lead Scoring Algorithm¶
Workflow: 1. CRM Trigger - Contact updated 2. Code Task - Calculate score 3. Edit Client - Update score
Code:
// Get contact data
const email = input.task_47001_email || '';
const phone = input.task_47001_phone || '';
const company = input.task_47001_company || '';
const tags = input.task_47001_tags || '';
const formSubmissions = parseInt(input.task_47001_custom_form_count) || 0;
const emailOpens = parseInt(input.task_47001_custom_email_opens) || 0;
// Calculate score
let score = 0;
// Contact completeness
if (email) score += 10;
if (phone) score += 10;
if (company) score += 15;
// Email quality
if (email && !email.includes('@gmail.com') && !email.includes('@yahoo.com')) {
score += 20; // Business email
}
// Engagement
score += formSubmissions * 5;
score += emailOpens * 2;
// Tags
if (tags.includes('Enterprise')) score += 30;
if (tags.includes('Decision Maker')) score += 25;
// Cap at 100
score = Math.min(score, 100);
// Determine grade
let grade;
if (score >= 80) grade = 'A';
else if (score >= 60) grade = 'B';
else if (score >= 40) grade = 'C';
else grade = 'D';
return {
lead_score: score,
lead_grade: grade,
is_qualified: score >= 60,
recommendation: score >= 80 ? 'Contact immediately' :
score >= 60 ? 'Add to nurture' :
'Continue monitoring'
};
Example 2: E-commerce Order Processing¶
Workflow: 1. Webhook In - Order received 2. Code Task - Process order 3. MySQL Query - Store in database
Code:
const orderData = JSON.parse(input.task_46001_body);
// Extract order info
const items = orderData.line_items || [];
const customer = orderData.customer || {};
const shipping = orderData.shipping_address || {};
// Calculate totals
const subtotal = items.reduce((sum, item) => {
return sum + (parseFloat(item.price) * parseInt(item.quantity));
}, 0);
const tax = subtotal * 0.15; // 15% VAT
const shippingCost = subtotal > 500 ? 0 : 50; // Free shipping over R500
const total = subtotal + tax + shippingCost;
// Determine shipping method
let shippingMethod, estimatedDays;
if (subtotal > 1000) {
shippingMethod = 'Express';
estimatedDays = 2;
} else {
shippingMethod = 'Standard';
estimatedDays = 5;
}
// Generate order reference
const today = new Date();
const orderRef = `ORD-${today.getFullYear()}${String(today.getMonth()+1).padStart(2,'0')}${String(today.getDate()).padStart(2,'0')}-${Math.random().toString(36).substr(2,6).toUpperCase()}`;
return {
order_reference: orderRef,
customer_email: customer.email || '',
customer_name: `${customer.first_name} ${customer.last_name}`,
item_count: items.length,
subtotal: subtotal.toFixed(2),
tax: tax.toFixed(2),
shipping_cost: shippingCost.toFixed(2),
total: total.toFixed(2),
shipping_method: shippingMethod,
estimated_delivery_days: estimatedDays,
shipping_city: shipping.city || '',
requires_insurance: total > 5000,
priority: total > 2000 ? 'High' : 'Normal'
};
Example 3: Email Domain Analysis¶
Workflow: 1. Website Form 2. Code Task - Analyze email 3. If Task - Route based on domain type
Code:
const email = (input.task_55001_email || '').toLowerCase();
if (!email || !email.includes('@')) {
return {
error: true,
message: 'Invalid email'
};
}
const [localPart, domain] = email.split('@');
// Free email providers
const freeProviders = [
'gmail.com', 'yahoo.com', 'outlook.com', 'hotmail.com',
'live.com', 'icloud.com', 'aol.com', 'mail.com'
];
const isFree = freeProviders.includes(domain);
// Disposable email detection
const disposableDomains = [
'tempmail.com', '10minutemail.com', 'guerrillamail.com'
];
const isDisposable = disposableDomains.includes(domain);
// Extract company info
const domainParts = domain.split('.');
const companyName = domainParts[0];
return {
email: email,
domain: domain,
local_part: localPart,
is_free_email: isFree,
is_business_email: !isFree && !isDisposable,
is_disposable: isDisposable,
likely_company: !isFree ? companyName : 'Unknown',
email_type: isDisposable ? 'Disposable' :
isFree ? 'Personal' : 'Business',
lead_quality: isDisposable ? 'Low' :
isFree ? 'Medium' : 'High'
};
Example 4: Date Range Calculator¶
Workflow: 1. Schedule Trigger - Monthly report 2. Code Task - Calculate date range 3. MySQL Query - Query data for range
Code:
const today = new Date();
// Last month
const lastMonthStart = new Date(today.getFullYear(), today.getMonth() - 1, 1);
const lastMonthEnd = new Date(today.getFullYear(), today.getMonth(), 0);
// This quarter
const quarter = Math.floor(today.getMonth() / 3);
const quarterStart = new Date(today.getFullYear(), quarter * 3, 1);
// Last 7/30/90 days
const last7Days = new Date(today.getTime() - (7 * 24 * 60 * 60 * 1000));
const last30Days = new Date(today.getTime() - (30 * 24 * 60 * 60 * 1000));
const last90Days = new Date(today.getTime() - (90 * 24 * 60 * 60 * 1000));
// Format as YYYY-MM-DD
function formatDate(date) {
return date.toISOString().split('T')[0];
}
return {
today: formatDate(today),
last_month_start: formatDate(lastMonthStart),
last_month_end: formatDate(lastMonthEnd),
last_month_name: lastMonthStart.toLocaleString('en-US', { month: 'long' }),
quarter_start: formatDate(quarterStart),
last_7_days: formatDate(last7Days),
last_30_days: formatDate(last30Days),
last_90_days: formatDate(last90Days),
current_year: today.getFullYear(),
current_month: today.getMonth() + 1
};
Example 5: Response Parser & Validator¶
Workflow: 1. Webhook Out - Call external API 2. Code Task - Parse and validate response 3. If Task - Handle success/failure
Code:
// Parse API response
let response;
try {
response = JSON.parse(input.task_1001_response_body || '{}');
} catch (e) {
return {
success: false,
error: 'Invalid JSON response',
error_details: e.message
};
}
// Validate required fields
const requiredFields = ['id', 'status', 'email'];
const missingFields = requiredFields.filter(field => !response[field]);
if (missingFields.length > 0) {
return {
success: false,
error: 'Missing required fields',
missing: missingFields.join(', ')
};
}
// Extract and transform data
const statusCode = parseInt(input.task_1001_response_code);
const isSuccess = statusCode >= 200 && statusCode < 300;
return {
success: isSuccess,
api_id: response.id,
api_status: response.status,
email: response.email,
created_at: response.created_at || new Date().toISOString(),
external_url: `https://system.com/record/${response.id}`,
status_code: statusCode,
needs_retry: !isSuccess && statusCode !== 400
};
Available Libraries¶
Standard JavaScript¶
Full ES6+ support: - Array methods (map, filter, reduce, etc.) - Object methods (keys, values, entries, etc.) - String methods (split, replace, trim, etc.) - Math functions - Date operations - JSON parse/stringify - Regular expressions
Lodash¶
Utility library available as _:
const _ = require('lodash');
const items = JSON.parse(input.task_46001_items);
return {
unique_tags: _.uniq(items.map(i => i.tag)),
grouped: _.groupBy(items, 'category'),
max_price: _.maxBy(items, 'price')?.price || 0,
chunk_size: _.chunk(items, 10).length
};
Moment.js¶
Date manipulation (use built-in Date when possible):
const moment = require('moment');
const date = moment(input.task_46001_date);
return {
formatted: date.format('YYYY-MM-DD'),
from_now: date.fromNow(),
is_past: date.isBefore(moment()),
day_of_week: date.format('dddd')
};
Best Practices¶
Performance¶
- Keep code simple - Complex operations slow workflow
- Avoid large loops - Process in batches if needed
- Cache calculations - Don't recalculate same values
- Use built-in methods - Faster than custom implementations
- Limit external library use - Adds overhead
Error Handling¶
-
Try-catch blocks - Handle JSON parsing errors
-
Validate inputs - Check for undefined/null
- Return error flags - Indicate failure in output
- Provide error messages - Help debug issues
- Set defaults - Use fallback values
Code Quality¶
- Comment complex logic - Explain why, not what
- Use descriptive names -
leadScorenotls - Keep functions focused - One task per Code task
- Format consistently - Readable code is maintainable
- Test thoroughly - Verify edge cases
Security¶
- Sanitize input - Don't trust external data
- Avoid eval() - Never use eval() or Function()
- Limit scope - Only access needed data
- Don't log sensitive data - Avoid console.log of passwords/keys
- Validate outputs - Ensure safe data types
Troubleshooting¶
Code Not Executing¶
Check: 1. Syntax errors in code? 2. Missing return statement? 3. Timeout exceeded? (max 30 seconds) 4. Task enabled in workflow?
View execution history for error details
Undefined Values¶
Error: Cannot read property 'X' of undefined
Causes: - Input field doesn't exist - Previous task didn't run - Typo in field name
Solution:
Type Errors¶
Error: NaN or incorrect calculations
Cause: Didn't convert string to number
Solution:
Return Not Working¶
Check: - Return statement exists? - Returning object (not array/string directly)? - No code after return?
// ✓ Correct
return { field: value };
// ✗ Wrong
return value; // Must be object
return [1, 2, 3]; // Must be object
Frequently Asked Questions¶
Can I make API calls from Code task?¶
No, Code task runs synchronously. Use Webhook Out task for API calls, then Code task to process response.
What's the timeout?¶
30 seconds maximum execution time.
Can I use async/await?¶
No, Code task is synchronous only.
Can I access previous Code task outputs?¶
Yes: input.task_42001_output_field
Can I import NPM packages?¶
Limited selection available (lodash, moment). Contact support for additional libraries.
How do I debug?¶
- View execution history
- Check error messages
- Add intermediate return values
- Test code in browser console first
Can I modify workflow variables?¶
No, you can only read inputs and return new outputs.
Related Tasks¶
- Variable Task - Store Code task results
- If Task - Conditional logic (simpler alternative)
- Loop Task - Process arrays from Code task
- MySQL Query - Database operations alternative
- Webhook Out - External API calls before Code task