AutomationFlowsAI & RAG › Automate SEO Blog Creation From Trends Using Gemini Ai, Apify, and Google Docs

Automate SEO Blog Creation From Trends Using Gemini Ai, Apify, and Google Docs

ByParth Pansuriya @parthpansuriya on n8n.io

For content creators, SEO specialists, and digital marketers who want to automatically generate SEO-optimized blog posts from trending topics — no manual writing or formatting required.

Cron / scheduled trigger★★★★☆ complexityAI-powered23 nodesHTTP RequestAgentGoogle Gemini ChatOutput Parser Structured
AI & RAG Trigger: Cron / scheduled Nodes: 23 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #10754 — we link there as the canonical source.

This workflow follows the Agent → HTTP Request 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 →

Download .json
{
  "id": "ex6EtLx0qHHlJlbD",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Blog With Image",
  "tags": [],
  "nodes": [
    {
      "id": "b32cc401-8586-4d52-add3-aa563f3997da",
      "name": "Daily Trigger 8AM",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -80,
        -16
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 8
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "30348d27-0cf9-49ed-afd4-ad23bf939693",
      "name": "Fetch Google Trends",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        128,
        -16
      ],
      "parameters": {
        "url": "https://api.apify.com/v2/acts/data_xplorer~google-trends-fast-scraper/run-sync-get-dataset-items?token=<YOUR-TOKEN>>",
        "method": "POST",
        "options": {},
        "jsonBody": "{\n    \"enableTrendingSearches\": true,\n    \"fetchRegionalData\": false,\n    \"proxyConfiguration\": {\n        \"useApifyProxy\": true\n    },\n    \"trendingSearchesCountry\": \"IN\",\n    \"trendingSearchesTimeframe\": \"24\"\n}",
        "sendBody": true,
        "specifyBody": "json"
      },
      "typeVersion": 4.3
    },
    {
      "id": "858f2dbe-4cc1-414d-ac4c-49215c0896aa",
      "name": "Generate SEO Blog Content",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        368,
        -16
      ],
      "parameters": {
        "text": "=Trending topics\n\n{{ $json.trending_searches[0].term }}\n  - {{ $json.trending_searches[0].trend_volume }}\n  - {{ $json.trending_searches[0].related_terms }}",
        "options": {
          "systemMessage": "=You are an expert SEO content writer who writes high-performing blog articles for Google Search and social media. \nYour job is to generate a fully SEO-optimized blog post based on the user\u2019s topic or keywords.\n\nRequirements:\n1. Create an engaging, keyword-rich **blog title** (under 70 characters).\n2. Generate **long-form blog content** (600\u20131200 words) that is:\n   - Fully SEO optimized with natural keyword placement.\n   - Structured with **headings (H2, H3)**, short paragraphs, and lists where helpful.\n   - Written in a human, engaging, and informative tone.\n3. Include a **meta description (under 160 characters)** optimized for CTR.\n4. Avoid repetition, AI-like phrases, or keyword stuffing.\n5. Add **relevant subheadings** and **call-to-action** at the end.\n6. Use current SEO best practices and trending search intent.\n\n"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 3
    },
    {
      "id": "37ee318d-d507-426d-90b5-8b056a306f6f",
      "name": "Refine Content with Gemini AI",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        368,
        144
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "b5fde2a5-0077-41b6-8ca5-8a3347cce73c",
      "name": "Parse Blog Output",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        528,
        144
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"title\": \"SEO blog title here\",\n  \"meta_description\": \"Short SEO description here\",\n  \"content\": \"Full SEO optimized blog article here\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "c587ccea-4079-4cec-a167-45135257cdaf",
      "name": "Format output for Google Docs",
      "type": "n8n-nodes-base.code",
      "position": [
        736,
        -16
      ],
      "parameters": {
        "jsCode": "const input = $input.first().json;\nconst output = input.output || {};\nconst markdown = (output.content || '').trim();\nconst title = output.title || '';\nconst resultUrls = input.resultUrls || [];\n\nconst requests = [];\nlet cursor = 1;\n\n// Step 1: Insert image\nif (Array.isArray(resultUrls) && resultUrls.length > 0) {\n  const imageUrl = resultUrls[0];\n  requests.push({\n    insertInlineImage: {\n      location: { index: cursor },\n      uri: imageUrl,\n      objectSize: { height: { magnitude: 200, unit: 'PT' } }\n    }\n  });\n  cursor += 1; // move past image\n  requests.push({\n    insertText: {\n      location: { index: cursor },\n      text: '\\n\\n'\n    }\n  });\n  cursor += 2;\n}\n\n// Step 2: Insert Title\nif (title) {\n  const titleText = title + '\\n\\n';\n  requests.push({\n    insertText: { location: { index: cursor }, text: titleText }\n  });\n  requests.push({\n    updateParagraphStyle: {\n      range: { startIndex: cursor, endIndex: cursor + title.length },\n      paragraphStyle: { namedStyleType: 'HEADING_1' },\n      fields: 'namedStyleType'\n    }\n  });\n  cursor += titleText.length;\n}\n\n// Step 3: Remove duplicate markdown title\nconst markdownContent = markdown.replace(/^#.*\\n/, '').trim();\n\n// Step 4: Insert all markdown safely\nconst lines = markdownContent.split('\\n');\nfor (const line of lines) {\n  const trimmed = line.trim();\n  if (!trimmed) {\n    requests.push({\n      insertText: { location: { index: cursor }, text: '\\n' }\n    });\n    cursor += 1;\n    continue;\n  }\n\n  // Headings\n  const headingMatch = trimmed.match(/^(#{1,3})\\s*(.*)/);\n  if (headingMatch) {\n    const hashes = headingMatch[1].length;\n    const headingText = headingMatch[2].trim() + '\\n\\n';\n    let styleType = 'NORMAL_TEXT';\n    if (hashes === 1) styleType = 'HEADING_2';\n    if (hashes === 2) styleType = 'HEADING_3';\n    if (hashes === 3) styleType = 'HEADING_4';\n\n    requests.push({ insertText: { location: { index: cursor }, text: headingText } });\n    requests.push({\n      updateParagraphStyle: {\n        range: { startIndex: cursor, endIndex: cursor + headingText.length - 2 },\n        paragraphStyle: { namedStyleType: styleType },\n        fields: 'namedStyleType'\n      }\n    });\n    cursor += headingText.length;\n    continue;\n  }\n\n  // Normal paragraph (remove bold markers)\n  const paragraph = trimmed.replace(/[*_]{2}/g, '') + '\\n\\n';\n  requests.push({ insertText: { location: { index: cursor }, text: paragraph } });\n  cursor += paragraph.length;\n}\n\n// Step 5: Return requests\nreturn [{ json: { requests } }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "8e804594-07bc-4e4d-908e-6412367548b0",
      "name": "Update Google Doc",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        976,
        -16
      ],
      "parameters": {
        "url": "=https://docs.googleapis.com/v1/documents/1xxCxjQ73GCtsJyn2u86dZsEId18Uha82OxvaIOjhZf0:batchUpdate",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "authentication": "predefinedCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "requests",
              "value": "={{ $json.requests }}"
            }
          ]
        },
        "nodeCredentialType": "googleDocsOAuth2Api"
      },
      "credentials": {
        "googleDocsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "8ea9d0c0-e219-40a5-a5f3-28cf7b70e94d",
      "name": "Generate Blog Image",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        832,
        400
      ],
      "parameters": {
        "url": "https://api.kie.ai/api/v1/jobs/createTask",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"model\": \"google/nano-banana\",\n  \"input\": {\n    \"prompt\": \"{{ $json.output.title }}\",\n    \"output_format\": \"png\",\n    \"image_size\": \"16:9\"\n  }\n} ",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer <YOUR-API-TOKEN>"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "a73a2817-5d92-4b70-a1de-6894b879a983",
      "name": "Check Image Generation Status",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1072,
        400
      ],
      "parameters": {
        "url": "https://api.kie.ai/api/v1/jobs/recordInfo",
        "options": {},
        "sendQuery": true,
        "sendHeaders": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "taskId",
              "value": "={{ $json.data.taskId }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer <YOUR-API-TOKEN>"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "bda4084e-c7a6-4bad-9da6-ce3f11548e5d",
      "name": "Is Image Ready?",
      "type": "n8n-nodes-base.if",
      "position": [
        1312,
        400
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "0c96f9ae-4956-4698-86b1-76b1b067c2e1",
              "operator": {
                "type": "string",
                "operation": "empty",
                "singleValue": true
              },
              "leftValue": "={{ $json.data.resultJson }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "191b9b4d-a124-41c0-84fb-4855cc9d10fc",
      "name": "Prepare Image URL for Insert",
      "type": "n8n-nodes-base.set",
      "position": [
        1552,
        608
      ],
      "parameters": {
        "mode": "raw",
        "options": {},
        "jsonOutput": "={{ $json.data.resultJson }}"
      },
      "typeVersion": 3.4
    },
    {
      "id": "08dc0f9e-abee-422f-8d22-3b78a39dd751",
      "name": "Download Image",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1760,
        608
      ],
      "parameters": {
        "url": "={{ $json.resultUrls[0] }}",
        "options": {}
      },
      "typeVersion": 4.3
    },
    {
      "id": "8eb3c2fd-7cef-4b39-a91c-f21430da15b0",
      "name": "Wait 5 Second Before Recheck",
      "type": "n8n-nodes-base.wait",
      "position": [
        1536,
        384
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "6ea6df37-6bb3-4978-865c-a68f3180b5bb",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        64,
        -192
      ],
      "parameters": {
        "width": 224,
        "height": 352,
        "content": "## \ud83d\ude80 Fetch Google Trends\n\nFetches India\u2019s top trending searches in the last 24h via Apify API"
      },
      "typeVersion": 1
    },
    {
      "id": "6c4c9e3b-00cc-4380-a0eb-5ad355c57e49",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        320,
        -224
      ],
      "parameters": {
        "color": 3,
        "width": 320,
        "height": 528,
        "content": "## \ud83d\udcdd Generate SEO Blog Content\n\nGenerates a fully SEO-optimized, human-like blog post from trending topics; includes title, meta description, and structured content."
      },
      "typeVersion": 1
    },
    {
      "id": "1e070641-8454-4cce-8bea-0d1769798939",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        672,
        -256
      ],
      "parameters": {
        "width": 224,
        "height": 400,
        "content": "## \ud83d\udcc4 Format Output for Google Docs\n\nConverts AI-generated blog content and images into Google Docs requests with proper headings and formatting."
      },
      "typeVersion": 1
    },
    {
      "id": "af6debd0-aa3f-40bb-9f2d-464f8ddd4400",
      "name": "Sticky Note - Update Google Doc",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        928,
        -224
      ],
      "parameters": {
        "color": 4,
        "width": 188,
        "height": 364,
        "content": "## \ud83d\udcdd Update Google Doc\n\nSends formatted blog content and images to Google Docs using batchUpdate API."
      },
      "typeVersion": 1
    },
    {
      "id": "d6c1df3a-ae0a-4db5-8adc-c0c18874ea98",
      "name": "Sticky Note - Generate Blog Image",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        784,
        176
      ],
      "parameters": {
        "color": 2,
        "width": 182,
        "height": 380,
        "content": "## \ud83d\uddbc\ufe0f Generate Blog Image\n\nCreates a blog post image using KIE AI based on the blog title in 16:9 PNG format."
      },
      "typeVersion": 1
    },
    {
      "id": "2393576a-24e6-4c36-a267-671f8aae18af",
      "name": "Sticky Note - Check Image Status",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1008,
        176
      ],
      "parameters": {
        "color": 4,
        "width": 220,
        "height": 396,
        "content": "## \u23f3 Check Image Generation Status\n\nPolls KIE AI to see if the blog image task is complete before downloading."
      },
      "typeVersion": 1
    },
    {
      "id": "67a52914-8394-4261-802f-bc1a564fbae1",
      "name": "Sticky Note - Is Image Ready?",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1264,
        192
      ],
      "parameters": {
        "color": 5,
        "width": 188,
        "height": 348,
        "content": "## \u2705 Is Image Ready?\n\nChecks if the generated blog image is complete; routes workflow based on readiness."
      },
      "typeVersion": 1
    },
    {
      "id": "e66abb7d-1659-41ac-a8f0-49b86b7576fa",
      "name": "Sticky Note - Wait 5 Seconds",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1488,
        176
      ],
      "parameters": {
        "color": 6,
        "width": 204,
        "height": 364,
        "content": "## \u23f1\ufe0f Wait 5 Seconds Before Recheck\n\nPauses workflow briefly before checking the blog image status again."
      },
      "typeVersion": 1
    },
    {
      "id": "e35d114c-98f8-4967-a2f1-ef62901d521e",
      "name": "Sticky Note - Prepare Image URL",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1232,
        592
      ],
      "parameters": {
        "color": 3,
        "width": 300,
        "height": 172,
        "content": "## \ud83d\udd17 Prepare Image URL for Insert\n\nExtracts the generated blog image URL to use in the Google Docs insertion step."
      },
      "typeVersion": 1
    },
    {
      "id": "1547eb6c-4b1d-4a99-a05d-7bd513f82d72",
      "name": "Sticky Note - Download Image",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1904,
        592
      ],
      "parameters": {
        "color": 4,
        "width": 300,
        "height": 140,
        "content": "## \u2b07\ufe0f Download Image\n\nDownloads the generated blog image from the URL for insertion into Google Docs."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "db809ba2-f0e9-4946-be50-9a55429a133e",
  "connections": {
    "Download Image": {
      "main": [
        [
          {
            "node": "Format output for Google Docs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Image Ready?": {
      "main": [
        [
          {
            "node": "Wait 5 Second Before Recheck",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Prepare Image URL for Insert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Daily Trigger 8AM": {
      "main": [
        [
          {
            "node": "Fetch Google Trends",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Blog Output": {
      "ai_outputParser": [
        [
          {
            "node": "Generate SEO Blog Content",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Google Trends": {
      "main": [
        [
          {
            "node": "Generate SEO Blog Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Blog Image": {
      "main": [
        [
          {
            "node": "Check Image Generation Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate SEO Blog Content": {
      "main": [
        [
          {
            "node": "Format output for Google Docs",
            "type": "main",
            "index": 0
          },
          {
            "node": "Generate Blog Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Image URL for Insert": {
      "main": [
        [
          {
            "node": "Download Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 5 Second Before Recheck": {
      "main": [
        [
          {
            "node": "Check Image Generation Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Image Generation Status": {
      "main": [
        [
          {
            "node": "Is Image Ready?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format output for Google Docs": {
      "main": [
        [
          {
            "node": "Update Google Doc",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Refine Content with Gemini AI": {
      "ai_languageModel": [
        [
          {
            "node": "Generate SEO Blog Content",
            "type": "ai_languageModel",
            "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.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

For content creators, SEO specialists, and digital marketers who want to automatically generate SEO-optimized blog posts from trending topics — no manual writing or formatting required.

Source: https://n8n.io/workflows/10754/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

LinkedIn_Job_Hunt_and_Cover_Letter. Uses outputParserStructured, outputParserAutofixing, googleDrive, agent. Scheduled trigger; 85 nodes.

Output Parser Structured, Output Parser Autofixing, Google Drive +6
AI & RAG

Automatically scan major financial newswires for biotech catalyst events, score them with AI sentiment analysis, and surface ranked trade candidates — all without manual monitoring.

RSS Feed Read, Data Table, HTTP Request +4
AI & RAG

Author: Nguyen Thieu Toan Category: Community & Knowledge Automation Tags: Telegram, Reddit, n8n Forum, AI Summarization, Gemini, Groq

Groq Chat, Output Parser Structured, Memory Mongo Db Chat +5
AI & RAG

Fully automated blog creation system using n8n + AI Agents + Image Generation

Agent, Output Parser Structured, Groq Chat +9
AI & RAG

This workflow automates the complete blog publishing process. It removes manual work from content creation, image generation, category management, and WordPress publishing by using AI and n8n. It help

Google Gemini Chat, Output Parser Structured, Lm Chat Deep Seek +5