ChatGPTCreativeWritingAI score · 73/100AI-assisted edit · no obvious prompt-injection riskn8n.io

n8n Automated SEO Blog Publishing: Google Sheets to WordPress

Input Google Sheets row → AI research & planning → generate inline images → write HTML article → publish to WordPress with featured image

Some experienceStepsWorkflowPromptTip
Who
Content creators, agencies, or business operators who need to publish SEO-optimized blog posts at scale
You get
Automatically publish complete HTML articles with embedded images to WordPress, plus a featured header image
You need
n8n · perplexity · google-sheets · wordpress · cloudinary

Constraints

Requires an n8n instance, WordPress REST API credentials, OpenAI API key, Perplexity API key, Google Sheets OAuth2 access, and a Cloudinary unsigned upload preset. Optional Pexels API key for stock header images. The workflow triggers on a schedule and processes one unpublished row per run.

What they did

Template author lukaszb built a 43-node n8n automation that reads unpublished blog topics from Google Sheets, uses an AI Agent with Perplexity research to generate a content plan, batch-generates inline images uploaded to Cloudinary, writes semantic HTML articles, and publishes to WordPress with a featured header image.

How it went

The author claims the system can 'publish professional articles in minutes' with end-to-end automation, SEO and RAO optimization, and enhanced reader engagement through inline images. These claims are author-reported and unverified by this site.

Worth knowing

The workflow contains spelling inconsistencies in node names and field keys (e.g., 'Article wrtiter', 'descritption_image', 'wordpres website url') that must be matched exactly. The Pexels stock header path is disabled by default; the AI header path uses gpt-image-1 at 1536x1024. The Structured Output Parser node has autoFix enabled to harden JSON output. The OpenAI Chat Model4 node shows gpt-5-mini in parameters, but availability must be confirmed by the user. This site has not executed the workflow; reproduction status is not_tested.

n8n workflow template

Structure checked · Not run-tested

Use “Import from File” in n8n, or copy the JSON and paste it into the editor. Connect your own accounts, then try test data. The template is inactive by default.

Setup and test checklist

Credentials to connect

  • OpenAI Chat Model node: connect OpenAI API credentials.
  • OpenAI Chat Model4 node: connect OpenAI API credentials.
  • Generate an image1 node: connect Google Gemini/PaLM API credentials.
  • OpenAI Chat Model1 node: connect OpenAI API credentials.
  • Message a model in Perplexity node: connect Perplexity API credentials.
  • Get data databse node: connect Google Sheets OAuth2 credentials.
  • Set Image on Wordpress Post1 node: connect wordpressApi credentials.
  • WordPress excerpt add1 node: connect wordpressApi credentials.
  • WordPress excerpt add1 node: connect HTTP Header Auth credentials.
  • OpenAI 4.1 mini4 node: connect OpenAI API credentials.
  • Append or update row in sheet node: connect Google Sheets OAuth2 credentials.
  • Create a post node: connect wordpressApi credentials.
  • upload image to wordpress node: connect wordpressApi credentials.
  • Get Image from Pexels node: connect HTTP Header Auth credentials.
  • OpenAI 4.1 mini5 node: connect OpenAI API credentials.
  • Generate an image node: connect OpenAI API credentials.
  • Set Image on Wordpress Post2 node: connect wordpressApi credentials.
  • upload image to wordpress1 node: connect wordpressApi credentials.
  • Append or update row in sheet1 node: connect Google Sheets OAuth2 credentials.
  • Generate an image2 node: connect OpenAI API credentials.
  • Generate an image3 node: connect Google Gemini/PaLM API credentials.

Configuration to replace

  • Source template is n8n public workflow #7965 (~43 nodes). Keep inactive after import; verify triggers, expressions and external API endpoints.
  • Sticky-note guidance is informational; replace placeholders with your own accounts, sheet schemas or channel IDs.

