Skip to content

9.1 The Custom Code Node

Built-in columns cover common operations like enrichment APIs, AI models, webhooks, and email. But what if you need something completely unique? That's where Custom Code comes in—it gives you full programming power to build exactly what you need.


What Is the Custom Code Column?

The Concept

A Custom Code column lets you write Groovy code that runs automatically for each row in your taible.

Think of it as:

  • A blank canvas for custom logic
  • Full access to all data in the row
  • Ability to perform complex calculations
  • Custom validation and transformations
  • Integration with your unique business rules

In simple terms: If you can code it, you can automate it.

Custom Code

Write Groovy code for custom logic

Full programming power for any automation
Access all row data from other columns
Complex calculations and transformations
Custom validation and business rules

Why Custom Code?

Built-in columns are great for common operations:

  • ✅ Data enrichment (Clearbit, Apollo)
  • ✅ AI completions (OpenAI, Claude)
  • ✅ Send emails
  • ✅ Update CRM

But what if you need:

  • Custom scoring algorithm with your proprietary formula
  • Integration with your internal API
  • Complex multi-step data transformation
  • Unique business validation rules
  • Legacy system connection

Custom Code fills these gaps perfectly.


When to Use Custom Code

Use Case 1: Unique Business Logic

Scenario: Your company has a proprietary lead scoring algorithm.

The Problem: Built-in nodes don't know your specific formula.

The Solution: Write custom code implementing your exact algorithm.

Example: Custom Lead Scoring

Your unique business rules:
+40 pointsIndustry is Fintech, InsurTech, or WealthTech
+30 pointsRecent funding over $10M
+20 pointsMore than 5 job postings last month
def score = 0
// Check industry fit
if (companyIndustry in ['Fintech', 'InsurTech', 'WealthTech']) {
score += 40
}
// Check funding
if (recentFunding > 10000000) {
score += 30
}
// Check hiring activity
if (jobPostings > 5) {
score += 20
}
return score

Why use Custom Code? Built-in nodes don't have your proprietary scoring formula. Custom Code lets you implement your exact business rules.

Result: Every lead gets automatically scored using your exact business rules.


Use Case 2: Complex Transformations

Scenario: You need to parse, validate, clean, and format address data.

The Problem: Built-in nodes would require 5-10 separate columns.

The Solution: One custom code column does it all.

Example:

groovy
// Parse address components
def parts = rawAddress.split(',')
def street = parts[0]?.trim()
def city = parts[1]?.trim()
def stateZip = parts[2]?.trim()

// Extract state and ZIP
def matcher = (stateZip =~ /([A-Z]{2})\s+(\d{5})/)
def state = matcher ? matcher[0][1] : null
def zip = matcher ? matcher[0][2] : null

// Validate completeness
if (!street || !city || !state || !zip) {
  return [valid: false, reason: 'Incomplete address']
}

// Return standardized format
return [
  street: street.toUpperCase(),
  city: city.toUpperCase(),
  state: state,
  zip: zip,
  valid: true
]

Result: Complex transformation in a single column instead of many.


Use Case 3: Custom Validation

Scenario: You have complex B2B validation rules.

Example: Email domain must match company, revenue in range, industry allowed.

groovy
def errors = []

// Check email domain matches company
def emailDomain = email.split('@')[1]
if (!companyName.toLowerCase().contains(emailDomain.split('\\.')[0])) {
  errors.add('Email domain mismatch')
}

// Check revenue range
if (revenue < 1000000 || revenue > 1000000000) {
  errors.add('Revenue outside target range')
}

// Check blocked industries
def blockedIndustries = ['Gambling', 'Tobacco']
if (industry in blockedIndustries) {
  errors.add("Industry not allowed: ${industry}")
}

return [
  valid: errors.isEmpty(),
  errors: errors,
  status: errors.isEmpty() ? 'APPROVED' : 'REJECTED'
]

Result: Comprehensive validation with your business logic.


Use Case 4: Custom Algorithms

