Google Sheets to WordPress, publish ready posts
Your content pipeline probably isn’t stuck because you can’t write. It’s stuck because publishing is a dozen tiny steps that never end: research, outlines, drafts, images, links, formatting, uploads, backups.
Content managers feel it when the calendar slips. Agency owners feel it when clients want “two posts a week” and approvals drag. And a solo founder? You just want Sheets WordPress automation that turns “topic ideas” into posts without babysitting every click.
This n8n workflow takes a new Google Sheets row, does deep research, writes a full SEO post with images and internal links, and publishes it to WordPress (or saves as a draft). You’ll see what it automates, what you get out of it, and what to watch for.
How This Automation Works
The full n8n workflow, from trigger to final output:
n8n Workflow Template: Google Sheets to WordPress, publish ready posts
flowchart LR
subgraph sg0["Google Sheets Flow"]
direction LR
n0@{ icon: "mdi:robot", form: "rounded", label: "Generate featured image", pos: "b", h: 48 }
n1["<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"]
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/httprequest.dark.svg' width='40' height='40' /></div><br/>Get post sitemap"]
n3@{ icon: "mdi:cog", form: "rounded", label: "Get XML file", pos: "b", h: 48 }
n4@{ icon: "mdi:swap-vertical", form: "rounded", label: "Split out links", pos: "b", h: 48 }
n5@{ icon: "mdi:robot", form: "rounded", label: "Generate chapter image", pos: "b", h: 48 }
n6@{ icon: "mdi:cog", form: "rounded", label: "Resize Image", 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/httprequest.dark.svg' width='40' height='40' /></div><br/>Upload chapter images"]
n8["<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 chapters title and text"]
n9["<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/markdown.dark.svg' width='40' height='40' /></div><br/>Markdown to HTML"]
n10["<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/>Post on Wordpress"]
n11@{ icon: "mdi:cog", form: "rounded", label: "Resize featured image", pos: "b", h: 48 }
n12["<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/>Upload featured image"]
n13["<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/>Set featured image for post"]
n14["<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/>Update image meta data"]
n15@{ icon: "mdi:swap-vertical", form: "rounded", label: "Loop Over Items", pos: "b", h: 48 }
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/httprequest.dark.svg' width='40' height='40' /></div><br/>Update featured image meta d.."]
n17@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields", pos: "b", h: 48 }
n18["<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/>Set excerpt"]
n19@{ icon: "mdi:cog", form: "rounded", label: "Wait1", pos: "b", h: 48 }
n20@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Check inputs", pos: "b", h: 48 }
n21@{ icon: "mdi:cog", form: "rounded", label: "Save texts to Doc", pos: "b", h: 48 }
n22@{ icon: "mdi:cog", form: "rounded", label: "Create Doc", pos: "b", h: 48 }
n23@{ icon: "mdi:cog", form: "rounded", label: "Upload featured image to Drive", pos: "b", h: 48 }
n24@{ icon: "mdi:cog", form: "rounded", label: "Upload chapter images to Drive", pos: "b", h: 48 }
n25@{ icon: "mdi:swap-vertical", form: "rounded", label: "Get output", pos: "b", h: 48 }
n26@{ icon: "mdi:cog", form: "rounded", label: "Create Drive folder", pos: "b", h: 48 }
n27["<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"]
n28["<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/>Merge1"]
n29@{ icon: "mdi:robot", form: "rounded", label: "Researcher", pos: "b", h: 48 }
n30@{ icon: "mdi:wrench", form: "rounded", label: "Research Tool", pos: "b", h: 48 }
n32@{ icon: "mdi:robot", form: "rounded", label: "Structured Output Parser1", pos: "b", h: 48 }
n33@{ icon: "mdi:wrench", form: "rounded", label: "Research Tool1", pos: "b", h: 48 }
n34@{ icon: "mdi:cog", form: "rounded", label: "Wait2", pos: "b", h: 48 }
n35["<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/>Wait featured image"]
n36@{ icon: "mdi:robot", form: "rounded", label: "Structured Output Parser3", pos: "b", h: 48 }
n37@{ icon: "mdi:robot", form: "rounded", label: "Structured Output Parser4", pos: "b", h: 48 }
n38@{ icon: "mdi:swap-vertical", form: "rounded", label: "Settings", pos: "b", h: 48 }
n39@{ icon: "mdi:robot", form: "rounded", label: "Initial Research", pos: "b", h: 48 }
n40@{ icon: "mdi:swap-vertical", form: "rounded", label: "Split out chapters", pos: "b", h: 48 }
n41@{ icon: "mdi:robot", form: "rounded", label: "Copywriter", pos: "b", h: 48 }
n42@{ icon: "mdi:cog", form: "rounded", label: "Limit internal links", pos: "b", h: 48 }
n43@{ icon: "mdi:swap-vertical", form: "rounded", label: "Loop Over Items2", pos: "b", h: 48 }
n44@{ icon: "mdi:swap-vertical", form: "rounded", label: "Get title chapter and content", pos: "b", h: 48 }
n45@{ icon: "mdi:swap-vertical", form: "rounded", label: "Final article in Markdown", pos: "b", h: 48 }
n46@{ icon: "mdi:swap-vertical", form: "rounded", label: "FInal article in HTML", 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/code.svg' width='40' height='40' /></div><br/>Combine into article"]
n48@{ icon: "mdi:cog", form: "rounded", label: "Aggregate internal links", pos: "b", h: 48 }
n49@{ icon: "mdi:play-circle", form: "rounded", label: "Google Sheets Trigger", pos: "b", h: 48 }
n51@{ icon: "mdi:robot", form: "rounded", label: "Blog Planner", pos: "b", h: 48 }
n52@{ icon: "mdi:brain", form: "rounded", label: "OpenAI Chat Model", pos: "b", h: 48 }
n53@{ icon: "mdi:brain", form: "rounded", label: "OpenAI Chat Model1", pos: "b", h: 48 }
n54@{ icon: "mdi:brain", form: "rounded", label: "OpenAI Chat Model2", pos: "b", h: 48 }
n55@{ icon: "mdi:brain", form: "rounded", label: "OpenAI Chat Model3", pos: "b", h: 48 }
n56@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Check empty output", pos: "b", h: 48 }
n57@{ icon: "mdi:cog", form: "rounded", label: "Limit to last post", pos: "b", h: 48 }
n1 --> n43
n19 --> n15
n34 --> n43
n28 --> n19
n27 --> n35
n38 --> n20
n41 --> n34
n22 --> n21
n25 --> n0
n25 --> n40
n29 --> n41
n18 --> n22
n51 --> n56
n20 --> n2
n20 --> n39
n3 --> n4
n6 --> n7
n30 -.-> n39
n33 -.-> n29
n15 --> n8
n15 --> n5
n4 --> n42
n2 --> n3
n39 --> n51
n43 --> n44
n43 --> n29
n9 --> n46
n52 -.-> n39
n10 --> n35
n21 --> n17
n56 --> n26
n56 --> n51
n57 --> n38
n53 -.-> n51
n54 -.-> n29
n55 -.-> n41
n40 --> n15
n40 --> n1
n26 --> n25
n35 --> n12
n47 --> n45
n42 --> n48
n46 --> n10
n49 --> n57
n11 --> n27
n7 --> n14
n12 --> n16
n5 --> n24
n5 --> n6
n14 --> n28
n0 --> n23
n0 --> n11
n48 --> n1
n45 --> n9
n32 -.-> n51
n36 -.-> n41
n37 -.-> n39
n13 --> n18
n44 --> n8
n8 --> n47
n24 --> n28
n23 --> n27
n16 --> n13
end
subgraph sg1["Execute Workflow Flow"]
direction LR
n58@{ icon: "mdi:play-circle", form: "rounded", label: "Execute Workflow Trigger", pos: "b", h: 48 }
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/httprequest.dark.svg' width='40' height='40' /></div><br/>PerplexityAI API"]
n60@{ icon: "mdi:swap-vertical", form: "rounded", label: "Get Research Content", pos: "b", h: 48 }
n61@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields1", pos: "b", h: 48 }
n61 --> n59
n59 --> n60
n58 --> n61
end
subgraph sg2["Schedule Flow"]
direction LR
n50@{ icon: "mdi:play-circle", form: "rounded", label: "Schedule Trigger", pos: "b", h: 48 }
end
subgraph sg3["When clicking ‘Test workflow’ Flow"]
direction LR
n31@{ icon: "mdi:play-circle", form: "rounded", label: "When clicking ‘Test workflow’", 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 n49,n58,n50,n31 trigger
class n0,n5,n29,n32,n36,n37,n39,n41,n51 ai
class n52,n53,n54,n55 aiModel
class n30,n33 ai
class n20,n56 decision
class n2,n7,n12,n13,n14,n16,n18,n59 api
class n47 code
class n19 disabled
class n34 disabled
class n58 disabled
class n59 disabled
class n60 disabled
class n61 disabled
class n50 disabled
class n31 disabled
classDef customIcon fill:none,stroke:none
class n1,n2,n7,n8,n9,n10,n12,n13,n14,n16,n18,n27,n28,n35,n47,n59 customIcon
The Problem: Publishing great posts still feels manual
You can have a solid topic and still lose half a day turning it into something publishable. First you chase “latest info” across tabs, then you write and rewrite the outline, then you hunt for images that won’t look generic. After that comes internal links (which means opening your own site, searching old posts, copying URLs), and finally WordPress formatting, featured images, and excerpts. The worst part is the mental context switching. You’re doing creative work, then admin work, then SEO work, then admin again.
None of these steps is hard. Together, they slow everything down and introduce little errors you only catch after the post is live.
- Research gets outdated fast, so you end up patching facts right before publishing.
- Internal linking is “quick” until you realize you need 10 to 20 links and consistent anchor text.
- Image sourcing steals momentum, and rushed visuals make the whole post feel cheap.
- If you don’t back up drafts and assets, you eventually lose something important (and it’s always at the worst time).
The Solution: A Google Sheets row becomes a WordPress post
This workflow starts with a simple input: a new row in Google Sheets (topic, target audience, style, word count, number of sections, and a few other knobs you can control). From there, it runs initial research to understand what’s current, then creates a structured plan for the article so the final post isn’t just a wall of text. Next, it loops through each planned section and performs deeper research on that specific subtopic, then writes the section using the research as grounding. It also generates a featured “hero” image plus a unique image for each section, uploads those images, and inserts them into the content. Finally, it pulls internal links from your own site (via sitemap), places them throughout the post, publishes to WordPress (or saves a draft), and backs up everything to Google Drive in a folder named after the post.
The flow begins when Google Sheets triggers on a new row (or a schedule trigger if you prefer). Research and planning happen first, then writing and image generation run in controlled loops with wait steps to avoid rate limits. The output is a formatted WordPress post plus a Drive backup of the article text and all images.
What You Get: Automation vs. Results
| What This Workflow Automates | Results You’ll Get |
|---|---|
|
|
Example: What This Looks Like
Say you publish 3 posts a week. Manually, a “publish-ready” pass often takes about 2 hours per post (research refresh, internal links, images, WordPress formatting, and creating a backup), so you’re spending roughly 6 hours a week on the non-writing parts. With this workflow, you add one row to Google Sheets in a minute or two, then let it run while you do other work. Even if the automation takes about 45 minutes to process in the background, your hands-on time drops to a quick review and final tweaks.
What You’ll Need
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- Google Sheets to trigger new post requests.
- WordPress to publish posts and upload media.
- OpenAI API key (get it from your OpenAI dashboard)
Skill level: Intermediate. You’ll connect accounts, paste API keys, and test with a few cheap runs before going “hands-off.”
Don’t want to set this up yourself? Talk to an automation expert (free 15-minute consultation).
How It Works
A new row appears in Google Sheets. That row contains your topic and the controls (audience, style, length, number of sections, draft vs publish). The workflow checks the inputs so it doesn’t run on blanks.
It pulls internal links from your site. n8n fetches your WordPress sitemap, parses the XML, and builds a pool of URLs. It limits the list (20 by default) so the post doesn’t look spammy.
Research and writing run in loops. An initial research agent and planning model create the article structure, then each section goes through deeper research and a writing pass. Wait nodes are used to prevent “too many requests” problems when APIs slow down.
Images, formatting, publishing, and backup happen at the end. The workflow generates a hero image and section images, resizes them, uploads them to WordPress, assigns featured media, and sets the excerpt. It also writes the final text to Google Docs and stores all assets in Google Drive in a dedicated folder.
You can easily modify the trigger (Sheets row vs scheduled run) to match your editorial rhythm. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Trigger Type
This workflow can be started manually, on a schedule, or when a Google Sheets row updates.
- Enable the trigger you want to use: Sheets Row Trigger, Scheduled Start Trigger, or Manual Test Trigger.
- If using Sheets Row Trigger, open the node and connect your spreadsheet settings for the row updates that should start the workflow.
- If using Scheduled Start Trigger, set your preferred schedule and ensure the node is enabled.
- Keep Manual Test Trigger enabled only for manual testing runs.
Credential Required: Connect your Google Sheets credentials in Sheets Row Trigger.
Step 2: Connect Google Workspace Storage
Drive and Docs are used to store generated assets and text outputs.
- Open Create Drive Folder and connect your Drive account.
- Connect Google Drive credentials in Send Hero Image to Drive and Send Section Images to Drive.
- Connect Google Docs credentials in Generate Doc File and Store Texts in Doc.
Credential Required: Connect your Google Drive credentials in Create Drive Folder, Send Hero Image to Drive, and Send Section Images to Drive.
Credential Required: Connect your Google Docs credentials in Generate Doc File and Store Texts in Doc.
Step 3: Set Up AI Research and Planning
These nodes create the blog plan and research foundation for the article.
- Open Initial Research Agent, Deep Research Agent, Blog Plan Generator, and Writing Agent to confirm their prompts and input fields.
- Ensure Primary Chat Model, Planner Chat Model, Research Chat Model, and Writer Chat Model are configured with your preferred OpenAI models.
- Confirm the parser and tools are attached: Structured Parser A, Structured Parser B, and Structured Parser C output to their parent nodes, while Research Utility and Research Utility B attach as tools.
Credential Required: Connect your OpenAI credentials in Primary Chat Model, Planner Chat Model, Research Chat Model, Writer Chat Model, Create Hero Image, and Create Section Image.
⚠️ Common Pitfall: Structured Parser A, Structured Parser B, Structured Parser C, Research Utility, and Research Utility B are AI sub-nodes; add credentials to their parent nodes (e.g., Initial Research Agent or Deep Research Agent), not to the sub-nodes themselves.
Step 4: Configure Research Inputs and Internal Links
This section pulls recent posts and internal links to improve topical alignment.
- Review Limit Recent Post and Configure Defaults to ensure only the latest topic is processed.
- Set the sitemap URL and request settings in Fetch Post Sitemap, then ensure Parse XML File and Extract Link List parse the response correctly.
- Confirm internal link curation with Limit Internal Links and aggregation in Aggregate Link Pool.
Credential Required: If your sitemap endpoint or APIs require authentication, add credentials to Fetch Post Sitemap and any other HTTP-based nodes used for access.
Step 5: Assemble and Write the Article
This stage assembles sections, writes content, and compiles the full article.
- Ensure Split Section Items routes to both Iterate Section Items and Combine Streams in parallel as designed.
- Verify the section assembly flow: Iterate Topic Items → Assemble Section Details → Join Section Title & Text → Compile Full Article.
- Confirm formatting nodes: Finalize Markdown Article → Convert Markdown to HTML → Finalize HTML Article.
Tip: Prepare Output Data outputs to both Create Hero Image and Split Section Items in parallel, so ensure any required fields are ready for both branches.
Step 6: Generate and Process Images
This portion creates hero and section images, scales them, and uploads them.
- Confirm Create Section Image outputs to both Send Section Images to Drive and Scale Section Image in parallel.
- Verify the hero image branch: Create Hero Image outputs to both Send Hero Image to Drive and Scale Hero Image in parallel.
- Check that Upload Section Images and Upload Hero Image send the files to your WordPress media endpoints, then refresh metadata via Refresh Image Metadata and Refresh Hero Metadata.
Credential Required: Add authentication headers or credentials in Upload Section Images, Upload Hero Image, Assign Hero Image, Set Post Excerpt, and Refresh Image Metadata as required by your WordPress installation.
Step 7: Configure WordPress Publishing
This stage publishes the final article and assigns the hero image.
- Open Publish to WordPress and set the post creation fields for title, content, and status.
- Ensure Hold for Hero Image waits for media, then check Assign Hero Image and Set Post Excerpt update the new post.
- Confirm the document handoff: Generate Doc File → Store Texts in Doc → Map Output Fields.
Credential Required: Connect your WordPress credentials in Publish to WordPress.
Step 8: Test and Activate Your Workflow
Run a full test to verify outputs and then activate the workflow.
- Click Execute Workflow from Manual Test Trigger to run a full test.
- Confirm a successful run creates a WordPress draft/published post, uploads media, and stores Google Docs outputs.
- If using automated starts, enable Sheets Row Trigger or Scheduled Start Trigger and save the workflow as active.
Common Gotchas
- WordPress credentials can expire or need specific permissions. If things break, check your WordPress application password and user role settings 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.
- Default prompts in AI nodes are generic. Add your brand voice early or you’ll be editing outputs forever.
Frequently Asked Questions
About 45 minutes if you already have your accounts and API keys.
No. You’ll mostly connect accounts and paste API keys. The rest is testing and small copy changes.
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 OpenAI and Perplexity-style research API usage, which is usually a few dollars during testing and more when you scale.
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 it’s a common tweak. You’ll change the behavior in the WordPress publishing step (the “Publish to WordPress” part) so it creates a draft instead of publishing immediately. Other popular changes include lowering the internal link limit, adjusting the number of sections, and swapping the image model if you don’t like the default style.
Usually it’s an invalid or expired application password, or the WordPress user doesn’t have permission to upload media and publish posts. Double-check the credentials stored in n8n, then confirm your site isn’t blocking REST API requests with a security plugin. If failures happen only on bigger runs, rate limits and timeouts can also be the culprit, especially during image upload.
A lot, but it depends on your hosting and your API budgets.
For this specific use case, n8n is usually the better fit because the workflow isn’t just “move data from A to B.” You have loops inside loops (sections, images, research), branching checks, and structured validation so the output doesn’t break halfway through. Zapier and Make can do parts of this, but multi-step AI pipelines get expensive fast and debugging is frankly more painful when you can’t see the whole flow clearly. n8n also gives you the option to self-host, which means you can run larger volumes without paying per task. If you only need a lightweight “Sheet row to WordPress draft” with no research, no images, and no internal linking, Zapier can still be fine. Talk to an automation expert if you want help choosing.
Once this is running, publishing stops being a weekly scramble and becomes a quiet background process. You’ll still steer the strategy, but the workflow handles the repetitive parts so you can actually ship content consistently.
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.