How To Automate Your Social Media with AI + n8n?

Tired of manually posting on social media every day? Want to grow your audience while you sleep? In this guide, I’ll show you how to create an AI-powered social media agent that automatically posts trending news to LinkedIn and Facebook—for free using n8n (a no-code automation tool).

How It Works

  1. Fetches Latest News – Uses the GNews API to find trending articles.
  2. Generates AI Content – Google Gemini rewrites the news into engaging posts.
  3. Creates AI Images – Automatically generates visuals for each post.
  4. Auto-Posts to Social Media – Publishes to LinkedIn & Facebook on a schedule.

What You’ll Need

✅ Free n8n account
✅ Free Google Gemini API Key
✅ Free GNews API Key
✅ Facebook & LinkedIn developer access (for auto-posting)


Step 1: Set Up the n8n Workflow

  1. Go to n8n.io and sign up (or use the desktop app).
  2. Create a new workflow (click the + button).
  3. Add a Schedule Trigger – This will run your workflow daily.
  • Set it to trigger at 9 AM (or your preferred time).

Step 2: Fetch Trending News (GNews API)

  1. Add an HTTP Request Node – This will call the GNews API.
  2. Configure the API Request:
  • Method: GET
  • URL: https://gnews.io/api/v4/search
  • Query Parameters:
    • token=YOUR_API_KEY (Get it from GNews)
    • q=ecommerce (or any topic like “AI,” “marketing,” etc.)
    • lang=en (for English articles)
    • max=5 (number of articles to fetch)
  1. Test the Node – You should see recent news articles in JSON format.

Step 3: Let AI Pick the Best Article

  1. Add an AI Agent Node (Google Gemini).
  2. Configure Gemini API:
  • Model: Gemini 1.5 Pro
  • Prompt:
You are an expert social media strategist and content curator. Your task is to help me identify 1 article from following and analyze their potential for high click-through rates when shared on social media.

Article #1:

Title: {{ $json.articles[0].title }}
Description: {{ $json.articles[0].description }}
Content: {{ $json.articles[0].content }}
URL: {{ $json.articles[0].url }}

Article #2:
Title: {{ $json.articles[1].title }}
Description: {{ $json.articles[1].description }}
Content: {{ $json.articles[1].content }}
URL: {{ $json.articles[1].url }}

In return only share Title, URL and summary with in 100 words of that article. In following format

Title: 
URL: 
Summary:
  1. Map the GNews data (title, description, URL) into the AI input.
  2. Test the Node – It should return the best article for posting.

Step 4: Generate AI-Powered Post Content

  1. Add Another AI Agent Node (Gemini).
  2. Prompt:
   "Write a LinkedIn/Facebook post about this news. Make it engaging, add hashtags, and include 'Read more: [URL]' at the end."  
  1. Test the Node – You’ll get a ready-to-post social media update.

Step 5: Create an AI Image for the Post

  1. Add an HTTP Request Node (Gemini Image Generation).
  2. URL: https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent
  3. Headers: Authorization: Bearer YOUR_GEMINI_API_KEY
  4. Body (JSON):
    json { "contents": [{ "parts": [{ "text": "Generate an engaging social media image about: [ARTICLE_SUMMARY]" }] }] }
  5. Test & Extract Image URL – Save the generated image for posting.

Step 6: Auto-Post to Facebook

  1. Add Facebook Graph API Node.
  2. Configure:
  • Endpoint: me/feed (or page_id/feed for Pages).
  • Method: POST
  • Parameters:
    • message = AI-generated post text
    • url = AI-generated image URL
  1. Test the Node – Check your Facebook to confirm the post went live!

Step 7: Auto-Post to LinkedIn

  1. Add LinkedIn API Node.
  2. Configure:
  • Endpoint: ugcPosts
  • Method: POST
  • Body:
    json { "author": "urn:li:person:YOUR_ID", "lifecycleState": "PUBLISHED", "specificContent": { "com.linkedin.ugc.ShareContent": { "shareCommentary": { "text": "AI-generated post here" }, "media": [{ "status": "READY", "description": { "text": "AI-generated image" } }] } }, "visibility": { "com.linkedin.ugc.MemberNetworkVisibility": "PUBLIC" } }
  1. Test & Confirm Posting – Refresh LinkedIn to see the automated post!