Scenario: You need fuzzy matching to detect duplicate company names.

Example: Levenshtein distance algorithm for similarity scoring.

groovy
// Calculate similarity between two strings
def calculateSimilarity(String s1, String s2) {
  // Levenshtein distance implementation
  def costs = new int[s2.length() + 1]
  for (int j = 0; j <= s2.length(); j++) costs[j] = j

  for (int i = 1; i <= s1.length(); i++) {
    costs[0] = i
    int nw = i - 1
    for (int j = 1; j <= s2.length(); j++) {
      int cj = Math.min(
        Math.min(costs[j] + 1, costs[j - 1] + 1),
        s1.charAt(i - 1) == s2.charAt(j - 1) ? nw : nw + 1
      )
      nw = costs[j]
      costs[j] = cj
    }
  }
  return costs[s2.length()]
}

// Find similar company names
def targetName = inputCompanyName
def existingNames = allCompanies // From another column

def matches = existingNames.collect { name ->
  [
    name: name,
    distance: calculateSimilarity(targetName.toLowerCase(), name.toLowerCase())
  ]
}.findAll { it.distance <= 3 }

return [
  matches: matches,
  isDuplicate: !matches.isEmpty()
]

Result: Custom matching algorithm tailored to your needs.


Programming Language: Groovy

What Is Groovy?

Groovy is a programming language that runs on the Java Virtual Machine (JVM).

Key characteristics:

  • Similar syntax to JavaScript/Python - easy to learn
  • Dynamic typing - less verbose than Java
  • Powerful features - lists, maps, string interpolation
  • Access to Java libraries - extensive ecosystem

Why Groovy?

Advantages for Taibles:

  1. Easy to learn: Python-like simplicity
  2. Powerful: Full Java ecosystem access
  3. Safe: Runs in controlled environment
  4. Flexible: Dynamic typing with type inference
  5. String interpolation: Easy data manipulation

Groovy Basics for Non-Programmers

If you're not a developer, Groovy is surprisingly approachable:

Groovy Basics for Beginners

Variables (storing data)

def name = "John"
def age = 30
def isActive = true

Conditionals (if/else)

if (age > 18) {
return "Adult"
} else {
return "Minor"
}

Inserting Variables into Text

def greeting = "Hello, ${name}!"
// Result: "Hello, John!"

Math Operations

def total = price * quantity
def discount = total * 0.1
return total - discount

Good news: Groovy syntax is similar to JavaScript, Python, and Java. If you know any programming language, you'll pick it up quickly!


Learning Resources

Want to learn Groovy?

Or hire a developer: Many freelancers and agencies know Groovy and can write custom code for you!


What You Can Do with Custom Code

Capability 1: Access All Row Data

You can access any column in the current row:

groovy
def customerEmail = [Email Column]
def companyName = [Company Name]
def enrichmentData = [Enrichment Result]

When you type in the code editor, press CTRL+SPACE to see all available columns. They appear as colored badges in your code.


Capability 2: Complex Calculations

Mathematical operations:

groovy
def orderTotal = [Quantity] * [Unit Price]
def discount = orderTotal * 0.1
def finalPrice = orderTotal - discount
return finalPrice

Statistical calculations:

groovy
def scores = [All Scores] // Array from another column
def average = scores.sum() / scores.size()
def maximum = scores.max()
def minimum = scores.min()
return [average: average, max: maximum, min: minimum]

Capability 3: String Manipulation

Text processing:

groovy
def fullName = [Full Name]

// Split into first and last name
def parts = fullName.split(' ')
def firstName = parts[0]
def lastName = parts.size() > 1 ? parts[1..-1].join(' ') : ''

// Format different ways
return [
  first: firstName,
  last: lastName,
  formal: "Mr./Ms. ${lastName}",
  informal: firstName
]

Capability 4: Data Structure Manipulation

Working with lists and objects:

groovy
def contacts = [Contact List] // Array from another column

// Filter active contacts
def activeContacts = contacts.findAll { it.status == 'active' }

