Complete Step-by-Step Guide

Automate Your
WordPress Blog
with AI

Send a Word document on WhatsApp → n8n picks it up → AI enriches it → Featured image generated → Live on your website. Zero manual work.

📱 WhatsApp
⚙️ n8n
🤖 Claude + DALL·E
🌐 WordPress
Phase 1

Infrastructure Setup

Spin up a server and install n8n. This is a one-time setup that takes about 30–45 minutes.

1
Spin up your VPS server (Hetzner CX21)
One-time setup · ~15 min · €3.79/month
💰
Cost
Hetzner CX21: €3.79/month (~USD $4.10). DigitalOcean Basic Droplet is $6/month if you prefer.

1.1 — Create Hetzner account

  1. Go to hetzner.com → create account → verify email → add payment method
  2. Go to Cloud → Projects → New Project → name it "WordPress Automation"

1.2 — Create the server

  1. Click "Add Server"
  2. Location: nearest to you (Ash = US, FSN = Europe, SGP = Asia/Middle East)
  3. Image: Ubuntu 24.04
  4. Type: CX21 (2 vCPU, 4 GB RAM)
  5. Add your SSH key or set a root password → click "Create & Buy Now"

1.3 — Connect to your server

ssh root@YOUR_SERVER_IP

1.4 — Install Docker

apt-get update && apt-get upgrade -y
apt-get install -y docker.io docker-compose-plugin
systemctl enable docker && systemctl start docker
2
Install n8n with Docker
One-time setup · ~10 min · Free (self-hosted)
💰
Cost
Free — n8n self-hosted is open source. You only pay for the VPS server in Step 1.
  1. Create the n8n directory:
mkdir -p /opt/n8n && cd /opt/n8n
nano docker-compose.yml
  1. Paste this into the file (replace the password and your domain):
version: '3.8'
services:
  n8n:
    image: n8nio/n8n
    restart: always
    ports:
      - "5678:5678"
    environment:
      - N8N_BASIC_AUTH_ACTIVE=true
      - N8N_BASIC_AUTH_USER=admin
      - N8N_BASIC_AUTH_PASSWORD=YourStrongPassword123
      - WEBHOOK_URL=https://YOUR_DOMAIN_OR_IP:5678
    volumes:
      - n8n_data:/home/node/.n8n
volumes:
  n8n_data:
  1. Press Ctrl+O to save, Ctrl+X to exit, then start n8n:
docker compose up -d
  1. Wait 30 seconds, then open: http://YOUR_SERVER_IP:5678
  2. Log in with the username/password you set above — you should see the n8n editor
💡
Tip
For production, point a domain at your server and set up Nginx + Certbot (free SSL). WhatsApp requires HTTPS webhook URLs. This takes ~20 minutes extra and there are many free guides online for "n8n nginx ssl certbot".
Phase 2

WhatsApp Business API Setup

Connect 360dialog as your WhatsApp provider. This is the bridge between WhatsApp and n8n.

3
Set up 360dialog WhatsApp Business API
One-time setup · 1–3 days (approval) · $7/month
💰
Cost
360dialog Starter: USD $7/month flat. Receiving messages is free. Sending the confirmation reply costs ~$0.005 per message under Meta's pricing.
⚠️
Important
The phone number you register must NOT already be active on regular WhatsApp. Use a new SIM card or a landline/VoIP number. UAE numbers work fine.

3.1 — Register

  1. Go to 360dialog.com → click "Get Started" → create business account
  2. You need a Facebook Business Manager account. If you don't have one, create it at business.facebook.com first
  3. Connect your Facebook Business Manager to 360dialog when prompted

3.2 — Add your phone number

  1. In the 360dialog dashboard → Channels → Add Channel
  2. Enter your phone number → complete OTP verification
  3. Wait for Meta approval (1–3 business days)

3.3 — Get API key and set webhook

  1. Once approved, go to "API Key" → copy your key (save it securely)
  2. Go to "Webhooks" → set the URL to:
https://YOUR_DOMAIN:5678/webhook/whatsapp
  1. Save the webhook configuration
Phase 3

API Keys & Credentials

Gather the three credentials you'll need inside n8n: Claude, OpenAI, and your WordPress Application Password.

4
Get your Claude API key
5 min · ~$0.04 per blog post
💰
Cost
Claude Sonnet 4: $3/1M input tokens + $15/1M output tokens. One blog enrichment call uses ~2,000 tokens = under $0.04 per post. No monthly minimum — pay only what you use.
  1. Go to console.anthropic.com → create account → add payment method
  2. Go to API Keys → Create Key
  3. Name it "n8n-blog-automation" → copy the key immediately (you cannot view it again)
  4. Save it somewhere secure — you'll paste it into n8n in Phase 4
