Skip to content

9.2 Writing Custom Code

You understand what the Custom Code Node can do. Now let's actually build one. This section shows you how to add a Custom Code column and write your first script.


Step-by-Step: Adding a Custom Code Column

Step 1: Open Add Column Modal

From your taible:

  1. Look for the "+" button in the column headers

    • Usually at the right end of your columns
    • Or next to an existing column
  2. Click the "+" button

    • Add column modal opens
    • Shows available column types

Add Column

Categories:

  • All
  • Data
  • AI & LLM
  • Development
  • Communication

Column Types:

Code
Run custom code
🔧
Template
Combine text and data

Step 2: Find Custom Code Column Type

Method 1: Search

1. Type "code" or "custom" in search box
2. Result shows "Code" column type:
Code
Run custom code
Select →
3. Click "Code" to continue

Method 2: Browse by Category

1. Click "Development" category:
  • All
  • Data
  • AI & LLM
  • Development ←
  • Communication
2. Find "Code" in the list:
Code
Run custom code
🔧
Template
Combine text and data
3. Click "Code" to continue

Step 3: Column Configuration Opens

After clicking "Code":

Configuration panel appears with settings:

Configure Column

Node Configuration

To access data from other columns, press CTRL + SPACE or start typing the column name.

Configuration Fields Explained

Field 1: Column Name

Label: "Column Name"

Purpose: Internal identifier for the column

Rules:

  • No spaces (use underscores)
  • Lowercase recommended
  • Alphanumeric and underscores only
  • Must be unique in taible

Examples:

  • lead_score
  • custom_validation
  • calculate_discount
  • Lead Score (spaces not allowed)
  • lead-score (hyphens not allowed)

Use in code: Access with the system variable for that column


Field 2: Display Label

Label: "Display Label"

Purpose: Human-readable name shown in column header

Rules:

  • Can contain spaces
  • Any characters allowed
  • Displays in column header

Examples:

  • "Lead Score"
  • "Custom Validation"
  • "Calculate Discount"

User sees this in the taible grid


Field 3: Output Type (Optional)

Label: "Output type"

Purpose: Specifies the data type returned by your code

Default: any (accepts any type)

When to specify:

  • Type safety
  • Better autocomplete in dependencies
  • Documentation

Simple types:

String
Integer
Boolean
Double

Collection types:

List<String>
List<Map<String, Object>>
Map<String, Object>

Custom types (if defined in your system):

LeadScore
ValidationResult
CompanyData

Leave as any if you're not sure—it will work fine!


Field 4: Code to be executed

Label: "Code to be executed"

The main event: This is where you write your Groovy code

Editor features:

  • Line numbers: Easy reference
  • Syntax highlighting: Color-coded
  • Autocomplete: Access column names (via CTRL + SPACE)
  • Multi-line: Write complex scripts
  • Current line highlight: Know where you are
  • Template badges: See column references as green badges
Code Editor Features:
1
2
3
4
5
6
// Calculate total with tax
def quantity = Quantity
def price = Unit Price
def total = quantity * price * 1.1
return total
Line Numbers
See line 1, 2, 3...
Syntax Highlighting
Keywords in blue, numbers in orange
Column References
Green badges show column names
Current Line Highlight
Line 1 is highlighted
Autocomplete
Press CTRL + SPACE
Multi-line
Write complex logic

This is your canvas for custom logic!


Writing Your First Custom Code

Example 1: Simple Calculation

Goal: Calculate order total from quantity and price

Goal: Calculate order total from quantity and price
1
2
3
4
5
6
7
def quantity = Quantity
def unitPrice = Unit Price
def subtotal = quantity * unitPrice
def tax = subtotal * 0.1
def total = subtotal + tax
return total
Configuration:
• Column name: order_total
• Display label: Order Total
• Output type: Double

