Perplexity to WordPress, SEO posts published reliably
Publishing SEO content sounds simple until you’re the one stitching research, drafts, internal links, images, and metadata together at 11pm. Then a week slips by, the draft lives in three different docs, and “we’ll publish tomorrow” turns into “maybe next month.”
If you’re a marketing manager, you’ve felt the pressure to ship content consistently. Agency owners deal with the same chaos across multiple clients. And founders doing their own marketing get hit hardest. This Perplexity WordPress automation turns research into WordPress-ready posts that publish reliably, with linking and sitemap work handled in the background.
You’ll see what the workflow does end-to-end, the results you can expect, what you’ll need to run it, and the key places you can tweak it to match your brand voice.
How This Automation Works
Here’s the complete workflow you’ll be setting up:
n8n Workflow Template: Perplexity to WordPress, SEO posts published reliably
flowchart LR
subgraph sg0["Schedule Flow"]
direction LR
n0["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/wordpress.svg' width='40' height='40' /></div><br/>Create a post1"]
n1@{ icon: "mdi:robot", form: "rounded", label: "Preliminary Plan", pos: "b", h: 48 }
n2["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/perplexity.dark.svg' width='40' height='40' /></div><br/>Message a model"]
n3["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Image Covers2"]
n4@{ icon: "mdi:swap-vertical", form: "rounded", label: "Split Out", pos: "b", h: 48 }
n5["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Code"]
n6@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields4", pos: "b", h: 48 }
n7["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Code1"]
n8@{ icon: "mdi:cog", form: "rounded", label: "Limit", pos: "b", h: 48 }
n9@{ icon: "mdi:swap-vertical", form: "rounded", label: "Split Out1", pos: "b", h: 48 }
n10@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Filter", pos: "b", h: 48 }
n11@{ icon: "mdi:cog", form: "rounded", label: "Limit1", pos: "b", h: 48 }
n21@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields6", pos: "b", h: 48 }
n22@{ icon: "mdi:swap-vertical", form: "rounded", label: "Split Out3", pos: "b", h: 48 }
n23@{ icon: "mdi:cog", form: "rounded", label: "Aggregate3", pos: "b", h: 48 }
n24["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/merge.svg' width='40' height='40' /></div><br/>Merge"]
n25@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields5", pos: "b", h: 48 }
n26@{ icon: "mdi:robot", form: "rounded", label: "Structured Output Parser1", pos: "b", h: 48 }
n27@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields7", pos: "b", h: 48 }
n28@{ icon: "mdi:brain", form: "rounded", label: "OpenAI Chat Model", pos: "b", h: 48 }
n29@{ icon: "mdi:cog", form: "rounded", label: "Aggregate4", pos: "b", h: 48 }
n32@{ icon: "mdi:robot", form: "rounded", label: "Intro", pos: "b", h: 48 }
n33@{ icon: "mdi:robot", form: "rounded", label: "dev 1", pos: "b", h: 48 }
n34@{ icon: "mdi:robot", form: "rounded", label: "dev 2", pos: "b", h: 48 }
n35@{ icon: "mdi:robot", form: "rounded", label: "conclusion", pos: "b", h: 48 }
n36["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/merge.svg' width='40' height='40' /></div><br/>Merge2"]
n37@{ icon: "mdi:cog", form: "rounded", label: "Aggregate5", pos: "b", h: 48 }
n38@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields9", pos: "b", h: 48 }
n39@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields10", pos: "b", h: 48 }
n40@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields11", pos: "b", h: 48 }
n41@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields12", pos: "b", h: 48 }
n42["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/github.dark.svg' width='40' height='40' /></div><br/>get sitemap1"]
n43@{ icon: "mdi:cog", form: "rounded", label: "Extract from File2", pos: "b", h: 48 }
n44@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields8", pos: "b", h: 48 }
n45["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/github.dark.svg' width='40' height='40' /></div><br/>Edit a file1"]
n46@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields13", pos: "b", h: 48 }
n47["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/github.dark.svg' width='40' height='40' /></div><br/>get articles.json1"]
n48@{ icon: "mdi:cog", form: "rounded", label: "Extract from File3", pos: "b", h: 48 }
n49@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields15", pos: "b", h: 48 }
n50["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/github.dark.svg' width='40' height='40' /></div><br/>Edit a file"]
n51@{ icon: "mdi:robot", form: "rounded", label: "header post", pos: "b", h: 48 }
n52@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields14", pos: "b", h: 48 }
n53@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Filter1", pos: "b", h: 48 }
n57["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Code6"]
n58["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/merge.svg' width='40' height='40' /></div><br/>Merge3"]
n59["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Code7"]
n60@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields", pos: "b", h: 48 }
n61@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields1", pos: "b", h: 48 }
n62@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields2", pos: "b", h: 48 }
n63["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Code9"]
n64@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields16", pos: "b", h: 48 }
n65@{ icon: "mdi:cog", form: "rounded", label: "Limit3", pos: "b", h: 48 }
n66@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields17", pos: "b", h: 48 }
n70@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields18", pos: "b", h: 48 }
n71@{ icon: "mdi:cog", form: "rounded", label: "Aggregate", pos: "b", h: 48 }
n72@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields19", pos: "b", h: 48 }
n73["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>submit sitemap"]
n74@{ icon: "mdi:swap-vertical", form: "rounded", label: "set sitemap variables", pos: "b", h: 48 }
n78["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Quality?"]
n79["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>size?"]
n80["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/github.dark.svg' width='40' height='40' /></div><br/>Create blog"]
n81["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>select blog table"]
n82@{ icon: "mdi:cog", form: "rounded", label: "limit to 1", pos: "b", h: 48 }
n83["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>blog table"]
n84@{ icon: "mdi:robot", form: "rounded", label: "create plan for dev", pos: "b", h: 48 }
n85["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/slack.svg' width='40' height='40' /></div><br/>wait approval"]
n86["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>Log blog link for future int.."]
n89@{ icon: "mdi:brain", form: "rounded", label: "OpenRouter Chat Model6", pos: "b", h: 48 }
n90@{ icon: "mdi:robot", form: "rounded", label: "FAQ section", pos: "b", h: 48 }
n91@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields20", pos: "b", h: 48 }
n92@{ icon: "mdi:play-circle", form: "rounded", label: "Schedule Trigger1", pos: "b", h: 48 }
n94@{ icon: "mdi:brain", form: "rounded", label: "OpenAI Chat Model2", pos: "b", h: 48 }
n96@{ icon: "mdi:brain", form: "rounded", label: "OpenAI Chat Model3", pos: "b", h: 48 }
n97@{ icon: "mdi:brain", form: "rounded", label: "OpenAI Chat Model4", pos: "b", h: 48 }
n98@{ icon: "mdi:brain", form: "rounded", label: "OpenAI Chat Model5", pos: "b", h: 48 }
n99@{ icon: "mdi:brain", form: "rounded", label: "OpenAI Chat Model6", pos: "b", h: 48 }
n5 --> n6
n7 --> n5
n57 --> n47
n57 --> n46
n57 --> n62
n59 --> n49
n63 --> n45
n32 --> n38
n8 --> n52
n24 --> n29
n33 --> n39
n34 --> n40
n79 --> n53
n10 --> n8
n11 --> n25
n65 --> n64
n65 --> n66
n36 --> n37
n58 --> n65
n53 --> n11
n78 --> n79
n71 --> n24
n4 --> n7
n23 --> n24
n29 --> n32
n29 --> n33
n29 --> n34
n29 --> n35
n29 --> n51
n29 --> n90
n37 --> n60
n9 --> n78
n22 --> n21
n83 --> n70
n35 --> n41
n82 --> n1
n80 --> n58
n60 --> n57
n50 --> n58
n90 --> n91
n51 --> n36
n61 --> n59
n62 --> n80
n62 --> n0
n6 --> n10
n25 --> n24
n21 --> n23
n27 --> n84
n44 --> n63
n38 --> n36
n45 --> n58
n42 --> n43
n39 --> n36
n40 --> n36
n41 --> n36
n46 --> n42
n52 --> n24
n49 --> n50
n64 --> n85
n66 --> n86
n70 --> n71
n72 --> n3
n91 --> n36
n3 --> n4
n85 --> n74
n0 --> n74
n0 --> n66
n2 --> n9
n2 --> n22
n2 --> n27
n2 --> n72
n2 --> n83
n1 --> n2
n28 -.-> n84
n92 --> n81
n81 --> n82
n43 --> n44
n48 --> n61
n94 -.-> n51
n96 -.-> n32
n97 -.-> n33
n98 -.-> n35
n99 -.-> n34
n47 --> n48
n84 --> n24
n74 --> n73
n89 -.-> n90
n26 -.-> n84
end
subgraph sg1["Schedule Flow"]
direction LR
n12@{ icon: "mdi:cog", form: "rounded", label: "Aggregate2", pos: "b", h: 48 }
n13@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields3", pos: "b", h: 48 }
n14@{ icon: "mdi:robot", form: "rounded", label: "Structured Output Parser", pos: "b", h: 48 }
n15["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>Insert rows in a table"]
n16["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>Select rows from a table1"]
n17["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>Select rows from a table2"]
n18@{ icon: "mdi:swap-vertical", form: "rounded", label: "Split Out2", pos: "b", h: 48 }
n19["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Code4"]
n20["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Code5"]
n67["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>Fetch Keywords1"]
n68@{ icon: "mdi:database", form: "rounded", label: "Select rows from a table in ..", pos: "b", h: 48 }
n69@{ icon: "mdi:play-circle", form: "rounded", label: "Schedule Trigger", pos: "b", h: 48 }
n75@{ icon: "mdi:robot", form: "rounded", label: "Choose keywords, Intent, etc", pos: "b", h: 48 }
n76["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>Primary keywords"]
n77["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>Used secondary"]
n93@{ icon: "mdi:brain", form: "rounded", label: "OpenAI Chat Model1", pos: "b", h: 48 }
n95@{ icon: "mdi:cog", form: "rounded", label: "Limit2", pos: "b", h: 48 }
n19 --> n77
n20 --> n76
n95 --> n13
n12 --> n75
n18 --> n17
n13 --> n12
n67 --> n95
n69 --> n67
n93 -.-> n75
n14 -.-> n75
n16 --> n20
n17 --> n19
n75 --> n15
n75 --> n16
n75 --> n18
n68 -.-> n75
end
subgraph sg2["Flow 3"]
direction LR
n54["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>Select rows from a table"]
n55["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/code.svg' width='40' height='40' /></div><br/>Score Keywords"]
n56@{ icon: "mdi:swap-vertical", form: "rounded", label: "Loop Over Items", pos: "b", h: 48 }
n87["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/postgres.svg' width='40' height='40' /></div><br/>Update score"]
n88@{ icon: "mdi:cog", form: "rounded", label: "All scored", pos: "b", h: 48 }
n87 --> n56
n55 --> n87
n56 --> n88
n56 --> n55
n54 --> n56
end
subgraph sg3["Flow 4"]
direction LR
n30@{ icon: "mdi:brain", form: "rounded", label: "OpenRouter Chat Model1", pos: "b", h: 48 }
end
subgraph sg4["Flow 5"]
direction LR
n31@{ icon: "mdi:brain", form: "rounded", label: "OpenRouter Chat Model2", pos: "b", h: 48 }
end
%% Styling
classDef trigger fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
classDef ai fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
classDef aiModel fill:#e8eaf6,stroke:#3f51b5,stroke-width:2px
classDef decision fill:#fff8e1,stroke:#f9a825,stroke-width:2px
classDef database fill:#fce4ec,stroke:#c2185b,stroke-width:2px
classDef api fill:#fff3e0,stroke:#e65100,stroke-width:2px
classDef code fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef disabled stroke-dasharray: 5 5,opacity: 0.5
class n92,n69 trigger
class n1,n26,n32,n33,n34,n35,n51,n84,n90,n14,n75 ai
class n28,n89,n94,n96,n97,n98,n99,n93,n30,n31 aiModel
class n10,n53 decision
class n81,n83,n86,n15,n16,n17,n67,n68,n76,n77,n54,n87 database
class n3,n73 api
class n5,n7,n57,n59,n63,n78,n79,n19,n20,n55 code
classDef customIcon fill:none,stroke:none
class n0,n2,n3,n5,n7,n24,n36,n42,n45,n47,n50,n57,n58,n59,n63,n73,n78,n79,n80,n81,n83,n85,n86,n15,n16,n17,n19,n20,n67,n76,n77,n54,n55,n87 customIcon
Why This Matters: Publishing SEO Content Without Dropped Balls
The real problem usually isn’t “writing.” It’s everything wrapped around it. You start with keyword research in one place, competitor notes in another, a half-outline somewhere else, then you’re hunting for internal links you vaguely remember writing last year. Add images, formatting, categories, meta fields, and the last-mile steps like sitemap updates and indexing. That’s how a post that should be a routine publish turns into a multi-day project, and honestly, it’s why teams stop being consistent.
The friction compounds. Here’s where it breaks down in day-to-day work.
- Keyword lists get reused or forgotten, which leads to cannibalized topics and wasted effort.
- Research and outlining takes forever because you’re switching tools and reformatting the same notes repeatedly.
- Internal links are added late (or not at all), so posts don’t support each other and rankings move slower.
- Publishing steps are fragile: a missed image, a broken sitemap update, or “we’ll submit indexing later” silently drags performance down.
What You’ll Build: Perplexity Research → WordPress-Ready Posts With SEO Infrastructure
This workflow is a full content pipeline, not a single “write me a blog post” button. It starts with a scheduled run that pulls your keyword list, scores it, and picks the next best topic based on relevance and competition. From there it uses Perplexity for deep research and planning, then hands the structured outline and context to writing models (OpenAI/OpenRouter plus an Anthropic chat model in the mix) to generate a multi-part long-form article. While content is being assembled, the workflow also pulls your existing article data so it can recommend and insert internal links in a consistent, scalable way. Finally, it outputs a WordPress-ready article (and can publish), commits supporting files through GitHub, updates your sitemap, and submits it so indexing doesn’t get “left for later.”
The workflow starts on a schedule, selects and locks in a keyword, then does research and outlining with Perplexity. Next it generates the intro, body sections, conclusion, and FAQ, runs basic quality/size checks, and prepares WordPress-ready output. At the end, it updates your publishing files (including sitemap and articles JSON) via GitHub and triggers sitemap submission.
What You’re Building
| What Gets Automated | What You’ll Achieve |
|---|---|
|
|
Expected Results
Say you publish 3 posts a week. Manually, a typical cycle might look like: about 45 minutes of keyword cleanup, 60 minutes of research, 60 minutes of formatting/internal linking in WordPress, then another 15 minutes for sitemap and indexing tasks. That’s roughly 3 hours per post, or about 9 hours a week. With this workflow, you spend maybe 20 minutes reviewing and adjusting the final draft and links, while the research, writing, file updates, and sitemap submission run on their own. You get most of that week back.
Before You Start
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- Perplexity for research and article planning prompts.
- WordPress to publish or import WordPress-ready output.
- OpenAI / OpenRouter / Anthropic API access for writing and refinement.
- PostgreSQL to store keyword scoring and prevent reuse.
- GitHub to store article JSON and sitemap files.
Skill level: Intermediate. You won’t write code from scratch, but you should be comfortable adding credentials, mapping fields, and testing a run end-to-end.
Want someone to build this for you? Talk to an automation expert (free 15-minute consultation).
Step by Step
A scheduled run selects the next keyword. n8n pulls your keyword list from PostgreSQL (or a connected source), applies a scoring formula, and chooses the best candidate. It also logs the decision so the same keyword doesn’t get reused too soon.
Research and outlining happens automatically. Perplexity is queried to gather authoritative context and sources, and the workflow turns that into a structured outline. This is where the “blank page” problem disappears because you start with direction, not guesses.
The article is written in sections, then checked. Separate AI chains create an introduction, multiple body parts, a conclusion, and an FAQ. Then lightweight quality and size checks run, so you don’t end up publishing something that’s thin, repetitive, or oddly formatted.
WordPress-ready output, linking, and sitemap updates go out. The workflow generates a WordPress article payload, updates your article index files in GitHub, updates sitemap content, and submits the sitemap via HTTP request. Optional Slack approval can be inserted before anything goes live.
You can easily modify the keyword scoring and the internal linking rules to match your site goals. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Schedule Trigger
This workflow starts on a schedule for both keyword processing and blog table selection. Configure both triggers so the downstream keyword and draft generation flows run at the right cadence.
- Open Scheduled Run A and define the schedule that should start the keyword scoring pipeline.
- Open Scheduled Run B and define the schedule that should start the blog table selection pipeline.
- Verify Scheduled Run A is connected to Fetch Keyword List.
- Verify Scheduled Run B is connected to Select Blog Table and then to Limit To One.
Tip: Keep the schedules offset to reduce load if both branches query large tables at the same time.
Step 2: Connect Postgres Data Sources
Multiple Postgres nodes handle keyword lists, intent selection, scoring, and logging. Ensure all Postgres connections are configured consistently across the workflow.
- Open Fetch Keyword List and configure the query for the keyword source table.
- Configure Select Blog Table and Blog Table Rows to pull blog metadata used by downstream generation steps.
- Configure intent and keyword set nodes: Select DB Rows A, Select DB Rows B, Select DB Rows C, Primary Keyword Set, and Secondary Keyword Set.
- Configure write-back nodes: Insert DB Rows, Log Blog Link, and Update Term Score.
- Credential Required: Connect your Postgres credentials for all Postgres nodes listed above.
⚠️ Common Pitfall: If any Postgres node is missing credentials, the keyword scoring and blog publishing branches will stop before content assembly.
Step 3: Set Up AI/LLM Generation and Parsers
AI nodes generate outlines, content sections, and the development plan. Parsers and tools are attached to AI agents and must inherit credentials from their parent nodes.
- Configure Draft Outline Step and Query AI Model for outline generation and research.
- Connect language models for content composition: OpenAI Chat Intro → Compose Introduction, OpenAI Chat Body A → Compose Body Part A, OpenAI Chat Body B → Compose Body Part B, OpenAI Chat Outro → Compose Conclusion, OpenAI Chat Header → Compose Header, and OpenRouter Chat C → Compose FAQ.
- Ensure OpenAI Chat Core is connected as the language model for Generate Dev Plan.
- Structured Parser A and Structured Parser B are AI sub-nodes; add credentials to their parent nodes (Select Keyword Intent and Generate Dev Plan), not to the parsers.
- Postgres Tool Select is an AI tool sub-node; add Postgres credentials to the parent node Select Keyword Intent, not to the tool.
- Credential Required: Connect your OpenAI credentials for Draft Outline Step, OpenAI Chat Core, OpenAI Chat Keywords, OpenAI Chat Header, OpenAI Chat Intro, OpenAI Chat Body A, OpenAI Chat Body B, and OpenAI Chat Outro.
- Credential Required: Connect your OpenRouter credentials for OpenRouter Chat A, OpenRouter Chat B, and OpenRouter Chat C.
- Credential Required: Connect your Perplexity credentials for Query AI Model.
Tip: Keep consistent system prompts across Compose Introduction, Compose Body Part A, Compose Body Part B, Compose Conclusion, Compose Header, and Compose FAQ for a unified tone.
Step 4: Configure Data Processing, Filtering, and Parallel Branches
This workflow uses multiple transform, set, and filter steps to prepare data and gate content quality. Several nodes run in parallel, so ensure every branch is configured and connected.
- Confirm the initial image path: Map Fields T → Fetch Image Covers → Split Items A → Transform Script B → Transform Script A → Map Fields A → Filter Records A → Apply Limit A → Map Fields M.
- Verify quality gates: Split Items B → Quality Check → Size Check → Filter Records B → Apply Limit B → Map Fields D.
- Ensure keyword and draft aggregation: Map Fields B → Aggregate Keywords → Select Keyword Intent and Map Fields C → Aggregate Drafts.
- Query AI Model outputs to Split Items B, Split Items D, Map Fields E, Map Fields T, and Blog Table Rows in parallel.
- Aggregate Sections outputs to Compose Introduction, Compose Body Part A, Compose Body Part B, Compose Conclusion, Compose Header, and Compose FAQ in parallel.
- Group-configure all Transform Script and Map Fields nodes (10+ and 22+ respectively) to ensure consistent field naming before merges and aggregations.
⚠️ Common Pitfall: If any parallel branch is disconnected (especially from Aggregate Sections), the final article will miss sections and fail downstream merges.
Step 5: Configure Content Assembly and File Management
This section combines AI-generated sections, updates content files in GitHub, and prepares the final payload for publishing and sitemap submission.
- Verify the assembly chain: Combine Streams A → Aggregate Sections → Combine Sections → Aggregate Final → Map Fields N → Transform Script E.
- Transform Script E outputs to Retrieve Articles JSON, Map Fields K, and Map Fields P in parallel.
- Configure GitHub file operations: Retrieve Articles JSON → Extract Articles Data → Map Fields O → Transform Script F → Map Fields L → Update Articles File.
- Configure sitemap path: Map Fields K → Retrieve Sitemap File → Extract Sitemap Data → Map Fields J → Transform Script G → Update Sitemap File.
- Map Fields P outputs to both Create Blog File and Generate WP Article in parallel.
- Credential Required: Connect your GitHub credentials for Retrieve Articles JSON, Create Blog File, Update Articles File, Retrieve Sitemap File, and Update Sitemap File.
Step 6: Configure Publishing, Approval, and Submission
The publishing branch sends content to WordPress, requests approval, and submits the sitemap update. Ensure these integrations are fully authorized.
- Configure Generate WP Article to post to the correct WordPress site and content type.
- Generate WP Article outputs to Assign Sitemap Vars and Map Fields R in parallel, so ensure both connections remain intact.
- Apply Limit C outputs to Map Fields Q and Map Fields R in parallel; Map Fields Q then routes to Request Approval.
- Verify Request Approval → Assign Sitemap Vars → Submit Sitemap for notifying and submitting updates.
- Credential Required: Connect your WordPress credentials for Generate WP Article.
- Credential Required: Connect your Slack credentials for Request Approval.
- Credential Required: Connect any required HTTP authentication for Submit Sitemap if your endpoint is protected.
Step 7: Configure Scoring Loop and Logging
This branch iterates through database records to score and update terms, then logs the final blog link after publishing.
- Validate the scoring loop: Select DB Rows C → Iterate Records → Score Terms → Update Term Score → Iterate Records → Scores Complete.
- Confirm the logging branch: Map Fields R → Log Blog Link.
- Credential Required: Connect your Postgres credentials for Select DB Rows C, Update Term Score, and Log Blog Link.
Step 8: Test and Activate Your Workflow
Run end-to-end tests on both scheduled branches to validate all parallel paths, AI generation, and publishing actions before enabling production schedules.
- Manually execute Scheduled Run A and confirm keywords flow through Fetch Keyword List, Select Keyword Intent, and the AI composition branch.
- Manually execute Scheduled Run B and confirm Select Blog Table → Limit To One → Draft Outline Step → Query AI Model.
- Verify a successful run creates content in Generate WP Article, updates GitHub files through Update Articles File and Update Sitemap File, and submits through Submit Sitemap.
- Check that Log Blog Link writes the published URL and Scores Complete is reached for scoring loops.
- Activate both schedules by enabling Scheduled Run A and Scheduled Run B for production use.
Troubleshooting Tips
- GitHub credentials can expire or need specific repository permissions. If commits fail, check the n8n GitHub credential scope and the repo access token first.
- If you’re using Wait nodes or external rendering, processing times vary. Bump up the wait duration if downstream nodes fail on empty responses.
- Perplexity and LLM prompts drift over time if you keep them generic. Add your brand voice and formatting rules early (intro/body/FAQ prompts) or you will spend your “saved time” editing everything.
Quick Answers
About 60–90 minutes if you already have your credentials handy.
No. You will mostly connect accounts and adjust prompts and field mappings.
Yes. n8n has a free self-hosted option and a free trial on n8n Cloud. Cloud plans start at $20/month for higher volume. You’ll also need to factor in Perplexity and LLM API costs, which usually land around a few dollars per long-form post depending on length and model choice.
Two options: n8n Cloud (managed, easiest setup) or self-hosting on a VPS. For self-hosting, Hostinger VPS is affordable and handles n8n well. Self-hosting gives you unlimited executions but requires basic server management.
Yes, and you should. Most teams start by changing the keyword scoring logic (the Score Terms step) and the writing prompts used in Compose Introduction / Compose Body Part A / Compose Body Part B / Compose FAQ so the tone matches the brand. You can also swap the publishing destination: keep “Generate WP Article” for WordPress-ready output, or lean harder into the GitHub steps if your site deploys from a repo.
Usually it’s a token scope issue. Regenerate your GitHub token with repo write permissions, then update the credential in n8n. Also confirm the workflow is pointing at the correct repository and branch, because a surprising number of “auth errors” are really “wrong repo” problems.
If you self-host, there’s no fixed execution cap (it mostly depends on your server and API rate limits). On n8n Cloud, your plan sets execution limits, so higher posting volume usually means upgrading. In practice, many teams run this a few times per day or a few times per week, and that’s already enough to keep a content calendar full.
Often, yes, because this workflow has a lot going on. You’re doing multi-step research, long-form generation, branching checks, database logging, file updates, and sitemap submission. n8n handles complex logic without punishing you for every branch, and self-hosting keeps execution costs predictable. Zapier or Make can still work if you trim the scope down to “generate draft and send it somewhere,” but the full content infrastructure is harder to replicate cleanly. Talk to an automation expert if you want a quick recommendation for your exact setup.
This is what consistent publishing looks like when the system does the repetitive parts for you. Set it up once, then focus your time on angles, offers, and distribution instead of busywork.
Need Help Setting This Up?
Our automation experts can build and customize this workflow for your specific needs. Free 15-minute consultation—no commitment required.