5
Get your OpenAI API key (for DALL·E 3)
5 min · $0.04 per image
💰
Cost
DALL·E 3 Standard quality (1792×1024): USD $0.04 per image. HD quality: $0.08. Standard is sufficient for blog featured images. No monthly minimum.
  1. Go to platform.openai.com → create account → add billing under "Billing"
  2. Go to API Keys → Create new secret key
  3. Name it "n8n-image-gen" → copy and save the key
6
Generate WordPress Application Password
2 min · Free
💰
Cost
Free — WordPress REST API is built into every WordPress installation v4.7+. No plugin needed.
  1. Log into your WordPress admin panel
  2. Go to Users → Profile (or Users → All Users → click your admin)
  3. Scroll down to "Application Passwords"
  4. In the "New Application Password Name" field type: n8n-automation
  5. Click "Add New Application Password"
  6. Copy the password shown immediately — it won't be shown again
💡
Note
Your n8n credentials will be: Username = your WordPress admin username, Password = this application password (copy it exactly, spaces included).
Phase 4

Build the n8n Workflow

Log into your n8n dashboard → click "New Workflow" → name it "WhatsApp Blog Publisher". Then add each node below in order.

7
Node 1 — WhatsApp Webhook Trigger
Entry point of the workflow · Listens 24/7
  1. Click "+" in the workflow editor → search "Webhook" → select it
  2. Set HTTP Method to: POST
  3. Set Path to: whatsapp
  4. Set Authentication to: None (360dialog authenticates via API key header)
  5. Copy the generated webhook URL → paste it into your 360dialog Webhooks settings
  6. Click "Test Webhook" in n8n → send any WhatsApp message to your business number → you'll see the raw payload captured
