No history yet

Advanced Expressions and Scripting

Beyond Drag and Drop

You already know how to connect nodes and pass data from one step to the next. But what happens when the data isn't in the right shape? APIs don't always return clean, flat data. More often, you get nested objects and arrays that need to be transformed before you can use them in a database, a spreadsheet, or another API call.

This is where expressions become your superpower. They bridge the gap between simple node configuration and writing a full-blown Code node. Expressions allow you to run small snippets of JavaScript directly inside a node's parameter fields to manipulate data on the fly.

Think of it this way: if nodes are the building blocks, expressions are the custom tools you use to make those blocks fit together perfectly.

Let's work with a typical, slightly messy JSON object you might get from an API. It represents a user's order.

{
  "customerDetails": {
    "userId": "usr_12345",
    "name": "Alex Chen",
    "joinDate": "2023-10-26T14:30:00Z"
  },
  "order": {
    "orderId": "ord_67890",
    "items": [
      {
        "sku": "A-001",
        "name": "Wireless Mouse",
        "price": 29.99,
        "quantity": 1
      },
      {
        "sku": "B-002",
        "name": "Mechanical Keyboard",
        "price": 119.50,
        "quantity": 1
      }
    ],
    "isPriority": true,
    "metadata": {
      "source": "web",
      "campaign": "FALL2024"
    }
  }
}

Shaping Data with Expressions

The primary tool for data transformation is the 'Edit Fields' (or Set) node. It lets you create, modify, or remove fields in your data stream. While you can drag and drop basic variables, its real power comes from writing custom expressions.

Let's say we want to create a new field called totalCost. We need to multiply the price by the quantity for each item and then sum them up. You can't do that with a simple variable. You need an expression.

Inside an expression, you have access to the full power of JavaScript. This includes array methods like .map() and .reduce() which are perfect for this kind of calculation.

// In an expression field for totalCost:
{{ $json.order.items.reduce((sum, item) => sum + item.price * item.quantity, 0) }}

This expression iterates through the items array, calculates the cost of each line item, and adds it to an accumulator (sum), starting from 0. The result is a single number representing the total cost of the order.

Advanced Tools in Your Toolbox

n8n's expression engine comes with powerful libraries built-in. For any date and time manipulation, you have access to Luxon, a modern JavaScript date library. Instead of wrestling with raw date strings, you can parse them into Luxon objects and format them however you need.

// Reformat the user's join date:
{{ DateTime.fromISO($json.customerDetails.joinDate).toFormat('DDDD') }}
// Output: "October 26, 2023"

Sometimes you need simple conditional logic. You could use an IF node, but for simple cases, a ternary operator is much cleaner. It's a compact, one-line if-else statement. Let's create a field called shippingMethod based on the isPriority flag.

// Syntax: condition ? value_if_true : value_if_false
{{ $json.order.isPriority ? 'Express' : 'Standard' }}

This expression checks if isPriority is true. If it is, it returns 'Express'; otherwise, it returns 'Standard'. This is much more efficient than adding a whole new node to your workflow for a simple binary choice.

Accessing Data Across the Workflow

So far, we've only accessed data from the immediately preceding node ($json). But what if you need data from a much earlier step? n8n provides special variables for this. The $node object allows you to grab the output of any previous node by its name.

Imagine you have a node named 'GetUser' at the beginning of your workflow. Many steps later, you can still access its data like this:

// Get the email from the 'GetUser' node's first item
{{ $node["GetUser"].json.email }}

Remember to use quotes around the node name. If your node name has spaces, like 'Get User from DB', you must use this syntax: $node["Get User from DB"].json.

You can also use $items to get data from a node that returns multiple items. This is useful when you need to loop or find specific data from an earlier step without merging it all in. For example, to get the email from the first item output by the 'GetUser' node:

{{ $items("GetUser")[0].json.email }}

Mastering these variables frees you from complex data merging, allowing you to build cleaner, more readable workflows by pulling in exactly the data you need, right when you need it.

Quiz Questions 1/6

What is the primary purpose of using expressions in a tool like n8n?

Quiz Questions 2/6

You need to create a new field called shippingMethod. If the incoming data has a boolean field isPriority that is true, the value should be 'Express'. Otherwise, it should be 'Standard'. Which expression correctly uses a ternary operator for this?

By moving beyond simple variable mapping, you unlock the ability to handle any data structure and logic your automations require.