How to enter this:

  1. Click in "Code to be executed" editor

  2. Type or paste the code

  3. Set output type: Double (it's a number)

  4. Set column name: order_total

  5. Set display label: "Order Total"

  6. Click "Save"

Result: New column appears, calculates total for each row


Example 2: String Concatenation

Goal: Combine first name and last name

Goal: Combine first name and last name
1
2
3
4
def firstName = First Name
def lastName = Last Name
return "${firstName} ${lastName}"

Configuration:

  • Column name: full_name
  • Display label: "Full Name"
  • Output type: String

Tip: This is simple enough that you could use a template instead! But it demonstrates the basics.


Example 3: Conditional Logic

Goal: Assign lead tier based on score

Goal: Assign lead tier based on score
1
2
3
4
5
6
7
8
9
10
11
def score = Lead Score
if (score >= 80) {
  return "A - Hot Lead"
} else if (score >= 60) {
  return "B - Warm Lead"
} else if (score >= 40) {
  return "C - Cold Lead"
} else {
  return "D - Unqualified"
}

Configuration:

  • Column name: lead_tier
  • Display label: "Lead Tier"
  • Output type: String

Example 4: Return an Object

Goal: Return structured data (multiple fields)

Goal: Return structured data (multiple fields)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def companySize = Company Size
def revenue = Annual Revenue
def tier = 'Small'
def priority = 'Low'
if (companySize > 500 && revenue > 10000000) {
  tier = 'Enterprise'
  priority = 'High'
} else if (companySize > 50) {
  tier = 'Mid-Market'
  priority = 'Medium'
}
return [
  tier: tier,
  priority: priority,
  qualified: priority == 'High',
  category: "${tier} - ${priority}"
]
Result in cell:
{
  "tier": "Enterprise",
  "priority": "High",
  "qualified": true,
  "category": "Enterprise - High"
}

Configuration:

  • Column name: company_classification
  • Display label: "Company Classification"
  • Output type: Map<String, Object>

Result: Cell displays as JSON object

Access nested data in other columns using the autocomplete—just start typing the column name and you'll see nested properties available!


Accessing Column Data

How to Reference Columns

In the code editor:

  1. Start typing the column name you want to reference

  2. Autocomplete appears showing matching columns

  3. Select the column from the list

  4. A green badge appears showing the column name

1
Start typing the column name:
def quantity = em|
2
Autocomplete shows matching columns:
def quantity = em|
Columns:
Email
Customer email address
Employee Count
Number of employees
3
Select "Email" - a green badge appears:
def email = Email
Done!
The system automatically inserts the correct reference when your code runs.

That's it! The system automatically inserts the correct reference when your code runs.


Using Autocomplete

To access column names easily:

  1. In the code editor, press: CTRL + SPACE

  2. Autocomplete popup appears showing available columns

  3. Select column from list

  4. Green badge appears showing the column reference

Press CTRL + SPACE to see all available columns:
Available Columns:
Email
First Name
Last Name
Company Size
Annual Revenue
Lead Score
Unit Price
Quantity

Tip: You can also just start typing a column name and the autocomplete will filter to matching columns!


Safe Navigation (Avoiding Null Errors)

Problem: Column might be empty or null

Bad code (will crash if empty):

groovy
def email = [Email Column]
def domain = email.split('@')[1] // CRASH if email is null!

Good code (safe navigation):

groovy
def email = [Email Column]
def domain = email?.split('@')?.getAt(1) // Returns null if email is null

// Or with default value
def emailValue = [Email Column] ?: 'no-email@example.com'
❌ Bad (will crash):
def email = [Email]
def domain = email.split('@')[1]
// CRASH if email is null!
✅ Good (safe):
def email = [Email]
def domain = email?.split('@')?.getAt(1)
// Returns null if email is null

Safe navigation operator: ?.

  • If left side is null, entire expression returns null
  • No crash!

Elvis operator: ?:

  • If left side is null, use right side (default value)

Accessing Nested Data

When column contains object:

Column Enrichment Result contains: { name: "Acme Corp", employees: 500, industry: "Technology" }
def enrichment = Enrichment Result
// Access nested properties
def companyName = enrichment.name
def employees = enrichment.employees
def industry = enrichment.industry
return "${companyName}, Size: ${employees}"

Accessing Array Data

When column contains list:

Column Contacts contains array of objects
def contacts = Contacts
// Get first item
def firstContact = contacts[0]
// Count items
def count = contacts.size()
// Filter items
def active = contacts.findAll { it.status == 'active' }

Available Built-in Variables

objectMapper (JSON Operations)

Purpose: Parse and create JSON

Parse JSON string:
def jsonString = '{"name": "John", "age": 30}'
def parsed = objectMapper.readValue(jsonString, Map)
def name = parsed.name // "John"
Create JSON string:
def myObject = [name: "John", age: 30]
def jsonString = objectMapper.writeValueAsString(myObject)
// Result: '{"name":"John","age":30}'

Column References (Data)

Purpose: Access all column data in current row

Usage: Use autocomplete (CTRL + SPACE) to insert column references

Always available in your code


executeColumn (Advanced)

Purpose: Execute another column programmatically

// Execute another column programmatically
def result = executeColumn('enrich_company')
if (result?.data) {
  def enrichedData = result.data
  return enrichedData
} else {
  return null
}
⚠️ Caution: Can create circular dependencies—be careful!

When to use:

  • Conditional column execution
  • Dynamic workflows
  • Complex dependencies

Caution: Can create circular dependencies—be careful!


Testing Your Custom Code

Step 1: Save Configuration

  1. Click "Save" button at bottom of configuration panel

  2. Column is created in your taible

  3. Configuration closes


Step 2: Add Test Row

To test your code:

  1. Add a new row at the bottom of taible

    • Click "Add Row" or use row menu
  2. Fill in dependency columns

    • Enter data for columns your code reads
    • Example: If code reads quantity and price, enter values
  3. Custom code column executes automatically

    • State: Queued → Running → Completed
    • Or Error if there's a problem
Cell Execution States:
Queued
Waiting to execute
Running
Currently executing
Completed
Success!
Code executed successfully
Error
Failed
Click to see error details

Step 3: Check Result

If successful (Completed, green badge):

  • Cell shows your returned value
  • Click cell to see full data

If failed (Error, red badge with zap icon):

  • Click cell to see error
  • Error sidebar shows detailed information
✅ If Successful:
Completed$245.50
• Cell shows your returned value
• Click cell to see full data
❌ If Failed:
Error
• Click error button to see details
• Shows error message and stack trace

Step 4: Fix Errors

Common errors:

ErrorCauseFix
Cannot get property 'field' on nullAccessed null valueUse safe navigation ?.
No such property: columnNameTypo in column nameCheck spelling in autocomplete
Cannot cast X to YType mismatchCheck data types, use conversions

How to fix:

  1. Click column header → settings icon

  2. Edit code in configuration

  3. Save changes

  4. Select failed cells → Right-click → "Recalculate cells"

  5. Cells re-execute with updated code

1
Click column header → settings icon
2
Edit code in configuration
3
Save changes
4
Select failed cells → Right-click → "Recalculate cells"
Cells re-execute with updated code

Step 5: Test with Multiple Rows

Once working with one row:

  1. Add more test rows with various data

    • Test edge cases
    • Test empty values
    • Test boundary conditions
  2. Verify all execute successfully

  3. Check results make sense

If all good: Your custom code is ready! ✓


Code Editor Tips

Tip 1: Use Comments

Document your code:

groovy
// Calculate lead score based on company size and industry
def companySize = [Company Size]

// Award points for company size
def score = 0
if (companySize > 1000) {
  score += 30 // Large company
} else if (companySize > 100) {
  score += 20 // Mid-size company
}

return score

Why: Makes code maintainable


Tip 2: Format for Readability

Bad (hard to read):

groovy
def score=0
if([Company Size]>1000){score+=30}else if([Company Size]>100){score+=20}
return score

Good (easy to read):

groovy
def score = 0
def companySize = [Company Size]

if (companySize > 1000) {
  score += 30
} else if (companySize > 100) {
  score += 20
}

return score

Tip 3: Use Variables

Instead of repeating:

groovy
if ([Company Size] > 1000) {
  // ... later ...
  def size = [Company Size]
}

Extract to variable:

groovy
def companySize = [Company Size]

if (companySize > 1000) {
  // Use companySize
}

Benefits: Shorter, clearer, less error-prone


Tip 4: Return Early

Complex nested conditions (hard to follow):

groovy
def score = 0
if ([Email]) {
  if ([Company Size]) {
    if ([Industry]) {
      // Calculate score
      score = complexCalculation()
    }
  }
}
return score

Return early (easier to understand):

groovy
// Validate required fields
def email = [Email]
if (!email) return 0

def companySize = [Company Size]
if (!companySize) return 0

def industry = [Industry]
if (!industry) return 0

// All required fields present, calculate score
return complexCalculation()

Tip 5: Test Incrementally

Don't write all at once:

  1. Start simple: return "Hello"
  2. Add data access: return [Email]
  3. Add logic piece by piece
  4. Test after each addition

If it breaks: You know which piece caused it


Modifying Existing Custom Code

To Edit Custom Code Column

  1. Click column header (column you want to edit)

  2. Click settings icon (⚙️) or three-dot menu (⋮)

  3. Select "Edit Column"

  4. Configuration panel opens with current code

  5. Modify code in editor

  6. Click "Save"

  7. Existing cells keep old values (won't auto-recalculate)

  8. To update cells with new code:

    • Select cells
    • Right-click → "Recalculate cells"
    • Cells re-execute with new code
To Edit Column:
1.
Click column header
2.
Click settings icon ⚙️
3.
Modify code
4.
Click "Save"
To Update Cells:
1.
Select cells to update
2.
Right-click
3.
Choose "Recalculate cells"
Cells execute with new code

Version Control Tip

Before major changes:

  1. Duplicate the column (create backup)

    • Same code, different name
  2. Test changes in new column

  3. If works: Delete old column

  4. If breaks: Revert to backup

Prevents data loss during experimentation


Common Patterns

Pattern 1: Data Validation

Pattern: Data Validation
// Validate email format
def email = Email
if (!email) {
  return [valid: false, error: 'Email is required']
}
if (!email.contains('@') || !email.contains('.')) {
  return [valid: false, error: 'Invalid email format']
}
return [valid: true, email: email]

Pattern 2: Fallback Values

Pattern: Fallback Values
// Use enriched if available, else manual entry
def enrichedName = Enriched Company
def manualName = Manual Company
return enrichedName ?: manualName ?: 'Unknown Company'

Pattern 3: Scoring/Classification

Pattern: Scoring/Classification
// Multi-factor scoring
def score = 0
// Factor 1: Company size
def size = Company Size ?: 0
score += size > 1000 ? 30 : size > 100 ? 20 : 10
// Factor 2: Industry
def industry = Industry
if (industry in ['Technology', 'Finance']) {
  score += 25
}
return [score: score, grade: score > 70 ? 'A' : 'B']

Pattern 4: Data Transformation

Pattern: Data Transformation
// Transform raw data to standardized format
def rawPhone = Phone
if (!rawPhone) return null
// Remove non-numeric
def cleaned = rawPhone.replaceAll(/[^\d]/, '')
// Format
if (cleaned.length() == 10) {
  return "+1 (${cleaned[0..2]}) ${cleaned[3..5]}-${cleaned[6..9]}"
} else {
  return cleaned
}

Summary: Writing Custom Code

You now know how to write custom code:

Add Custom Code column:

  • Click "+" → Search "code" → Configure

Configuration fields:

  • Column name (internal identifier)
  • Display label (shown in header)
  • Output type (optional, for type safety)
  • Code editor (where magic happens)

Write code:

  • Use autocomplete to insert column references
  • Use objectMapper for JSON
  • Use executeColumn for dynamic execution
  • Return value (simple or complex)

Test code:

  • Add test row
  • Check result
  • Fix errors
  • Test edge cases

Code editor tips:

  • Use comments
  • Format for readability
  • Use variables
  • Return early
  • Test incrementally

Common patterns:

  • Data validation
  • Fallback values
  • Scoring/classification
  • Data transformation

Next Steps

Now that you can write custom code, Section 9.3 will show you:

  • Real-world custom code examples
  • Lead scoring algorithms
  • Complex data transformations
  • API integration patterns
  • Advanced techniques

Let's see custom code in action! 🚀

Built with VitePress