G: 👋 Hey there, fellow automation enthusiasts! Are you using n8n to streamline your workflows but find yourself hitting a wall when built-in nodes just aren’t flexible enough? Do you need to perform complex data transformations, custom calculations, or intricate conditional logic that goes beyond simple drag-and-drop? If so, you’ve landed in the right place!
Today, we’re diving deep into the n8n Code Node – the true powerhouse that unlocks n8n’s full potential. Think of it as your custom JavaScript sandbox within n8n, allowing you to implement virtually any logic you can imagine. Get ready to elevate your automation game! 🚀
💡 What is the n8n Code Node and Why Do You Need It?
N8n excels at providing a visual, low-code interface for building workflows. You connect nodes, configure them, and data flows magically from one step to the next. But what happens when:
- You need to combine data from multiple incoming items in a unique way?
- You have a mathematical formula that needs to be applied dynamically?
- You want to filter items based on complex, multi-criteria conditions?
- You need to restructure JSON objects into a completely different format?
- You want to generate new items based on a single input?
This is where the Code Node shines! ✨ It provides a dedicated environment to write custom JavaScript code, giving you granular control over your data and workflow logic.
Key Benefits:
- Unmatched Flexibility: Implement any logic JavaScript allows.
- Custom Data Transformation: Reshape, combine, split, or filter data precisely.
- Complex Calculations: Perform advanced arithmetic, string manipulation, or date operations.
- Dynamic Control Flow: Create intricate conditional paths and loops.
- Consolidate Logic: Often, a single Code Node can replace multiple simpler nodes, making your workflow cleaner.
🧩 Understanding the Fundamentals: How the Code Node Works
The Code Node operates on the principle of items. When data enters the Code Node, it arrives as an array of item
objects. Each item
typically contains a json
property (your actual data) and potentially a binary
property (for files). Your job inside the Code Node is to manipulate this items
array and then return a new items
array.
Basic Structure:
// The 'items' array contains all incoming data
for (const item of items) {
// Your custom logic here
// Access data: item.json.yourPropertyName
// Modify data: item.json.newPropertyName = someValue;
}
// Return the modified 'items' array
return items;
Accessing Data:
item.json.propertyName
: Access data from the current item being processed.$json.propertyName
: A shorthand foritem.json.propertyName
whenitems
contains only one element, or when you are inside aforEach
ormap
loop onitems
.$node["Node Name"].json.propertyName
: Access data from a previous node in the workflow. Replace"Node Name"
with the exact name of the node (e.g.,"$node["Set"].json.myVariable"
).$node["Node Name"].binary.propertyName
: Access binary data from a previous node.
Important Considerations:
- JavaScript! You’re writing standard JavaScript (ES6+ features are supported).
return items;
: Always return an array ofitem
objects. If you return anything else, n8n will complain.- Debugging: Use
console.log()
inside your Code Node. The output will appear in the “Output” section of the Code Node when you test it, or in your n8n console/logs if running live. - Error Handling: Use
try...catch
blocks to gracefully handle potential errors within your code.
🛠️ 10 Practical Examples to Master the Code Node
Let’s get our hands dirty with some real-world examples! These will demonstrate the versatility of the Code Node for various automation scenarios.
Example 1: Data Transformation & Renaming Fields 🏷️
Problem: You receive data with inconsistent field names (e.g., cust_id
but need customer_id
).
Solution: Loop through items and rename properties.
// Example 1: Rename a property
for (const item of items) {
if (item.json.hasOwnProperty('cust_id')) {
item.json.customer_id = item.json.cust_id;
delete item.json.cust_id; // Remove the old property
}
// You can also add new properties
item.json.processedAt = new Date().toISOString();
}
return items;
Explanation: This code iterates through each incoming item. If an item has a cust_id
property, it copies its value to a new customer_id
property and then deletes the original cust_id
. It also adds a processedAt
timestamp.
Example 2: Conditional Logic & Dynamic Value Assignment 🤔
Problem: You want to apply a discount based on an order total, or assign a status based on a value.
Solution: Use if/else
statements to create dynamic outputs.
// Example 2: Apply discount based on order total
for (const item of items) {
const orderTotal = item.json.orderTotal;
if (orderTotal >= 500) {
item.json.discountPercentage = 0.15; // 15% off
item.json.finalAmount = orderTotal * 0.85;
} else if (orderTotal >= 100) {
item.json.discountPercentage = 0.05; // 5% off
item.json.finalAmount = orderTotal * 0.95;
} else {
item.json.discountPercentage = 0;
item.json.finalAmount = orderTotal;
}
item.json.status = "processed";
}
return items;
Explanation: This code checks the orderTotal
for each item and calculates a discountPercentage
and finalAmount
accordingly. It also adds a generic status
field.
Example 3: Filtering Items Based on Complex Criteria ✂️
Problem: You only want to proceed with items that meet multiple conditions (e.g., active users in a specific region).
Solution: Use Array.prototype.filter()
or a manual loop with conditional pushing.
// Example 3: Filter items based on multiple conditions
const filteredItems = items.filter(item => {
const isActive = item.json.isActive === true;
const region = item.json.region;
const lastLoginDays = item.json.daysSinceLastLogin;
return isActive && region === 'EU' && lastLoginDays 0 ? totalRevenue / totalOrders : 0,
processedAt: new Date().toISOString()
}
}
];
Explanation: This sums up the amount
from all incoming items and counts the total orders. It then returns a single new item containing the aggregated results.
Example 5: String Manipulation & Formatting 📝
Problem: You need to format names, standardize addresses, or extract specific parts of a string.
Solution: Utilize JavaScript’s string methods (toUpperCase()
, toLowerCase()
, substring()
, split()
, replace()
, etc.).
// Example 5: Format user names and email
for (const item of items) {
if (item.json.firstName && item.json.lastName) {
item.json.fullName = `${item.json.firstName.charAt(0).toUpperCase()}${item.json.firstName.slice(1).toLowerCase()} ${item.json.lastName.toUpperCase()}`;
}
if (item.json.email) {
item.json.standardizedEmail = item.json.email.trim().toLowerCase();
}
}
return items;
Explanation: This code converts the first name to title case and the last name to uppercase, then combines them into a fullName
. It also standardizes email addresses by trimming whitespace and converting to lowercase.
Example 6: Date & Time Operations 📅
Problem: You need to format dates, calculate age from a birth date, or determine days until an event.
Solution: Use JavaScript’s Date
object methods. For more complex scenarios, you could technically require('moment')
if configured in your n8n instance, but native Date
methods often suffice.
// Example 6: Calculate age from birthdate and format a timestamp
for (const item of items) {
if (item.json.birthDate) {
const birthDate = new Date(item.json.birthDate);
const today = new Date();
let age = today.getFullYear() - birthDate.getFullYear();
const m = today.getMonth() - birthDate.getMonth();
if (m < 0 || (m === 0 && today.getDate() ({
json: {
originalId: originalItem.id, // Keep a reference to the original item's ID
elementValue: element,
processed: true
}
}));
return newItems;
} else {
// Handle cases where the array property is missing or not an array
return [{ json: { error: "Input array property not found or invalid." } }];
}
Explanation: This takes the myArrayProperty
from the first incoming item and transforms each element of that array into a new n8n item, each with its own json
data.
Example 8: Custom Validation & Error Flagging 🔒
Problem: You need to validate incoming data against specific rules and flag items that don’t meet the criteria, without stopping the workflow entirely.
Solution: Add a isValid
or errorMessage
property to items that fail validation.
// Example 8: Custom data validation
for (const item of items) {
item.json.isValid = true;
item.json.validationErrors = [];
if (!item.json.name || item.json.name.length < 3) {
item.json.isValid = false;
item.json.validationErrors.push("Name must be at least 3 characters.");
}
if (!item.json.email || !item.json.email.includes('@')) {
item.json.isValid = false;
item.json.validationErrors.push("Invalid email format.");
}
if (item.json.age && item.json.age sum + product.quantity, 0);
// Get names of all unique products
item.json.productNames = [...new Set(orderDetails.items.map(product => product.name))];
// Check if any item is 'fragile'
item.json.hasFragileItems = orderDetails.items.some(product => product.isFragile === true);
// Flatten item details if needed (e.g., for sending to a separate system)
item.json.flattenedItems = orderDetails.items.map(product => ({
itemId: product.id,
itemName: product.name,
itemQuantity: product.quantity,
itemPrice: product.price,
}));
} else {
item.json.totalItemsQuantity = 0;
item.json.productNames = [];
item.json.hasFragileItems = false;
}
}
return items;
Explanation: This code demonstrates how to navigate a nested customerOrder
object. It calculates the total quantity of products, extracts unique product names, checks for fragile items, and even flattens the nested items
array into a simpler structure.
🚀 Advanced Tips & Considerations
-
Asynchronous Operations (
async/await
): If your Code Node needs to perform operations that take time (like fetching data from an external API directly within the node, though again, the HTTP Request node is preferred), you can useasync
andawait
. You’ll need to make yourfor...of
loopasync
and the Code Node itself will implicitly becomeasync
.// Example of async/await in Code Node (for illustrative purposes, generally use HTTP Request node) for (const item of items) { try { const response = await fetch(`https://api.example.com/data/${item.json.id}`); const data = await response.json(); item.json.externalData = data; } catch (error) { console.error("Error fetching data:", error); item.json.externalDataError = error.message; } } return items;
-
External NPM Modules: By default, only a limited set of common Node.js modules are available (
path
,fs
,url
, etc.). If you need specific external NPM packages (likelodash
oraxios
), your n8n server needs to be configured to include them using theNPM_ADDITIONAL_MODULES
environment variable. This is more advanced and requires control over your n8n deployment. -
Workflow Context (
workflow.settings
): You can access workflow-level settings or credentials if they are defined globally or within a specific node that exposes them. This is less common for simple data manipulation but powerful for complex scenarios.
🎉 Conclusion: Empowering Your n8n Workflows
The n8n Code Node is an incredibly powerful tool that bridges the gap between low-code convenience and full programming flexibility. While the visual nodes handle most common tasks with ease, the Code Node steps in when you need bespoke logic, complex data manipulation, or highly specific transformations.
Don’t be intimidated by the code! Start with simple examples, leverage console.log()
for debugging, and gradually build up your complexity. With the Code Node in your n8n arsenal, there’s virtually no automation task you can’t tackle.
Happy automating! automate 🤖✨