Skip to content

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

  1. Add Code task to workflow
  2. Write JavaScript code
  3. Access workflow data via input object
  4. Return results via return statement
  5. Test execution
  6. 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:

input.task_ID_field_name

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:

const orderDate = new Date(input.task_46001_order_date);
const now = new Date();

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:

return {
  field_name: value,
  another_field: anotherValue
};

Example:

return {
  calculated_total: 150.50,
  is_eligible: true,
  status_message: 'Approved',
  processed_date: new Date().toISOString()
};

Access in next task:

{{task_42001_calculated_total}}
{{task_42001_is_eligible}}
{{task_42001_status_message}}

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

  1. Keep code simple - Complex operations slow workflow
  2. Avoid large loops - Process in batches if needed
  3. Cache calculations - Don't recalculate same values
  4. Use built-in methods - Faster than custom implementations
  5. Limit external library use - Adds overhead

Error Handling

  1. Try-catch blocks - Handle JSON parsing errors

    try {
      const data = JSON.parse(input.task_x_field);
    } catch (e) {
      return { error: true, message: e.message };
    }
    

  2. Validate inputs - Check for undefined/null

  3. Return error flags - Indicate failure in output
  4. Provide error messages - Help debug issues
  5. Set defaults - Use fallback values

Code Quality

  1. Comment complex logic - Explain why, not what
  2. Use descriptive names - leadScore not ls
  3. Keep functions focused - One task per Code task
  4. Format consistently - Readable code is maintainable
  5. Test thoroughly - Verify edge cases

Security

  1. Sanitize input - Don't trust external data
  2. Avoid eval() - Never use eval() or Function()
  3. Limit scope - Only access needed data
  4. Don't log sensitive data - Avoid console.log of passwords/keys
  5. 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:

const value = input.task_x_field || 'default';
if (input.task_x_field) {
  // Use value
}

Type Errors

Error: NaN or incorrect calculations

Cause: Didn't convert string to number

Solution:

const value = parseFloat(input.task_x_field) || 0;

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?

  1. View execution history
  2. Check error messages
  3. Add intermediate return values
  4. Test code in browser console first

Can I modify workflow variables?

No, you can only read inputs and return new outputs.


  • 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