// Extract just emails
def emails = activeContacts.collect { it.email }

// Group by industry
def byIndustry = contacts.groupBy { it.industry }

return [
  total: contacts.size(),
  active: activeContacts.size(),
  emails: emails,
  byIndustry: byIndustry
]

Capability 5: Conditional Logic

Complex decision trees:

groovy
def score = [Lead Score]
def revenue = [Company Revenue]
def industry = [Industry]

def tier = 'C'

if (score > 80 && revenue > 10000000) {
  tier = 'A'
} else if (score > 60 && revenue > 1000000) {
  tier = 'B'
} else if (industry in ['Technology', 'Finance']) {
  tier = 'B' // Upgrade strategic industries
}

def actions = []
if (tier == 'A') {
  actions = ['Assign to senior sales', 'Schedule executive call']
} else if (tier == 'B') {
  actions = ['Assign to mid-level sales', 'Send personalized email']
} else {
  actions = ['Add to nurture campaign']
}

return [tier: tier, actions: actions]

Capability 6: Return Any Type of Data

Your code can return:

  • Simple values: strings, numbers, booleans
  • Objects: maps with multiple properties
  • Arrays: lists of items
  • Nested data: complex structures

Example:

groovy
// Return an object with multiple fields
return [
  status: 'valid',
  score: 85,
  tier: 'A',
  actions: ['Call', 'Email'],
  metadata: [
    processedAt: new Date(),
    version: '1.0'
  ]
]

How Results Display

When your code runs, the results appear in each cell:

How Results Display

Simple Text Result:
Business Email
Number Result:
85
List Result:
3 Entries
While Processing:
Processing...

Click on any result to see the full data in a sidebar with a formatted JSON view.

Click any result to see the full data in a detailed sidebar view with formatted JSON.


Configuring a Custom Code Column

When you add a Custom Code column, you configure two things:

Configure Custom Code Column

1
1
2
2
3
4
5
6
7
8
def email =
Email
def company =
Company Name
if (email.contains("@gmail.com")) {
return "Personal Email"
} else {
return "Business Email"
}
To access data from other columns, press CTRL + SPACE or start typing the column name.

1. Output Type

Tell the system what type of data your code returns:

  • String - Text
  • Integer or Double - Numbers
  • Boolean - True/false
  • List<String> - List of text items
  • Map<String, Object> - Object with properties
  • any - Any type (default)

2. Code to Execute

Write your Groovy code in the editor:

  • Line numbers on the left
  • Syntax highlighting for easier reading
  • CTRL+SPACE shows available columns
  • Colored badges show where you're using data from other columns
  • Current line highlighting shows where your cursor is

💡 Pro Tip

Press CTRL+SPACE while typing to see all available columns. When you select one, it appears as a colored badge in your code, making it easy to see which data you're using.

Important Limitations

Security Considerations

Current status: Custom code runs with full access to the system.

What this means:

  • Only use Custom Code for your own automations
  • Don't allow untrusted users to write code
  • Future versions will add sandboxing for safety

Best practice: Treat Custom Code like admin access—use it carefully.


No Direct HTTP Calls

Custom Code doesn't include HTTP libraries for API calls.

For API integrations:

  • Option 1: Use built-in API nodes where available
  • Option 2: Request a custom node for your specific API
  • Option 3: Use RPC node for HTTP calls (if available)

Performance Considerations

Your code executes for every row:

  • Complex code = slower processing
  • Heavy calculations affect performance
  • Consider rate limits if needed

Optimization tip: Keep code simple and efficient. If you're processing thousands of rows, every millisecond counts!


Debugging Can Be Tricky

Challenges:

  • Errors show in cell results
  • No step-by-step debugger
  • Stack traces can be technical

Best practices:

  • Start simple, test incrementally
  • Use return statements to check intermediate values
  • Test with one row before running on many
  • Check for null values: use ?. safe navigation

Example of safe coding:

groovy
// ❌ Might crash if data is missing
def domain = email.split('@')[1]