Step 8: Schedule Daily Auto-Posting

  • Go back to the Schedule Trigger and set it to run daily at your chosen time.
  • Save & Activate the workflow.

🎉 Done! Your AI agent will now:
✔ Fetch trending news
✔ Write posts with AI
✔ Generate images
✔ Post to LinkedIn & Facebook automatically!


Bonus: Expand to Twitter & Instagram

Want to add more platforms? Drop a comment below, and I’ll make a follow-up tutorial!

Complete JSON Code for N8N Workflow

{
  "name": "Social Media Content Generator",
  "nodes": [
    {
      "parameters": {
        "url": "https://gnews.io/api/v4/search",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "q",
              "value": "ecommerce"
            },
            {
              "name": "lang",
              "value": "en"
            },
            {
              "name": "country",
              "value": "us"
            },
            {
              "name": "max",
              "value": "10"
            },
            {
              "name": "apikey",
              "value": "b005cb1634851b7ebc140bdb1aac6847"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        260,
        0
      ],
      "id": "d6cfa9fa-bcdb-4196-8264-9d747a8a05b3",
      "name": "HTTP Request"
    },
    {
      "parameters": {
        "amount": 1
      },
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        1020,
        0
      ],
      "id": "7debaf41-c5c4-49ef-9e6f-3eaccfeaa78f",
      "name": "Wait1",
      "webhookId": "f2d44e18-f08a-4db2-b42e-370b6be83598"
    },
    {
      "parameters": {
        "jsCode": "const outputText = $input.first().json.output;\n\nlet title = '';\nlet summary = '';\nlet url = '';\n\n// Regex for URL - notice the escaped asterisks: \\*\\*\nconst urlMatch = outputText.match(/\\*\\*URL:\\*\\* (.*?)\\n/);\nif (urlMatch && urlMatch[1]) {\n  url = urlMatch[1].trim();\n}\n\n// Regex for Title - notice the escaped asterisks: \\*\\*\nconst titleMatch = outputText.match(/\\*\\*Title:\\*\\* (.*?)\\n/);\nif (titleMatch && titleMatch[1]) {\n  title = titleMatch[1].trim();\n}\n\n// Extract Summary - notice the escaped asterisks: \\*\\*\n// [\\s\\S]* matches any character including newline until the end of the string\nconst summaryMatch = outputText.match(/\\*\\*Summary:\\*\\* ([\\s\\S]*)/);\nif (summaryMatch && summaryMatch[1]) {\n  summary = summaryMatch[1].trim();\n}\n\n// It's good practice to only build the imagePrompt if summary is found\nlet imagePrompt = '';\nif (summary) {\n    imagePrompt = `Illustrate the concept of: ${summary}`;\n} else {\n    // Handle cases where summary might still not be found, e.g., if output format changes\n    imagePrompt = 'Illustrate the concept of: [Summary not available]';\n}\n\n\nreturn [{\n  json: {\n    originalTitle: title,\n    originalSummary: summary,\n    imagePrompt: imagePrompt,\n    originalURL: url\n  }\n}];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        800,
        0
      ],
      "id": "77ffb7bc-c65f-40bf-8ad9-9b1f2a26eac5",
      "name": "Code"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp-image-generation:generateContent",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "googlePalmApi",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{\n  {\n    \"contents\": [{\n      \"parts\": [\n        { \"text\": $('Code').item.json.imagePrompt }\n      ]\n    }],\n    \"generationConfig\": { \"responseModalities\": [\"TEXT\", \"IMAGE\"] }\n  }\n}}",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1820,
        0
      ],
      "id": "13782923-fed9-4560-a883-150071a476b1",
      "name": "HTTP Request1",
      "retryOnFail": true,
      "waitBetweenTries": 5000,
      "credentials": {
        "googlePalmApi": {
          "id": "6Ym7ncLLSycPldzg",
          "name": "Google Gemini(PaLM) Api account"
        }
      }
    },
    {
      "parameters": {
        "amount": 1
      },
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        1640,
        0
      ],
      "id": "d537ebeb-6a35-4990-b336-ea98d5a8626a",
      "name": "Wait",
      "webhookId": "fff719c9-e7b5-493e-bd81-78b50adb3e89"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=You are an expert social media strategist and content curator. Your task is to help me identify 1 article from following and analyze their potential for high click-through rates when shared on social media.\n\nArticle #1:\n\nTitle: {{ $json.articles[0].title }}\nDescription: {{ $json.articles[0].description }}\nContent: {{ $json.articles[0].content }}\nURL: {{ $json.articles[0].url }}\n\nArticle #2:\nTitle: {{ $json.articles[1].title }}\nDescription: {{ $json.articles[1].description }}\nContent: {{ $json.articles[1].content }}\nURL: {{ $json.articles[1].url }}\n\nIn return only share Title, URL and summary with in 100 words of that article. In following format\n\nTitle: \nURL: \nSummary:",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 1.7,
      "position": [
        460,
        0
      ],
      "id": "cc9da31c-c977-496a-9b63-e9920a690114",
      "name": "AI Agent"
    },
    {
      "parameters": {
        "modelName": "models/gemini-2.5-pro-preview-05-06",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1,
      "position": [
        500,
        220
      ],
      "id": "8d09d174-8b50-416d-bed3-2d7ed7805971",
      "name": "Google Gemini Chat Model",
      "credentials": {
        "googlePalmApi": {
          "id": "6Ym7ncLLSycPldzg",
          "name": "Google Gemini(PaLM) Api account"
        }
      }
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=You are an experienced Marketing Manager writing a LinkedIn post. Your goal is to share a valuable insight from following summary\n\n{{ $json.originalSummary }}\n\nReflection in a way that feels authentic, engaging, and genuinely human-written. Only return linkedin post content. Don't include anything like \"Here's a LinkedIn post reflecting on the summary:\". Please only return post which I can copy and paste in linkedin directly ",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 1.7,
      "position": [
        1300,
        0
      ],
      "id": "12d60105-12ba-47d8-aa89-304ccc436a45",
      "name": "AI Agent1"
    },
    {
      "parameters": {
        "modelName": "models/gemini-2.5-flash-preview-04-17-thinking",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1,
      "position": [
        1220,
        220
      ],
      "id": "52901dad-e16e-47f6-bbbd-9a3cb48218e3",
      "name": "Google Gemini Chat Model1",
      "credentials": {
        "googlePalmApi": {
          "id": "6Ym7ncLLSycPldzg",
          "name": "Google Gemini(PaLM) Api account"
        }
      }
    },
    {
      "parameters": {
        "operation": "toBinary",
        "sourceProperty": "imageData",
        "options": {}
      },
      "type": "n8n-nodes-base.convertToFile",
      "typeVersion": 1.1,
      "position": [
        2360,
        0
      ],
      "id": "1be7a527-a6dd-437a-a4b3-c9e098548cfc",
      "name": "Convert to File",
      "retryOnFail": true,
      "waitBetweenTries": 2000
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 10
            }
          ]
        }
      },
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        0
      ],
      "id": "4aeb37b1-ed43-433c-9317-bac7e423d2e9",
      "name": "Schedule Trigger"
    },
    {
      "parameters": {
        "postAs": "organization",
        "organization": "10500516",
        "text": "={{ $('Wait').item.json.output }}\n\nRead More: {{ $('Code').item.json.originalURL }}",
        "shareMediaCategory": "IMAGE",
        "additionalFields": {}
      },
      "type": "n8n-nodes-base.linkedIn",
      "typeVersion": 1,
      "position": [
        2720,
        -60
      ],
      "id": "0263af92-e4c6-442a-8977-00081797b174",
      "name": "Post To Linkedin",
      "credentials": {
        "linkedInOAuth2Api": {
          "id": "oI6AJAhpxFVotGo8",
          "name": "LinkedIn account"
        }
      }
    },
    {
      "parameters": {
        "httpRequestMethod": "POST",
        "graphApiVersion": "v22.0",
        "node": "me",
        "edge": "photos",
        "options": {
          "queryParameters": {
            "parameter": [
              {
                "name": "message",
                "value": "={{ $('AI Agent1').item.json.output }}\n\nRead More: {{ $('Wait1').item.json.originalURL }}"
              },
              {
                "name": "url",
                "value": "={{ $('Google Drive Upload Image').item.json.webContentLink }}"
              }
            ]
          }
        }
      },
      "type": "n8n-nodes-base.facebookGraphApi",
      "typeVersion": 1,
      "position": [
        2860,
        260
      ],
      "id": "37e3d697-4599-40d3-94af-941ddc5f0c3d",
      "name": "Post To Facebook",
      "credentials": {
        "facebookGraphApi": {
          "id": "iEdddBpcH0TtneDh",
          "name": "Facebook Graph account"
        }
      }
    },
    {
      "parameters": {
        "name": "image.png",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "folderId": {
          "__rl": true,
          "value": "1C0m6_SFcDzcII49KkBgONQEmOjVrsTrE",
          "mode": "list",
          "cachedResultName": "Content Creator",
          "cachedResultUrl": "https://drive.google.com/drive/folders/1C0m6_SFcDzcII49KkBgONQEmOjVrsTrE"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleDrive",
      "typeVersion": 3,
      "position": [
        2440,
        260
      ],
      "id": "78b86c63-988d-4b2f-b86f-fe4f308cfce5",
      "name": "Google Drive Upload Image",
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "21UFu9AjTKl1aVlG",
          "name": "Google Drive account"
        }
      }
    },
    {
      "parameters": {
        "operation": "share",
        "fileId": {
          "__rl": true,
          "value": "={{ $json.id }}",
          "mode": "id"
        },
        "permissionsUi": {
          "permissionsValues": {
            "role": "writer",
            "type": "anyone"
          }
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleDrive",
      "typeVersion": 3,
      "position": [
        2640,
        260
      ],
      "id": "5b53590f-6288-4ba1-8b52-01a46ceb6fd0",
      "name": "Google Drive Set Permissions",
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "21UFu9AjTKl1aVlG",
          "name": "Google Drive account"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const items = $input.first().json.candidates; // Or however you get the input item\nconst results = [];\n\nfor (const item of items) {\n  // Adjust the path according to the actual output structure\n  // This assumes the first candidate is the one we want.\n  const parts = $input.first().json.candidates[0].content.parts;\n  let imageBase64 = null;\n  let imageMimeType = null;\n\n  for (const part of parts) {\n    if (part.inlineData && part.inlineData.mimeType && part.inlineData.mimeType.startsWith('image/')) {\n      imageBase64 = part.inlineData.data;\n      imageMimeType = part.inlineData.mimeType;\n      break; // Found the image part\n    }\n  }\n\n  if (imageBase64) {\n    results.push({\n      json: {\n        imageData: imageBase64,\n        mimeType: imageMimeType\n        // You can add other fields from the original item if needed\n        // ...item.json\n      }\n    });\n  } else {\n    // Handle case where no image part was found (optional)\n    results.push({ json: { error: \"No image data found in response\", originalResponse: item.json } });\n  }\n}\n\nreturn results;"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2100,
        0
      ],
      "id": "3b1ece86-a1ea-42bc-9c56-d9a301aacab6",
      "name": "Code1"
    }
  ],
  "pinData": {},
  "connections": {
    "Code": {
      "main": [
        [
          {
            "node": "Wait1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request1": {
      "main": [
        [
          {
            "node": "Code1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait": {
      "main": [
        [
          {
            "node": "HTTP Request1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait1": {
      "main": [
        [
          {
            "node": "AI Agent1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent1",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent1": {
      "main": [
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert to File": {
      "main": [
        [
          {
            "node": "Google Drive Upload Image",
            "type": "main",
            "index": 0
          },
          {
            "node": "Post To Linkedin",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Drive Upload Image": {
      "main": [
        [
          {
            "node": "Google Drive Set Permissions",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Drive Set Permissions": {
      "main": [
        [
          {
            "node": "Post To Facebook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code1": {
      "main": [
        [
          {
            "node": "Convert to File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "1c550945-ed48-4a32-a7ae-5fb494443c58",
  "meta": {
    "templateCredsSetupCompleted": true,
    "instanceId": "7d6a5bcda733904ebcb54fc0e889f6735550f40f670703e17874c0872e05a9cb"
  },
  "id": "MThpyJnqjAHtW512",
  "tags": []
}
5/5 - (5 votes)

About

Leave a Comment

Your email address will not be published. Required fields are marked *