Test input and expected output

  • Manually run the main path once in a test workspace and confirm credentialed nodes authenticate without errors.
  • Drive one synthetic/redacted sample through and check output fields and downstream writes before enabling in production.

Template changes

  • Author credential bindings, webhookId and execution data are removed; the workflow is inactive. Nodes, connections and original prompts are preserved. Not run-tested in n8n.
  • No business-logic edits; verify keys, quotas and privacy compliance before use.

Template retrieved: 2026-10-24

Steps

  1. Setup inputs and trigger

    Configure a Schedule Trigger to run at intervals. Add a Google Sheets node to read rows where `created` is empty from your sheet (e.g., Arkusz1), use a Limit node to process one row at a time, and a Set node to store working variables: blog title and description from the sheet row, plus static config like Cloudinary cloud name, brand brief (b/c_information), and WordPress base URL. Keep credentials centralized here to avoid hard-coding.

  2. AI content planning and research

    The Content planer (Agent node) receives the title, description, and brand brief. It calls the Perplexity tool for research, checks Google Sheets history to avoid duplicate topics, and outputs a strict JSON plan with title, slug, meta, excerpt, description, image_prompts, and sources. A Structured Output Parser enforces this schema with autoFix enabled.

    Execution prompt · Source text。Content planer node user prompt field

    =Blog article title: {{ $json.blog_title }}
    Short descritpion: {{ $json.blog_s_descritpion }}
    
    Company/brand information: {{ $json['b/c_information'] }}

    Execution prompt · Source text。Content planer node systemMessage field

    =You are an AI Content Strategist specializing in creating unique, SEO-optimized, and RAO-friendly long-form blog content ideas.
    
    Your workflow is as follows:
    
    Read the brand brief provided in the user prompt and follow it strictly.
    
    Check history: Use the google_sheet tool to retrieve all previously generated topics and avoid duplication.
    
    Research: Use the perplexity tool to gather additional supporting information, statistics, and reputable sources. Include 2–3 source links in the final outline where relevant.
    
    Create a complete content plan for a blog article that is:
    
    Unique, evergreen, and aligned with the brand strategy.
    
    Valuable for both SEO and RAO (AI-driven search).
    
    Well-structured and highly detailed, showing what should be written in each section.
    
    Output format: Return only a single JSON object with the following fields:
    
    {
      "title": "Clear, keyword-rich title (max. 60 chars)",
      "slug": "url-friendly-lowercase-hyphenated",
      "meta": "Concise meta description (max. 160 chars, includes keywords)",
      "keywords": ["keyword1", "keyword2", "keyword3", "keyword4", "keyword5"],
      "excerpt": "1–2 sentence factual and engaging summary",
      "description ": "full description about blog, with all necessary information, and link to source"
      ],
      "image_prompts": [
        "Prompt for first relevant image (describe scene, style, purpose)",
        "Prompt for second relevant image (describe scene, style, purpose)"
      ],
      "sources": [
        "https://source-link-1.com",
        "https://source-link-2.com"
      ]
    }
    
    
    
    Rules:
    
    Never write the full article text. Only provide the plan and structure.
    
    Sources must be real, credible, and derived from Perplexity.
    
    Image prompts must describe visuals that add value inside the article (not generic).
    
    Always ensure topic originality vs. history from Google Sheets.
    
    Maintain factual, professional, and SEO-focused tone.
  3. Generate inline images and upload

    Split Out breaks the image_prompts array into items. Loop Over Items processes each: Generate an image2 (OpenAI Image, gpt-image-1) creates the image, then an HTTP Request uploads it to Cloudinary (URL: `https://api.cloudinary.com/v1_1/{{ cloudinary account name }}/image/upload`, preset: `unsigned_upload`). Set Output Image stores the returned image_url and original prompt. Aggregate collects all into an images array for the writer. The Gemini path (Generate an image1) is disabled by default.

    Execution prompt · Source text。Generate an image2 node prompt field

    =generate a image {{ $json['output.image_prompts'] }}
  4. Write HTML article body

    The Article wrtiter (Chain node) receives plan fields, brand brief, and the images array, outputting raw HTML (not JSON or Markdown). The system prompt enforces semantic HTML5, lazy-loaded images, no h1, optional table of contents, pull quotes, TL;DR, and a CTA footer.

    Execution prompt · Source text。Article wrtiter node text field (user prompt)

    =Create me a full ready conetnt  to article in my blog .
    
    Title of article: {{ $('Content planer').item.json.output.title }}
    Description: {{ $('Content planer').item.json.output['description '] }};
    Optional sources: {{ $('Content planer').item.json.output.sources }}.
    
    Avalible images urls to add betwen text:
    Image 1:
    -url: {{ $json.images[0].image_url }}
    -description:{{ $json.images[0].descritption_image }}
    Image 2:
    -url:{{ $json.images[1].image_url }}
    -description: {{ $json.images[1].descritption_image }}
    
    Company/brand information where and for who you writnig too:
    {{ $('Set input data/credintenials').item.json['b/c_information'] }}
    
    Give me the html as a raw multiline text. Do not format it as JSON, do not escape newlines.

    Execution prompt · Source text。Article wrtiter node messages.messageValues[0].message field (system prompt)

    =You are a Long-Form Blog Writer. Produce a complete, publication-ready HTML article body using the brand brief, the approved content plan (outline), and the provided images.
    
    Hard rules (STRICT):
    
    Output only HTML. No JSON, no Markdown, no comments, no extra prose.
    
    Do not include title, slug, excerpt, meta, or any front matter.
    
    Follow the plan_json.outline for structure and coverage.
    
    Respect the brand tone from brand_brief. Be precise, actionable, and factual.
    
    Target word count within ±10% of target_word_count.
    
    HTML requirements:
    
    Use semantic HTML5 only: <article>, <section>, <h2>–<h3>, <p>, <ul>, <ol>, <blockquote>, <figure>, <img>, <figcaption>, <nav>, <aside>, <footer>.
    
    No <h1> (title is handled elsewhere). Start main sections with <h2>.
    
    Optional Table of Contents as <nav> with anchor links to sections in the outline.
    
    Insert images as <figure> elements:
    
    Use loading="lazy" for all images.
    
    Provide descriptive alt text (keyword-aware, no stuffing).
    
    If an image has place_after_section_id, insert it immediately after that section; otherwise choose the most relevant place.
    
    Include 1–2 short pull quotes via <blockquote>.
    
    Add a concise TL;DR in an <aside> near the top (no title/excerpt duplication).
    
    End with a short actionable conclusion and, if appropriate, a brand-aligned CTA inside <footer>.
    
    Factuality & SEO/RAO:
    
    Use definitions and scannable sentences that AI systems can extract.
    
    If the outline references sources, link them with <a href="..."> (no bibliography header).
    
    Failure conditions:
    
    If required inputs are missing, produce an empty <article></article> (no explanations).
  5. Publish to WordPress

    The Create a post node uses WordPress credentials to publish: title and slug from the plan output, content from the writer's HTML text, status set to publish. Then WordPress excerpt add1 (HTTP Request) updates the post excerpt with the planned excerpt.

  6. Generate header image and mark complete

    The AI header image path is active by default: Write query too image AI generator converts title and excerpt into a 20-40 word image prompt, Generate an image (OpenAI, gpt-image-1, 1536x1024) creates the image, upload image to wordpress1 uploads it as media, and Set Image on Wordpress Post2 binds featured_media to the post. Finally, Append or update row in sheet1 sets `created` to True in Google Sheets. An optional Pexels stock path is disabled by default: Write query too pexels extracts 1-3 visual nouns, searches and downloads an image, then uploads. Only one path should be enabled to avoid conflicts.

    Execution prompt · Source text。Write query too image AI generator node text field

    =Title: {{ $('Content planer').item.json.output.title }}
    Description:{{ $json.excerpt.raw }}
    
    Convert the above title into the single best promopt to AI image genrator like midjourney or Leonardo AI

    Execution prompt · Source text。Write query too image AI generator node messages.messageValues[0].message field (system prompt)

    =You are an expert prompt engineer specialized in creating header images for blog articles.
    Your ONLY task is to transform a blog article’s title and excerpt into the best possible image generation prompt.
    
    Rules:
    
    The image must serve as a header illustration for a blog article.
    
    Always use concrete visual nouns and scenes that can be illustrated.
    
    Focus on places, objects, actions, or people that match the article’s theme.
    
    Add descriptive context:
    
    Mood (professional, minimalist, cinematic, modern, vintage, futuristic, etc.)
    
    Style (digital art, illustration, flat design, cinematic photo, infographic, etc.)
    
    Setting or environment (city, office, nature, abstract background, etc.)
    
    Keep prompts between 20–40 words.
    
    Always in English.
    
    Output format:
    
    Return only one final image prompt in plain text.
    
    Do not add explanations, quotes, markdown, or JSON.
    
    Fallback:
    
    If the content is abstract, create a conceptual illustration prompt (e.g. "abstract geometric shapes, futuristic digital art, minimal composition").

    Execution prompt · Source text。Write query too pexels node text field (Pexels path, disabled by default)

    =Title: {{ $('Content planer').item.json.output.title }}
    Description:{{ $json.excerpt.raw }}
    
    Convert the above title into the single best Pexels keyword phrase following every instruction in the system prompt.  
    Return ONLY the keyword phrase.

    Execution prompt · Source text。Write query too pexels node messages.messageValues[0].message field (system prompt, Pexels path, disabled by default)

    =You are an expert prompt‑engine and image curator.  
    Your ONLY task is to reduce a single blog‑post titleto the **best possible Pexels keyword phrase**.  
    Follow these rules exactly:
    
    1.Choose 1‑3 concrete visual nouns** that can actually appear in a photo (e.g. [EXAMPLES OF KEYWORDS LIKE "LONDON", "ROBOT","NATURE"]). Remove abstract terms like ‘outlook’, ‘sentiment’, ‘future’.
    
    2.Keep it SHORT: 
       • Maximum 3 words total.  
       • Prefer single‑ or double‑word phrases when possible.  
       • No adjectives such as ‘beautiful’, ‘cool’, ‘nice’.
    
    3. English only
    
    4.Output format 
       • Return **only** the keyword phrase, in plain text, no quotes, no commas, no additional words.  
       
    5. Fallback
       • If the title is too abstract, return one of:  
         [SAFE QUERRY SEARCH]
    
    Never add orientation, size, JSON, markdown, or explanations.  
    Return exactly one line containing only the keywords.

Prompt you can copy

Setup guidance · Editorial suggestion。Setup assistant; confirm inputs and permissions before building

This block is the prompt. Ads are never placed here.

You are an n8n workflow setup assistant. The user wants to replicate a template that auto-publishes SEO blog posts from Google Sheets to WordPress. First confirm they have: WordPress REST API credentials, OpenAI API key, Perplexity API key, Google Sheets OAuth2 access, and a Cloudinary unsigned upload preset named 'unsigned_upload'. Then guide them through importing the workflow JSON, configuring credentials, filling the Set node variables, and remind them to enable only ONE header image path (AI or Pexels).

Requires n8n instance and multiple API keys; first run should be manual to verify

Source

Automated SEO blog publishing with WordPress, OpenAI & Perplexity · lukaszb · n8n.io · 2025-08-27

Comments & feedback

Tried this method? Share results, problems or improvements. Comments appear after moderation. Please avoid sensitive information.

Loading…

    Related