// ✅ Safely handles missing data
def domain = email?.split('@')?.getAt(1)

When NOT to Use Custom Code

Don't Use When Built-In Nodes Exist

If there's already a node for what you need, use it:

  • More reliable (tested by many users)
  • Better error handling
  • Maintained and updated
  • Often more performant

Example:

  • ❌ Don't write HTTP client code for Clearbit
  • ✅ Use the Clearbit enrichment node

Don't Use for Simple Operations

For simple data manipulation, use dependencies and templates.

Bad (unnecessarily complex):

groovy
// Custom Code column
def firstName = [First Name]
def lastName = [Last Name]
return "${firstName} ${lastName}"

Good (use column dependencies): Just reference the data directly: The system automatically combines [First Name] and [Last Name].

Rule: If you can do it with column dependencies, don't use Custom Code.


Don't Duplicate Logic

If you're writing the same code in multiple columns:

  • Create a reusable column template
  • Or request a custom node
  • Don't copy-paste code everywhere

Why? Duplicated code = maintenance nightmare when you need to change it later.


Getting Help with Custom Code

If You're Not Technical

You don't need to be a programmer! Here's how to work with developers:

1. Describe your business logic clearly:

  • What data do you start with?
  • What do you want to calculate or validate?
  • What should the output look like?
  • What are the edge cases?

2. Provide examples:

  • Sample input data
  • Expected output for each example
  • Any special rules or conditions

3. Developer writes the code

4. You test it:

  • Create test rows with different scenarios
  • Verify the results match expectations
  • Report any issues

Where to find developers:

  • Upwork, Toptal (freelance platforms)
  • Local development agencies
  • Groovy/Java developer communities

Resources

Learn Groovy:

Get help:

  • Hire a developer for custom logic
  • Check existing examples in documentation
  • Ask in Taibles community

Real-World Examples

Example 1: Email Classification

groovy
def email = [Email]

if (email.contains('@gmail.com') || email.contains('@yahoo.com')) {
  return 'Personal'
} else if (email.contains('@company.com')) {
  return 'Internal'
} else {
  return 'Business'
}

Example 2: Price Calculation with Tiers

groovy
def quantity = [Quantity]
def basePrice = [Base Price]

def price = basePrice
if (quantity >= 100) {
  price = basePrice * 0.8  // 20% discount
} else if (quantity >= 50) {
  price = basePrice * 0.9  // 10% discount
}

return price * quantity

Example 3: Data Quality Check

groovy
def issues = []

if ([Email] == null || ![Email].contains('@')) {
  issues.add('Invalid email')
}

if ([Company Name] == null || [Company Name].length() < 2) {
  issues.add('Invalid company name')
}

if ([Phone] != null && ![Phone].matches('\\d{10,}')) {
  issues.add('Invalid phone format')
}

return [
  valid: issues.isEmpty(),
  issues: issues
]

Summary: The Custom Code Column

You now understand Custom Code columns:

What it is: Groovy code execution for custom logic

When to use it:

  • Unique business logic
  • Complex transformations
  • Custom validation
  • Proprietary algorithms
  • Data quality checks

What you can do:

  • Access all row data
  • Complex calculations
  • String manipulation
  • Data structure operations
  • Conditional logic
  • Return any data type

How it works:

  • Configure output type
  • Write code in editor with syntax highlighting
  • Press CTRL+SPACE for column autocomplete
  • Results display in colored badges
  • Click for detailed view

Limitations:

  • Security (use carefully)
  • No direct HTTP calls
  • Performance considerations
  • Debugging challenges

When NOT to use:

  • Built-in node exists
  • Simple operations
  • Duplicating logic

Getting help:

  • Learn Groovy basics
  • Hire a developer
  • Community resources

Next Steps

Now that you understand the concept, Section 9.2 will show you:

  • Step-by-step: Adding a Custom Code column
  • Configuring the code editor
  • Testing your code
  • Viewing results
  • Troubleshooting common issues

Let's build with custom code! 🚀

Built with VitePress