Lý thuyết
Bài 1/7

n8n Workflow Automation Fundamentals

Học cách tự động hóa công việc với n8n - công cụ automation mạnh mẽ và miễn phí

n8n Workflow Automation Fundamentals

1. n8n là gì?

n8n (n-eight-n) là workflow automation platform mã nguồn mở cho phép bạn kết nối các apps và services để tự động hóa công việc không cần code.

1.1 Tại sao chọn n8n?

Featuren8nZapierMake (Integromat)
PricingFree self-hosted$20+/month$9+/month
Custom codeJavaScript, PythonLimitedLimited
Data privacySelf-hosted optionCloud onlyCloud only
Nodes400+6000+1500+
Open source✅ Yes❌ No❌ No

n8n phù hợp khi:

  • Cần tự động hóa phức tạp với logic
  • Quan tâm data privacy
  • Muốn tùy biến cao
  • Budget hạn chế
  • Muốn integrate AI (OpenAI, Anthropic...)

1.2 Use Cases phổ biến

Text
1n8n Automation Use Cases
2├── Productivity & Office
3│ ├── Auto-save Gmail attachments to Drive
4│ ├── Sync calendar events to Notion
5│ └── Daily digest email from multiple sources
6├── Marketing & Sales
7│ ├── Auto-nurture leads from forms
8│ ├── Post to multiple social platforms
9│ └── Track competitor prices
10├── Data & Analytics
11│ ├── Scrape websites to Google Sheets
12│ ├── Daily reports from databases
13│ └── Data sync between apps
14└── AI Integration
15 ├── Auto-reply emails with GPT-4
16 ├── Content generation pipelines
17 └── AI-powered chatbots

2. n8n Core Concepts

2.1 Workflow Anatomy

Text
1Workflow = Nodes + Connections + Data Flow
2
3Trigger → Action 1 → Action 2 → ... → Final Action

Components:

  • Trigger Node: Bắt đầu workflow (webhook, schedule, manual)
  • Action Nodes: Thực hiện tasks (API calls, transformations)
  • Connections: Luồng dữ liệu giữa nodes
  • Expressions: Logic và data manipulation

2.2 Node Types

1. Trigger Nodes:

JavaScript
1// Schedule Trigger - Chạy định kỳ
2- Cron: "0 9 * * 1-5" // 9am weekdays
3- Interval: Every 1 hour
4
5// Webhook Trigger - HTTP endpoint
6- POST https://n8n.domain.com/webhook/abc123
7- Nhn data t forms, APIs, apps
8
9// Manual Trigger - Chạy thủ công
10- Test workflows
11- One-time executions

2. Data Nodes:

JavaScript
1// Google Sheets - Read/write spreadsheets
2- Get rows, update cells
3- Append new data
4
5// Database - SQL operations
6- MySQL, PostgreSQL, MongoDB
7- SELECT, INSERT, UPDATE
8
9// HTTP Request - Call any API
10- GET, POST, PUT, DELETE
11- Authentication: API key, OAuth

3. Logic Nodes:

JavaScript
1// IF - Conditional branching
2if ({{ $json.amount > 1000 }}) {
3 High value path
4} else {
5 Low value path
6}
7
8// Switch - Multiple conditions
9switch ({{ $json.category }}) {
10 case "urgent": Path A
11 case "normal": Path B
12 default: Path C
13}
14
15// Merge - Combine data streams

3. Hands-on: First Workflow

3.1 Gmail to Google Sheets

Objective: Tự động lưu emails quan trọng vào spreadsheet

Workflow:

Text
1Gmail Trigger (new emails with label "Important")
2→ Extract data (sender, subject, date, body)
3→ Google Sheets (append row)
4→ Gmail (mark as read)

Implementation:

Step 1: Gmail Trigger

JavaScript
1// Gmail Trigger Node settings
2Label: "Important"
3Poll Interval: Every 5 minutes
4Simple: false // Get full email data

Step 2: Set Node (Data extraction)

JavaScript
1{
2 "sender": "={{ $json.from.text }}",
3 "subject": "={{ $json.subject }}",
4 "date": "={{ $json.date }}",
5 "preview": "={{ $json.textPlain.slice(0, 200) }}",
6 "url": "={{ $json.webLink }}"
7}

Step 3: Google Sheets

