This workflow corresponds to n8n.io template #9217 — we link there as the canonical source.
This workflow follows the Agent → OpenAI Chat recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "ai-wordpress-blog-automation",
"meta": {
"templateCredsSetupCompleted": false
},
"name": "AI-Powered WordPress Content Workflow",
"tags": [],
"nodes": [
{
"id": "291e2ca0-6eb2-4e69-a147-2369e7f27257",
"name": "\ud83d\uddc4\ufe0f PostgreSQL Trigger",
"type": "n8n-nodes-base.postgres",
"position": [
-672,
80
],
"parameters": {
"query": "SELECT *\nFROM \"your_table_name\"\nWHERE \"Processed\" = FALSE OR \"Processed\" IS NULL\nORDER BY \"Created_At\" DESC\nLIMIT 1;",
"options": {},
"operation": "executeQuery"
},
"credentials": {
"postgres": {
"name": "<your credential>"
}
},
"typeVersion": 2.4
},
{
"id": "7fbc5898-0f88-46e8-96ce-e4e215122974",
"name": "\u23f0 Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-896,
80
],
"parameters": {
"rule": {
"interval": [
{}
]
}
},
"typeVersion": 1.1
},
{
"id": "057ddc57-2019-4cad-acdd-a3a69976512d",
"name": "\ud83d\udcdd Format Blog Data",
"type": "n8n-nodes-base.code",
"position": [
128,
80
],
"parameters": {
"jsCode": "// Parse the AI response safely\nconst input = $input.first().json;\n\n// Handle payload structure: sometimes response, sometimes output\nconst aiResponse = input.response || input.output || JSON.stringify(input);\n\n// Try to parse JSON from AI response\nlet blogData;\ntry {\n const jsonMatch =\n aiResponse.match(/```json\\s*([\\s\\S]*?)\\s*```/) ||\n aiResponse.match(/{[\\s\\S]*}/);\n\n if (jsonMatch) {\n blogData = JSON.parse(jsonMatch[1] || jsonMatch[0]);\n } else {\n throw new Error(\"No JSON structure found\");\n }\n} catch (error) {\n const safeText = aiResponse || \"AI did not return text.\";\n blogData = {\n title: safeText.split(\"\\n\")[0] || \"Generated Blog Post\",\n content: safeText,\n excerpt: safeText.substring(0, 200) + \"...\",\n meta_description: safeText.substring(0, 160),\n };\n}\n\n// Ensure fallback values\nconst safeTitle = blogData.title || \"AI Generated Marketing Content\";\nconst safeContent = blogData.content || \"No content generated.\";\nconst safeExcerpt =\n blogData.excerpt || safeContent.substring(0, 200) + \"...\";\nconst safeMeta =\n blogData.meta_description || safeContent.substring(0, 160);\n\n// Get the original database record\nlet dbRecord = {};\ntry {\n dbRecord = $('\ud83d\uddc4\ufe0f PostgreSQL Trigger').item.json || {};\n} catch (e) {\n dbRecord = { id: \"unknown\", source: \"no-db-record\" };\n}\n\n// Return structured data for WordPress\nreturn {\n json: {\n title: safeTitle,\n content: safeContent,\n excerpt: safeExcerpt,\n status: \"publish\",\n categories: [\"Marketing\"],\n tags: [\"AI\", \"PostgreSQL\", \"WordPress\", \"Marketing\", \"Automation\"],\n meta_description: safeMeta,\n original_record_id: dbRecord.id || \"no-id\",\n source_data: dbRecord,\n },\n};"
},
"typeVersion": 2
},
{
"id": "a2eeca41-110d-4c61-856d-409e8ce0661f",
"name": "\u270d\ufe0f WordPress Publisher",
"type": "n8n-nodes-base.wordpress",
"position": [
352,
80
],
"parameters": {
"tags": {
"tags": [
"AI",
"PostgreSQL",
"WordPress",
"Marketing",
"Automation"
]
},
"title": "={{ $json.title }}",
"status": "publish",
"content": "={{ $json.content }}",
"excerpt": "={{ $json.excerpt }}",
"categories": {
"categories": [
"Marketing"
]
},
"additionalFields": {
"meta": {
"metaProperties": [
{
"key": "meta_description",
"value": "={{ $json.meta_description }}"
}
]
}
}
},
"credentials": {
"wordpressApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "946b27ee-37ea-4b82-867b-624f281727d3",
"name": "\ud83d\udcbe Update Database",
"type": "n8n-nodes-base.postgres",
"position": [
576,
80
],
"parameters": {
"query": "UPDATE \"your_table_name\"\nSET \n \"Processed\" = TRUE,\n \"Wordpress_Post_Id\" = $1,\n \"Wordpress_Post_Url\" = $2,\n \"Blog_Title\" = $3,\n \"Processed_At\" = NOW()\nWHERE \"id\" = $4;",
"options": {},
"operation": "executeQuery",
"additionalFields": {
"queryParameters": {
"parameters": [
{
"value": "={{ $json.id }}"
},
{
"value": "={{ $json.link }}"
},
{
"value": "={{ $json.title.rendered }}"
},
{
"value": "={{ $('\ud83d\udcdd Format Blog Data').item.json.original_record_id }}"
}
]
}
}
},
"credentials": {
"postgres": {
"name": "<your credential>"
}
},
"typeVersion": 2.4
},
{
"id": "3254f143-fe85-49c8-a454-bb9729fd77dc",
"name": "OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
-176,
288
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "dde2cc13-b8a2-4771-beb6-09e7fc31a352",
"name": "\ud83d\udd0d Check Record Exists",
"type": "n8n-nodes-base.if",
"position": [
-448,
80
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "condition_1",
"operator": {
"type": "number",
"operation": "exists",
"singleValue": true
},
"leftValue": "={{ $json.id }}",
"rightValue": 0
},
{
"id": "c9785b0c-f86c-4293-a5b3-8825e74ad0c4",
"operator": {
"type": "string",
"operation": "exists",
"singleValue": true
},
"leftValue": "={{ $json.Blog_Title }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2
},
{
"id": "cdacc933-4448-40b8-a9c5-242bf766d62a",
"name": "\ud83e\udd16 Generates Blog Post",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
-224,
80
],
"parameters": {
"text": "=You are an expert marketing content writer. Create engaging, SEO-optimized blog posts that convert readers into customers.\n\nUser Message:\nCreate a comprehensive marketing blog post based on this title: \n{{ $json.Blog_Title }}\n\nThe blog post should include:\n1. A catchy, SEO-friendly title\n2. An engaging introduction that hooks the reader\n3. Well-structured body content with subheadings\n4. A compelling conclusion with a call-to-action\n5. Optimize for marketing and conversion\n\nFormat the response as JSON with these fields:\n- title: The blog post title\n- content: The full HTML content of the blog post\n- excerpt: A brief excerpt (150-200 characters)\n- meta_description: SEO meta description (150-160 characters)",
"options": {},
"promptType": "define"
},
"typeVersion": 2.2
},
{
"id": "d2941310-5f0a-43fa-a232-f68f0b990f78",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-944,
-320
],
"parameters": {
"width": 432,
"height": 720,
"content": "## 1. Trigger & Data Fetch\n\n**Schedule Trigger (\u23f0 Schedule Trigger)**: Initiates the workflow at regular intervals.\n\n**PostgreSQL Query (\ud83d\uddc4\ufe0f PostgreSQL Trigger)**: Fetches the latest unprocessed record from your database table.\n\n**Record Existence Check (\ud83d\udd0d Check Record Exists)**: Ensures only valid, non-empty records are processed."
},
"typeVersion": 1
},
{
"id": "539c0737-da51-4e7f-8127-fefd690f75d5",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-496,
-320
],
"parameters": {
"color": 4,
"width": 560,
"height": 720,
"content": "## 2. AI Content Generation\n\n**OpenAI Chat Model (OpenAI Chat Model)**: Receives record input and generates blog content based on the title.\n\n**Blog Post Agent (\ud83e\udd16 Generates Blog Post)**: Structures AI output into a JSON format with:\n- Title\n- Content (HTML)\n- Excerpt (150\u2013200 characters)\n- Meta description (SEO, 150\u2013160 characters)"
},
"typeVersion": 1
},
{
"id": "252aa9dd-5b44-4ba2-8621-19895689f740",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
80,
-320
],
"parameters": {
"color": 3,
"width": 208,
"height": 720,
"content": "## 3. Data Formatting & Safety\n\n**Code Node (\ud83d\udcdd Format Blog Data)**:\nPrepares a structured payload for WordPress, including:\n- Categories and tags\n- Original database record reference\n- Error handling for malformed AI responses"
},
"typeVersion": 1
},
{
"id": "af0ac8f3-d7e9-4546-8b27-02c1d9629d23",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
304,
-320
],
"parameters": {
"color": 5,
"width": 432,
"height": 720,
"content": "## 4. Publishing & Database Update\n\n**WordPress Publisher (\u270d\ufe0f WordPress Publisher)**: Publishes the formatted blog content to WordPress with proper categories, tags, and meta data.\n\n**Database Update (\ud83d\udcbe Update Database)**: After successful publishing, updates the original record to:\n- Mark it as processed\n- Store WordPress post ID and URL\n- Record processing timestamp\n\n**Purpose**: Ensures content is live and database stays synchronized."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "00000000-0000-0000-0000-000000000000",
"connections": {
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "\ud83e\udd16 Generates Blog Post",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"\u23f0 Schedule Trigger": {
"main": [
[
{
"node": "\ud83d\uddc4\ufe0f PostgreSQL Trigger",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udcbe Update Database": {
"main": [
[]
]
},
"\ud83d\udcdd Format Blog Data": {
"main": [
[
{
"node": "\u270d\ufe0f WordPress Publisher",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udd0d Check Record Exists": {
"main": [
[
{
"node": "\ud83e\udd16 Generates Blog Post",
"type": "main",
"index": 0
}
],
[]
]
},
"\ud83e\udd16 Generates Blog Post": {
"main": [
[
{
"node": "\ud83d\udcdd Format Blog Data",
"type": "main",
"index": 0
}
]
]
},
"\u270d\ufe0f WordPress Publisher": {
"main": [
[
{
"node": "\ud83d\udcbe Update Database",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\uddc4\ufe0f PostgreSQL Trigger": {
"main": [
[
{
"node": "\ud83d\udd0d Check Record Exists",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
openAiApipostgreswordpressApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow automatically generates and publishes marketing blog posts to WordPress using AI. It begins by checking your PostgreSQL database for unprocessed records, then uses OpenAI to create SEO-friendly, structured blog content. The content is formatted for WordPress,…
Source: https://n8n.io/workflows/9217/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Complete PostgreSQL-backed system: Keyword scoring → AI research → Multi-part content generation → fal.ai Nano Banana image generation → WordPress publishing
This workflow contains community nodes that are only compatible with the self-hosted version of n8n.
We’ve released Version 4 of our AI Powered Blog Automation workflow. We heard your complains and made a complete redesign built for serious content creators.
This workflow is for beauty salons who want consistent, high‑quality social media content without writing every post manually. It also suits agencies and automation builders who manage multiple beauty
Automate Microsoft Teams Meeting Analysis with GPT-4.1, Outlook & Mem.ai Watch the YouTube video to get started Follow along with the blog post