💡
Tip
After capturing a test payload, click on the Webhook node's output to explore the exact JSON paths. This is what you'll reference in the next node.
8
Node 2 — Filter: Validate Sender & File Type
Security gate — only authorised .docx files pass
  1. Add an "IF" node → connect from Webhook node
  2. Add Condition 1 — Sender phone number:
    • Left value: {{ $json.body.entry[0].changes[0].value.messages[0].from }}
    • Operation: Equal
    • Right value: 971501234567 (your authorised sender's number, no + sign)
  3. Add Condition 2 — Message type:
    • Left value: {{ $json.body.entry[0].changes[0].value.messages[0].type }}
    • Operation: Equal
    • Right value: document
  4. Add Condition 3 — MIME type:
    • Left value: {{ $json.body.entry[0].changes[0].value.messages[0].document.mime_type }}
    • Operation: Contains
    • Right value: openxmlformats
  5. Set Combine Conditions to: AND (all three must match)
  6. Connect the True output → next node. Connect False → Error Handler (Step 17)
9
Node 3 — Download the .docx File
HTTP Request node · Fetches file binary from WhatsApp
  1. Add an "HTTP Request" node
  2. Method: GET
  3. URL:
https://waba.360dialog.io/v1/media/{{ $json.body.entry[0].changes[0].value.messages[0].document.id }}
  1. Under Headers, add: D360-API-KEYYOUR_360DIALOG_API_KEY
  2. Under Options, set Response Format to: File
💡
Important
Setting Response Format to "File" is critical. Without it, the binary content won't be passed correctly to the DOCX parser in the next step.
10
Node 4 — Parse the Word Document (mammoth.js)
Code node · Extracts text and HTML from .docx · Free
  1. Add a "Code" node → set Language to JavaScript
  2. Paste the following code exactly:
const mammoth = require('mammoth');
const fileData = $input.first().binary.data;
const buffer = Buffer.from(fileData, 'base64');

const htmlResult = await mammoth.convertToHtml({ buffer });
const textResult = await mammoth.extractRawText({ buffer });

return [{
  json: {
    html_content: htmlResult.value,
    plain_text: textResult.value.trim(),
    char_count: textResult.value.trim().length
  }
}];
💰
Cost
Free — mammoth.js is built into n8n's Node.js runtime. No external API call or service needed.
11
Node 5 — AI Enrichment via Claude API
HTTP Request node · Generates SEO metadata + image prompt · ~$0.04/post

5a — The Claude API call

  1. Add an "HTTP Request" node
  2. Method: POST · URL: https://api.anthropic.com/v1/messages
  3. Headers:
    • Content-Type: application/json
    • x-api-key: YOUR_CLAUDE_API_KEY
    • anthropic-version: 2023-06-01
  4. Body (JSON mode):
{
  "model": "claude-sonnet-4-20250514",
  "max_tokens": 800,
  "messages": [{
    "role": "user",
    "content": "Analyse this blog post and return ONLY a valid JSON object with no markdown, no explanation:\n\nBlog content:\n{{ $json.plain_text.substring(0, 3000) }}\n\nReturn this exact JSON structure:\n{\"seo_title\": \"60-char max SEO title\",\"meta_description\": \"155-char max meta description\",\"slug\": \"url-friendly-slug\",\"tags\": [\"tag1\", \"tag2\", \"tag3\"],\"category\": \"most relevant single category\",\"image_prompt\": \"A professional blog featured image showing [describe visual], photorealistic, clean background, suitable for a business blog\",\"excerpt\": \"2-sentence blog excerpt for readers\"}"
  }]
}

5b — Parse the JSON response

  1. Add a "Code" node immediately after → paste this:
const raw = $input.first().json.content[0].text;
const cleaned = raw.replace(/```json|```/g, '').trim();
const parsed = JSON.parse(cleaned);
return [{ json: parsed }];
12
Node 6 — Generate Featured Image (DALL·E 3)
HTTP Request node · Creates image from AI prompt · $0.04/image
  1. Add an "HTTP Request" node
  2. Method: POST · URL: https://api.openai.com/v1/images/generations
  3. Headers: Authorization: Bearer YOUR_OPENAI_API_KEY
  4. Body:
{
  "model": "dall-e-3",
  "prompt": "{{ $json.image_prompt }}",
  "n": 1,
  "size": "1792x1024",
  "quality": "standard"
}
💰
Cost
1792×1024 standard quality = $0.04 per image. This is the ideal aspect ratio for WordPress featured images (landscape 16:9 ish). HD quality would be $0.08 — standard is sufficient.
13
Node 7 — Download the Generated Image
HTTP Request node · Fetches image binary from OpenAI URL
  1. Add an "HTTP Request" node
  2. Method: GET
  3. URL: {{ $json.data[0].url }}
  4. Response Format: File
💡
Note
OpenAI image URLs expire after 1 hour — download immediately in this node rather than storing the URL for later use.
14
Node 8 — Upload Image to WordPress Media Library
HTTP Request node · Uploads binary to /wp-json/wp/v2/media
  1. Add an "HTTP Request" node
  2. Method: POST
  3. URL: https://YOURSITE.com/wp-json/wp/v2/media
  4. Authentication: Basic Auth → Username: your WP admin username · Password: your Application Password
  5. Headers:
    • Content-Disposition: attachment; filename="featured-{{ $now.toISO() }}.jpg"
    • Content-Type: image/jpeg
  6. Body: Binary → set to the file data from the previous node
💡
Key output
The response contains an id field. This media ID is what you'll reference as featured_media in the next step to attach this image to your post.
15
Node 9 — Publish the Blog Post to WordPress
The main publish call — everything comes together here
  1. Add an "HTTP Request" node
  2. Method: POST
  3. URL: https://YOURSITE.com/wp-json/wp/v2/posts
  4. Authentication: Basic Auth (same credentials as Step 14)
  5. Body (JSON):
{
  "title": "{{ $('Parse Claude JSON').item.json.seo_title }}",
  "content": "{{ $('Parse DOCX').item.json.html_content }}",
  "excerpt": "{{ $('Parse Claude JSON').item.json.excerpt }}",
  "slug": "{{ $('Parse Claude JSON').item.json.slug }}",
  "status": "publish",
  "featured_media": {{ $('Upload Image').item.json.id }},
  "meta": {
    "_yoast_wpseo_metadesc": "{{ $('Parse Claude JSON').item.json.meta_description }}",
    "_yoast_wpseo_title": "{{ $('Parse Claude JSON').item.json.seo_title }}"
  }
}
⚠️
Draft vs Publish
Change "status": "publish" to "status": "draft" if you want to review each post before it goes live. You'll get a WhatsApp link to the draft preview instead of the live URL.
16
Node 10 — Send WhatsApp Confirmation Reply
Sends live post URL back to the original sender
  1. Add an "HTTP Request" node
  2. Method: POST · URL: https://waba.360dialog.io/v1/messages
  3. Headers: D360-API-KEY: your 360dialog API key · Content-Type: application/json
  4. Body:
{
  "messaging_product": "whatsapp",
  "to": "{{ $('Webhook').item.json.body.entry[0].changes[0].value.messages[0].from }}",
  "type": "text",
  "text": {
    "body": "✅ Blog published successfully!\n\nTitle: {{ $('Parse Claude JSON').item.json.seo_title }}\n\nURL: {{ $('Publish Post').item.json.link }}"
  }
}
17
Error Handler Node
Catches all failures and alerts you via WhatsApp
  1. Add a final "HTTP Request" node — this is your error catcher
  2. Connect the False branch from the Filter node (Step 8) to this node
  3. In n8n, click each node → look for "On Error" in the settings panel → route all errors to this node
  4. Configure it the same as Step 16 but send the error message to your admin number:
{
  "messaging_product": "whatsapp",
  "to": "YOUR_ADMIN_PHONE_NUMBER",
  "type": "text",
  "text": {
    "body": "❌ Blog automation failed!\n\nError: {{ $execution.error.message }}\n\nNode: {{ $execution.error.node.name }}"
  }
}
  1. Click "Activate" (toggle top right) to enable the workflow
💡
Testing
Send a .docx file from your authorised WhatsApp number to your business number. Watch the n8n Executions panel — each node turns green as it completes. Full run takes 30–60 seconds. Check WordPress for the new post.
Cost Reference

Full Cost Breakdown

Every cost itemised per blog post and per month at 30 posts. All prices in USD.

Cost per single blog post
Based on typical 800–1,500 word blog post
Service Per blog 30 posts/mo Notes
Claude API (SEO metadata + image prompt) $0.04 $1.20 ~2,000 tokens per call
DALL·E 3 (featured image, 1792×1024) $0.04 $1.20 Standard quality
360dialog (outgoing confirmation message) $0.005 $0.15 Per outgoing WhatsApp msg
Hetzner CX21 VPS (amortised) $0.14 $4.10 Fixed cost ÷ 30 posts
360dialog base plan (amortised) $0.23 $7.00 Fixed monthly fee ÷ 30
WordPress REST API $0.00 $0.00 Built into WordPress
mammoth.js (.docx parsing) $0.00 $0.00 Runs inside n8n, free
TOTAL ESTIMATE ~$0.46 / blog ~$13.65 / mo Self-hosted n8n

Monthly cost at different volumes

10 posts/mo
$12
per month
$1.20 / post
30 posts/mo
$14
per month
$0.47 / post
60 posts/mo
$16
per month
$0.27 / post
100 posts/mo
$20
per month
$0.20 / post
📊
Key Insight
Fixed costs (VPS + 360dialog base = ~$11/month) dominate at low volume. At 100 posts/month your per-post cost drops to $0.20. The more you publish, the cheaper each post becomes.

Platform comparison (30 posts/month)

Platform Monthly total Per post Verdict
n8n self-hosted (this guide) $14–20 $0.47 Best value
n8n Cloud (hosted) $24–34 $0.80 No server mgmt
Make (Integromat) $26–42 $0.87 Easier UI
Zapier $50–70 $1.67 Most expensive
Quick Reference

All 17 Steps at a Glance

Complete setup checklist
1
Spin up Hetzner VPS
Ubuntu 24.04 · CX21 · €3.79/mo
2
Install n8n via Docker
docker compose up -d
3
Register 360dialog
Connect Facebook Business Manager · get API key
4
Get Claude API key
console.anthropic.com · pay-as-you-go
5
Get OpenAI API key
platform.openai.com · for DALL·E 3
6
WP Application Password
Users → Profile → Application Passwords
7
Webhook Trigger node
Path: /webhook/whatsapp · Method: POST
8
IF Filter node
Validate sender phone + document type + mime
9
Download .docx node
GET from 360dialog media endpoint · Response: File
10
Parse DOCX node
Code node · mammoth.js · outputs html + plain_text
11
Claude API node
POST api.anthropic.com/v1/messages · parse JSON response
12
DALL·E 3 image node
POST api.openai.com/v1/images/generations
13
Download image node
GET from DALL·E returned URL · Response: File
14
Upload to WP Media
POST /wp-json/wp/v2/media · Basic Auth · save ID
15
Publish WP Post
POST /wp-json/wp/v2/posts · status: publish or draft
16
WhatsApp confirmation
POST to 360dialog · send post URL to sender
17
Error handler
Alert admin number with error details
⏱️
Setup Time
Estimated 4–6 hours total on first run. Most time is waiting for 360dialog WhatsApp approval (1–3 days).
🔁
Ongoing Work
Near-zero maintenance. Review n8n execution logs monthly. Update n8n Docker image quarterly.