JavaScript
1Operation: Append
2Spreadsheet: "Email Tracker"
3Sheet: "Important Emails"
4Columns: sender, subject, date, preview, url

Step 4: Gmail (mark as read)

JavaScript
1Operation: Update
2Message ID: "={{ $node['Gmail Trigger'].json.id }}"
3Label: Remove "UNREAD"

4. Working with Data

4.1 Expressions & Variables

Access node data:

JavaScript
1// Current node data
2{{ $json.fieldName }}
3
4// Previous node data
5{{ $node["Node Name"].json.field }}
6
7// All items
8{{ $items }}
9
10// Item index
11{{ $itemIndex }}

Common operations:

JavaScript
1// String manipulation
2{{ $json.email.toLowerCase() }}
3{{ $json.name.split(' ')[0] }} // First name
4
5// Math
6{{ $json.price * 1.1 }} // +10% tax
7
8// Date
9{{ new Date($json.timestamp).toLocaleDateString() }}
10
11// Conditional
12{{ $json.status === "active" ? "✅" : "❌" }}

4.2 Data Transformation

Code Node (JavaScript):

JavaScript
1// Example: Calculate total from items
2let total = 0;
3
4for (const item of $input.all()) {
5 total += item.json.amount;
6}
7
8return {
9 totalAmount: total,
10 itemCount: $input.all().length,
11 avgAmount: total / $input.all().length
12};

5. Dự án: Personal Productivity Dashboard

5.1 Mô tả dự án

Tạo Daily Productivity Dashboard tự động tổng hợp:

  • Gmail unread count
  • Google Calendar events today
  • Todoist tasks due
  • GitHub commits yesterday
  • Weather forecast

→ Gửi email summary mỗi sáng 8am

5.2 Workflow Design

Text
1Schedule Trigger (8am daily)
2├── Branch 1: Gmail → Count unread
3├── Branch 2: Google Calendar → List events
4├── Branch 3: Todoist → Get tasks
5├── Branch 4: GitHub → Count commits
6└── Branch 5: OpenWeather → Get forecast
7
8Merge all branches
9
10Format HTML email
11
12Send via Gmail

5.3 Implementation

Schedule Trigger:

JavaScript
1Cron: "0 8 * * *" // 8am daily
2Timezone: "Asia/Ho_Chi_Minh"

Branch 1: Gmail unread count

JavaScript
1// Gmail Node
2Operation: Search
3Search: "is:unread"
4Simple: true
5
6// Code Node
7return {
8 unreadCount: $input.all().length
9};

Branch 2: Google Calendar

JavaScript
1// Google Calendar Node
2Operation: Get Many
3Calendar: primary
4Time Min: {{ $today }}
5Time Max: {{ $today + 1d }}
6Max Results: 10
7
8// Code Node - Format events
9const events = $input.all().map(item => ({
10 time: new Date(item.json.start.dateTime).toLocaleTimeString('vi-VN', {hour: '2-digit', minute: '2-digit'}),
11 title: item.json.summary
12}));
13
14return { todayEvents: events };

Branch 3: Todoist

JavaScript
1// Todoist Node
2Operation: Get All
3Filter: "today | overdue"
4
5// Count & categorize
6const tasks = $input.all();
7return {
8 tasksToday: tasks.filter(t => t.json.due.string === "today").length,
9 tasksOverdue: tasks.filter(t => t.json.is_recurring === false && new Date(t.json.due.date) < new Date()).length
10};

Branch 4: GitHub commits

JavaScript
1// HTTP Request Node
2Method: GET
3URL: https://api.github.com/users/YOUR_USERNAME/events
4Authentication: Bearer Token
5
6// Code Node - Count commits yesterday
7const yesterday = new Date();
8yesterday.setDate(yesterday.getDate() - 1);
9const yesterdayStr = yesterday.toISOString().split('T')[0];
10
11const commits = $input.all().filter(event =>
12 event.json.type === "PushEvent" &&
13 event.json.created_at.startsWith(yesterdayStr)
14);
15
16return { commitsYesterday: commits.length };

Branch 5: Weather

JavaScript
1// OpenWeather Node
2Operation: Current Weather
3Location: "Ho Chi Minh City"
4
5return {
6 temp: Math.round($json.main.temp),
7 description: $json.weather[0].description,
8 humidity: $json.main.humidity
9};

