What the n8n If Node Does
The If node evaluates a condition on each incoming item and routes it to one of two outputs:
- True branch â condition matched
- False branch â condition did not match
It processes items one at a time. If your workflow receives 10 items and 3 match the condition, 3 go to the True branch and 7 go to the False branch â simultaneously, in the same execution.
Adding an If Node
- Open your workflow in n8n
- Click + after the node you want to branch from
- Search for If and select it
- Configure your condition in the node settings
Condition Types
The If node supports these value types:
| Type | Use for |
|---|---|
| String | Text comparisons (equals, contains, starts with, regex) |
| Number | Numeric comparisons (equal, greater than, less than) |
| Boolean | True/false flags |
| Date & Time | Before/after a timestamp |
| Array | Contains an element |
| Object | Has a key |
Building a Condition
Each condition has three parts:
-
Value 1 â the field you're evaluating (use expressions:
{{ $json.status }}) -
Operation â the comparison (
equals,contains,greater than, etc.) - Value 2 â what you're comparing against (can be a static value or another expression)
Example: Route based on order value
- Value 1:
{{ $json.amount }} - Operation:
greater than - Value 2:
100
Items with amount > 100 go to True; everything else goes to False.
Combining Conditions (AND / OR)
Click Add condition to chain multiple rules:
- AND â all conditions must be true for an item to go to True branch
- OR â any one condition being true routes to True branch
Switch between AND/OR with the toggle above the condition list.
Example: High-value lead from a specific source
{{ $json.lead_value }} greater than 500
AND
{{ $json.source }} equals "organic"
Only leads worth over $500 that came from organic traffic hit the True branch.
Using Expressions in Conditions
Expressions let you compare dynamic values, not just static ones.
Check if a field exists:
- Value 1:
{{ $json.email }} - Operation:
is not empty
Case-insensitive string match:
- Value 1:
{{ $json.status.toLowerCase() }} - Operation:
equals - Value 2:
active
Compare two dynamic fields:
- Value 1:
{{ $json.submitted_at }} - Operation:
greater than - Value 2:
{{ $json.deadline }}
What Happens to Unmatched Items
Items that don't match go to the False branch. You have three choices for what to do with them:
- Connect a node â process the False branch differently (e.g., send a rejection email)
- Leave it unconnected â False-branch items are silently dropped
- Connect to the same downstream node â merge both branches into one output
To merge both branches, connect the True and False outputs to the same node. n8n will combine the items automatically.
Practical Example: Duplicate Lead Filter
Scenario: Your webhook receives form submissions. You want to check if the email already exists in Google Sheets before adding it.
Workflow structure:
Webhook â Google Sheets (lookup) â If Node â [True: Skip] [False: Append Row + Send Welcome Email]
If node condition:
- Value 1:
{{ $json.email }} - Operation:
is not empty - (True = email found in sheet â skip; False = new lead â add)
This prevents duplicate rows without any custom code.
Free Workflow JSON: Lead Deduplication with If Node
Here's a complete workflow you can import directly into n8n. It:
- Receives a webhook with
name,email, andsourcefields - Looks up the email in Google Sheets
- Uses an If node to check if a row was found
- If duplicate â logs and stops; if new â appends the row and sends a welcome email via Gmail
{
"name": "Lead Dedup with If Node",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "lead-intake",
"responseMode": "responseNode",
"options": {}
},
"id": "webhook-1",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [240, 300]
},
{
"parameters": {
"operation": "lookup",
"documentId": { "__rl": true, "value": "YOUR_SHEET_ID", "mode": "id" },
"sheetName": { "__rl": true, "value": "Sheet1", "mode": "name" },
"lookupColumn": "Email",
"lookupValue": "={{ $json.body.email }}"
},
"id": "sheets-lookup",
"name": "Sheets Lookup",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4,
"position": [460, 300]
},
{
"parameters": {
"conditions": {
"options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict" },
"conditions": [
{
"id": "cond-1",
"leftValue": "={{ $json.email }}",
"rightValue": "",
"operator": { "type": "string", "operation": "notEmpty" }
}
],
"combinator": "and"
}
},
"id": "if-node",
"name": "Is Duplicate?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [680, 300]
},
{
"parameters": {
"operation": "append",
"documentId": { "__rl": true, "value": "YOUR_SHEET_ID", "mode": "id" },
"sheetName": { "__rl": true, "value": "Sheet1", "mode": "name" },
"columns": {
"mappingMode": "defineBelow",
"value": {
"Name": "={{ $('Webhook').item.json.body.name }}",
"Email": "={{ $('Webhook').item.json.body.email }}",
"Source": "={{ $('Webhook').item.json.body.source }}",
"Added": "={{ $now.toISO() }}"
}
}
},
"id": "sheets-append",
"name": "Append New Lead",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4,
"position": [900, 200]
},
{
"parameters": {
"sendTo": "={{ $('Webhook').item.json.body.email }}",
"subject": "Welcome â you're on the list",
"message": "Hi {{ $('Webhook').item.json.body.name }},\n\nThanks for signing up. We'll be in touch soon.\n\nCheers",
"options": {}
},
"id": "gmail-welcome",
"name": "Send Welcome Email",
"type": "n8n-nodes-base.gmail",
"typeVersion": 2,
"position": [1120, 200]
}
],
"connections": {
"Webhook": { "main": [[{ "node": "Sheets Lookup", "type": "main", "index": 0 }]] },
"Sheets Lookup": { "main": [[{ "node": "Is Duplicate?", "type": "main", "index": 0 }]] },
"Is Duplicate?": {
"main": [
[],
[{ "node": "Append New Lead", "type": "main", "index": 0 }]
]
},
"Append New Lead": { "main": [[{ "node": "Send Welcome Email", "type": "main", "index": 0 }]] }
},
"active": false,
"settings": { "executionOrder": "v1" }
}
To use it:
- In n8n: Workflows â Import from clipboard â paste the JSON
- Replace
YOUR_SHEET_IDwith your Google Sheet's ID (from its URL) - Connect your Google Sheets and Gmail credentials
- Activate and test with a POST to your webhook URL
Common If Node Mistakes
1. Confusing empty string with null
An empty string ("") and a missing field (null) both look "empty" visually but behave differently. Use is not empty (not is not equal to "") to catch both.
2. Type mismatch
Comparing {{ $json.amount }} (which arrives as a string from a webhook) to a number using greater than will fail silently or return unexpected results. Cast it: {{ Number($json.amount) }}.
3. Both branches unconnected
If you add an If node but forget to wire both outputs, one path will dead-end silently. Always check the False branch is handled intentionally.
When to Use Switch Instead
The If node is binary â True or False. If you need more than two paths (e.g., route by plan_type = free, pro, enterprise), use the Switch node instead. It evaluates multiple conditions and routes to a matching output.
Want More Workflows Like This?
I put together a Starter Pack of 10 production-ready n8n workflows â each with setup guides and JSON you can import in under 10 minutes:
- Lead capture â CRM â welcome email (with deduplication)
- Stripe payment â fulfillment trigger â receipt email
- Form submission â Google Sheets + Slack alert
- Webhook router with If/Switch branching
- Scheduled data sync with error logging
- And 5 more
â n8n Workflow Starter Pack ($29)
One-time purchase. No subscription. Instant download.
Discussion
What's the most useful conditional logic you've built in n8n? I'm planning the next pack around real use cases â drop your most-requested workflow in the comments.
Top comments (1)
What conditional logic do you use most in your n8n workflows? For me it's the duplicate-check pattern (lookup → If node → skip or add) — saves so much manual cleanup. Drop your most-used If node setup in the comments, I'm building the next workflow pack around real use cases.