Merge & Format Email:

JavaScript
1// Merge Node - Wait for all branches
2
3// Code Node - Create HTML email
4const data = $input.all().reduce((acc, item) => ({...acc, ...item.json}), {});
5
6const html = `
7<!DOCTYPE html>
8<html>
9<head>
10 <style>
11 body { font-family: Arial; line-height: 1.6; }
12 .card { background: #f5f5f5; padding: 15px; margin: 10px 0; border-radius: 8px; }
13 .number { font-size: 32px; font-weight: bold; color: #0066cc; }
14 </style>
15</head>
16<body>
17 <h1> Daily Dashboard - ${new Date().toLocaleDateString('vi-VN')}</h1>
18
19 <div class="card">
20 <h3> Email</h3>
21 <div class="number">${data.unreadCount}</div>
22 <p>Unread messages</p>
23 </div>
24
25 <div class="card">
26 <h3> Calendar Today</h3>
27 ${data.todayEvents.map(e => `<p>🕐 ${e.time} - ${e.title}</p>`).join('')}
28 </div>
29
30 <div class="card">
31 <h3> Tasks</h3>
32 <p>${data.tasksToday} due today | ${data.tasksOverdue} overdue</p>
33 </div>
34
35 <div class="card">
36 <h3> GitHub</h3>
37 <p>${data.commitsYesterday} commits yesterday</p>
38 </div>
39
40 <div class="card">
41 <h3> Weather</h3>
42 <div class="number">${data.temp}°C</div>
43 <p>${data.description}</p>
44 </div>
45</body>
46</html>
47`;
48
49return { html };

Send Email:

JavaScript
1// Gmail Node
2Operation: Send
3To: your-email@gmail.com
4Subject: "Daily Dashboard - {{ new Date().toLocaleDateString('vi-VN') }}"
5Email Type: HTML
6Body: {{ $json.html }}

6. Best Practices

6.1 Workflow Organization

JavaScript
1// ✅ DO
2- Descriptive node names: "Filter high-value customers"
3- Add Sticky Notes for documentation
4- Group related workflows in folders
5- Use consistent naming conventions
6
7// ❌ DON'T
8- Generic names: "HTTP Request 1", "IF 2"
9- No documentation
10- All workflows in root
11- Inconsistent styles

6.2 Error Handling

JavaScript
1// Error Trigger Node
2Connected to: Any node that might fail
3
4// Error handling workflow
5Error Trigger
6 Code Node (log error details)
7 Send Telegram alert
8 Write to error log file

6.3 Testing

Text
11. Manual Trigger → Test with sample data
22. Limit: 1 → Process only 1 item during testing
33. Pin Data → Fix input data for consistent testing
44. Execution History → Review past runs

7. Deployment Options

7.1 n8n Cloud (Easiest)

Bash
1# Sign up at n8n.cloud
2# Pricing: $20/month
3# Pros: No setup, automatic updates
4# Cons: Cost, less control

7.2 Self-hosted (Recommended)

Docker Compose:

yaml
1version: '3'
2
3services:
4 n8n:
5 image: n8nio/n8n
6 restart: always
7 ports:
8 - "5678:5678"
9 environment:
10 - N8N_BASIC_AUTH_ACTIVE=true
11 - N8N_BASIC_AUTH_USER=admin
12 - N8N_BASIC_AUTH_PASSWORD=your-password
13 - N8N_HOST=your-domain.com
14 - N8N_PROTOCOL=https
15 - WEBHOOK_URL=https://your-domain.com/
16 volumes:
17 - ~/.n8n:/home/node/.n8n

Run:

Bash
1docker-compose up -d

7.3 Railway.app (Free tier)

Bash
1# 1-click deploy
2# Free $5 credit monthly
3# Auto-scale
4# Perfect for personal use

8. Tài liệu tham khảo


Bài tập

  1. Bài 1: Tạo workflow tự động backup Google Docs sang Drive folder mỗi tuần
  2. Bài 2: Setup weather alert - gửi Telegram nếu có mưa
  3. Bài 3: Scrape tin tức từ VnExpress và post summary lên Notion
  4. Bài 4: Implement Daily Productivity Dashboard
  5. Bài 5: Auto-tag Gmail emails by sender domain

Next: Bài 2 - Advanced Nodes & Integrations