AutomationFlowsSocial Media › Generate Social Media Posts with GPT-4 for LinkedIn, X, and Facebook

Generate Social Media Posts with GPT-4 for LinkedIn, X, and Facebook

ByOneclick AI Squad @oneclick-ai on n8n.io

Automatically generates engaging marketing posts using OpenAI and publishes them across LinkedIn, Twitter (X), and Facebook. Creates platform-optimized content with hashtags, emojis, and proper formatting. Trigger — Runs daily at 10 AM or manual trigger for on-demand content…

Cron / scheduled trigger★★★★☆ complexity21 nodesHTTP RequestPostgres
Social Media Trigger: Cron / scheduled Nodes: 21 Complexity: ★★★★☆ Added:
Generate Social Media Posts with GPT-4 for LinkedIn, X, and Facebook — n8n workflow card showing HTTP Request, Postgres integration

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

This workflow follows the HTTP Request → Postgres 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": "Dr4ufJMCSwMI3yZJ",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "AI Social Media Content Generator",
  "tags": [],
  "nodes": [
    {
      "id": "d4a6b0a9-9d75-4420-a752-2c970539dca8",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2128,
        48
      ],
      "parameters": {
        "width": 820,
        "height": 720,
        "content": "## AI Social Media Content Generator\n\nAutomatically generates engaging marketing posts using OpenAI and publishes them across LinkedIn, Twitter (X), and Facebook. Creates platform-optimized content with hashtags, emojis, and proper formatting.\n\n## How it works\n\n1. **Trigger** \u2014 Runs daily at 10 AM or manual trigger for on-demand content\n2. **Generate** \u2014 Creates tailored marketing content using OpenAI GPT-4 based on topic/theme\n3. **Optimize** \u2014 Customizes content for each platform (character limits, hashtags, tone)\n4. **Review** \u2014 Optional human approval gate before publishing\n5. **Publish** \u2014 Auto-posts to LinkedIn, Twitter, and Facebook simultaneously\n6. **Track** \u2014 Logs all posts to database for analytics and content history\n7. **Notify** \u2014 Sends confirmation to Slack with links to published posts\n\n## Setup steps\n\n1. **OpenAI API** \u2014 Add your OpenAI API key in credentials\n2. **Social Media APIs** \u2014 Configure LinkedIn, Twitter (X), and Facebook credentials\n3. **PostgreSQL** \u2014 Create `social_posts` table to store post history\n4. **Slack** \u2014 Add webhook URL for notifications\n5. **Content Topics** \u2014 Customize the topic list in the initial node\n6. **Approval** (Optional) \u2014 Enable/disable manual review gate\n7. **Test** \u2014 Run manually first, then activate for daily automation"
      },
      "typeVersion": 1
    },
    {
      "id": "1fd10534-b70f-42ac-8f66-3610eb9ae0ad",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1200,
        256
      ],
      "parameters": {
        "color": 4,
        "width": 468,
        "height": 465,
        "content": "## 1. Trigger content generation\n\nRuns daily at 10 AM or can be triggered manually for on-demand content creation"
      },
      "typeVersion": 1
    },
    {
      "id": "b797c0cb-a919-4ba4-959e-07214e9b27e9",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -704,
        256
      ],
      "parameters": {
        "color": 5,
        "width": 668,
        "height": 465,
        "content": "## 2. Generate & optimize content\n\nUses OpenAI to create engaging posts and optimizes for each platform's requirements"
      },
      "typeVersion": 1
    },
    {
      "id": "c489aaea-efbe-465c-ba47-8ac4f49c970b",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        0
      ],
      "parameters": {
        "color": 4,
        "width": 636,
        "height": 905,
        "content": "## 3. Publish to platforms\n\nPosts content to LinkedIn, Twitter, and Facebook with platform-specific formatting"
      },
      "typeVersion": 1
    },
    {
      "id": "0c721a5a-2f20-4f18-9a89-1d85ef34e1a1",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        688,
        144
      ],
      "parameters": {
        "color": 5,
        "width": 960,
        "height": 601,
        "content": "## 4. Track & notify\n\nStores post data in database and sends confirmation notifications to team via Slack"
      },
      "typeVersion": 1
    },
    {
      "id": "36d9fe76-7799-456c-a6a2-8dc45b4743cc",
      "name": "Daily content generation at 10 AM",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1088,
        448
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 10 * * *"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "a18aba08-7b8a-4c1e-9133-175880c69c5b",
      "name": "Select content topic and type",
      "type": "n8n-nodes-base.code",
      "position": [
        -864,
        448
      ],
      "parameters": {
        "jsCode": "// Select random topic and content type for variety\nconst topics = [\n  { category: 'Product Launch', focus: 'announcing new features', tone: 'excited' },\n  { category: 'Industry Insights', focus: 'latest trends and analysis', tone: 'professional' },\n  { category: 'Customer Success', focus: 'testimonials and case studies', tone: 'inspiring' },\n  { category: 'Tips & How-To', focus: 'practical advice and tutorials', tone: 'helpful' },\n  { category: 'Company Culture', focus: 'behind-the-scenes and team highlights', tone: 'friendly' },\n  { category: 'Thought Leadership', focus: 'industry opinions and insights', tone: 'authoritative' },\n  { category: 'Events & Webinars', focus: 'upcoming events and recordings', tone: 'inviting' },\n  { category: 'Industry News', focus: 'recent developments and commentary', tone: 'informative' }\n];\n\nconst contentTypes = ['Educational', 'Promotional', 'Engagement', 'Storytelling'];\n\n// Select random topic\nconst selectedTopic = topics[Math.floor(Math.random() * topics.length)];\nconst selectedType = contentTypes[Math.floor(Math.random() * contentTypes.length)];\n\nconst timestamp = new Date().toISOString();\nconst dateString = new Date().toLocaleDateString('en-US', { \n  year: 'numeric', \n  month: 'long', \n  day: 'numeric' \n});\n\n// Generate unique post ID\nconst postId = `POST-${new Date().getFullYear()}-${String(new Date().getMonth() + 1).padStart(2, '0')}-${String(new Date().getDate()).padStart(2, '0')}-${Math.floor(Math.random() * 10000)}`;\n\nreturn [\n  {\n    json: {\n      postId,\n      timestamp,\n      dateString,\n      topic: selectedTopic,\n      contentType: selectedType,\n      category: selectedTopic.category,\n      focus: selectedTopic.focus,\n      tone: selectedTopic.tone\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "ac0ff0cc-779e-4d85-8bb5-1c14c482d561",
      "name": "Generate content with OpenAI GPT-4",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -640,
        448
      ],
      "parameters": {
        "url": "https://api.openai.com/v1/chat/completions",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "model",
              "value": "gpt-4"
            },
            {
              "name": "messages",
              "value": "={{ [{\"role\": \"system\", \"content\": \"You are a social media marketing expert who creates engaging, platform-optimized content. Generate posts that drive engagement and conversions.\"}, {\"role\": \"user\", \"content\": \"Create a \" + $json.contentType + \" social media post about \" + $json.category + \" focusing on \" + $json.focus + \". Tone should be \" + $json.tone + \". Include a compelling hook, key message, call-to-action, and relevant hashtags. Keep it under 200 words.\"}] }}"
            },
            {
              "name": "temperature",
              "value": "0.8"
            },
            {
              "name": "max_tokens",
              "value": "500"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "openAiApi"
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "a8a9b912-7470-41a2-b06a-48111ff94f24",
      "name": "Parse AI response and extract content",
      "type": "n8n-nodes-base.code",
      "position": [
        -416,
        448
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Extract generated content from OpenAI response\nconst data = $input.item.json;\nconst inputData = $input.first().json;\n\nconst aiContent = data.choices?.[0]?.message?.content || 'Failed to generate content';\n\n// Parse the generated content\nconst lines = aiContent.split('\\n').filter(line => line.trim());\nconst baseContent = aiContent;\n\n// Extract hashtags if present\nconst hashtagRegex = /#\\w+/g;\nconst hashtags = aiContent.match(hashtagRegex) || [];\n\n// Remove hashtags from base content for cleaner text\nconst contentWithoutHashtags = aiContent.replace(hashtagRegex, '').trim();\n\nreturn {\n  json: {\n    ...inputData,\n    aiGeneratedContent: baseContent,\n    contentWithoutHashtags,\n    extractedHashtags: hashtags,\n    wordCount: baseContent.split(/\\s+/).length,\n    hasHashtags: hashtags.length > 0\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "7b8a73da-86cf-4d8c-82dd-53fdb8d0c4e2",
      "name": "Optimize content for each platform",
      "type": "n8n-nodes-base.code",
      "position": [
        -192,
        448
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Create platform-specific versions of the content\nconst data = $input.item.json;\nconst baseContent = data.contentWithoutHashtags;\nconst hashtags = data.extractedHashtags || [];\n\n// --- LINKEDIN VERSION ---\n// LinkedIn allows 3000 chars but optimal is 150-250 words\n// Professional tone, less emojis\nlet linkedinContent = baseContent;\nif (linkedinContent.length > 1200) {\n  linkedinContent = linkedinContent.substring(0, 1200) + '...';\n}\nlinkedinContent += '\\n\\n' + hashtags.slice(0, 5).join(' ');\n\n// --- TWITTER/X VERSION ---\n// Twitter has 280 character limit\n// Need to be concise, use more hashtags\nlet twitterContent = baseContent;\nif (twitterContent.length > 220) {\n  // Find first sentence or cut at 220 chars\n  const firstSentence = twitterContent.match(/^[^.!?]+[.!?]/);\n  if (firstSentence && firstSentence[0].length < 220) {\n    twitterContent = firstSentence[0];\n  } else {\n    twitterContent = twitterContent.substring(0, 220) + '...';\n  }\n}\n// Add hashtags (leave room for them)\nconst hashtagString = hashtags.slice(0, 3).join(' ');\nif (twitterContent.length + hashtagString.length + 3 <= 280) {\n  twitterContent += '\\n\\n' + hashtagString;\n}\n\n// --- FACEBOOK VERSION ---\n// Facebook optimal is 40-80 characters for max engagement\n// But can be longer (63,206 limit). We'll go for ~300 words max\nlet facebookContent = baseContent;\nif (facebookContent.length > 1500) {\n  facebookContent = facebookContent.substring(0, 1500) + '...';\n}\n// Facebook uses hashtags but they're less important\nfacebookContent += '\\n\\n' + hashtags.slice(0, 5).join(' ');\n\n// Add emoji enhancement for Facebook (more casual)\nconst emojiMap = {\n  'excited': '\ud83d\ude80 ',\n  'professional': '\ud83d\udcbc ',\n  'inspiring': '\u2b50 ',\n  'helpful': '\ud83d\udca1 ',\n  'friendly': '\ud83d\ude0a ',\n  'authoritative': '\ud83c\udfaf ',\n  'inviting': '\ud83c\udf89 ',\n  'informative': '\ud83d\udcca '\n};\n\nconst emoji = emojiMap[data.tone] || '\u2728 ';\nfacebookContent = emoji + facebookContent;\n\nreturn {\n  json: {\n    ...data,\n    platforms: {\n      linkedin: {\n        content: linkedinContent,\n        platform: 'LinkedIn',\n        characterCount: linkedinContent.length,\n        hashtagCount: hashtags.slice(0, 5).length\n      },\n      twitter: {\n        content: twitterContent,\n        platform: 'Twitter/X',\n        characterCount: twitterContent.length,\n        hashtagCount: hashtags.slice(0, 3).length,\n        withinLimit: twitterContent.length <= 280\n      },\n      facebook: {\n        content: facebookContent,\n        platform: 'Facebook',\n        characterCount: facebookContent.length,\n        hashtagCount: hashtags.slice(0, 5).length,\n        hasEmoji: true\n      }\n    },\n    totalHashtags: hashtags.length,\n    platformCount: 3\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "1d0d4b10-be95-404b-86bc-c6372dc49bfd",
      "name": "Split content for each platform",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        32,
        448
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "="
      },
      "typeVersion": 1
    },
    {
      "id": "ad974eaa-30b9-4c41-bc43-12d0cc05adae",
      "name": "Route to appropriate platform",
      "type": "n8n-nodes-base.switch",
      "position": [
        256,
        432
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "LinkedIn",
              "conditions": {
                "options": {
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.platform }}",
                    "rightValue": "LinkedIn"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Twitter",
              "conditions": {
                "options": {
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.platform }}",
                    "rightValue": "Twitter/X"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Facebook",
              "conditions": {
                "options": {
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.platform }}",
                    "rightValue": "Facebook"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "034ef4da-8e8e-46e5-86cf-e2ed05d1967e",
      "name": "Post to LinkedIn",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        480,
        160
      ],
      "parameters": {
        "url": "https://api.linkedin.com/v2/ugcPosts",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "author",
              "value": "={{ \"urn:li:person:YOUR_LINKEDIN_ID\" }}"
            },
            {
              "name": "lifecycleState",
              "value": "PUBLISHED"
            },
            {
              "name": "specificContent",
              "value": "={{ {\"com.linkedin.ugc.ShareContent\": {\"shareCommentary\": {\"text\": $json.content}, \"shareMediaCategory\": \"NONE\"}} }}"
            },
            {
              "name": "visibility",
              "value": "={{ {\"com.linkedin.ugc.MemberNetworkVisibility\": \"PUBLIC\"} }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "X-Restli-Protocol-Version",
              "value": "2.0.0"
            }
          ]
        },
        "nodeCredentialType": "linkedInOAuth2Api"
      },
      "credentials": {
        "linkedInOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "58b1fc79-70dc-4f66-ae13-2beb87b23926",
      "name": "Post to Twitter/X",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        480,
        352
      ],
      "parameters": {
        "url": "https://api.twitter.com/2/tweets",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "text",
              "value": "={{ $json.content }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "twitterOAuth2Api"
      },
      "credentials": {
        "twitterOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "2bd704dc-22d4-4bdc-ba20-657239f191fb",
      "name": "Post to Facebook",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        480,
        544
      ],
      "parameters": {
        "url": "https://graph.facebook.com/v18.0/me/feed",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "message",
              "value": "={{ $json.content }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "facebookGraphApi"
      },
      "credentials": {
        "facebookGraphApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "17480ec1-6390-49a2-90e0-dd9bbff19fe4",
      "name": "Aggregate all platform results",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        704,
        352
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "f3795911-062c-4e77-bd21-98c05d5b4221",
      "name": "Prepare database record",
      "type": "n8n-nodes-base.code",
      "position": [
        928,
        352
      ],
      "parameters": {
        "jsCode": "// Prepare consolidated record for database storage\nconst items = $input.all();\nconst firstItem = items[0].json;\n\nconst timestamp = new Date().toISOString();\n\n// Extract platform results\nconst platformResults = {};\nconst postLinks = {};\n\nitems.forEach(item => {\n  const platform = item.json.platform;\n  const responseData = item.json;\n  \n  platformResults[platform] = {\n    success: responseData.id || responseData.data?.id ? true : false,\n    postId: responseData.id || responseData.data?.id || null,\n    characterCount: item.json.characterCount || 0\n  };\n  \n  // Build post links (platform-specific)\n  if (platform === 'LinkedIn' && responseData.id) {\n    postLinks[platform] = `https://www.linkedin.com/feed/update/${responseData.id}`;\n  } else if (platform === 'Twitter/X' && responseData.data?.id) {\n    postLinks[platform] = `https://twitter.com/user/status/${responseData.data.id}`;\n  } else if (platform === 'Facebook' && responseData.id) {\n    postLinks[platform] = `https://www.facebook.com/${responseData.id}`;\n  }\n});\n\nconst allSuccessful = Object.values(platformResults).every(r => r.success);\nconst successCount = Object.values(platformResults).filter(r => r.success).length;\n\nreturn [\n  {\n    json: {\n      postId: firstItem.postId,\n      timestamp,\n      category: firstItem.category,\n      contentType: firstItem.contentType,\n      tone: firstItem.tone,\n      focus: firstItem.focus,\n      baseContent: firstItem.aiGeneratedContent,\n      linkedinContent: firstItem.platforms?.linkedin?.content || '',\n      twitterContent: firstItem.platforms?.twitter?.content || '',\n      facebookContent: firstItem.platforms?.facebook?.content || '',\n      totalHashtags: firstItem.totalHashtags || 0,\n      wordCount: firstItem.wordCount || 0,\n      platformResults: JSON.stringify(platformResults),\n      postLinks: JSON.stringify(postLinks),\n      allPlatformsSuccess: allSuccessful,\n      successfulPlatforms: successCount,\n      status: allSuccessful ? 'PUBLISHED' : 'PARTIAL',\n      publishedAt: timestamp\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "4dd34fc5-6e0f-4d78-b402-432c04b08836",
      "name": "Store post record in PostgreSQL",
      "type": "n8n-nodes-base.postgres",
      "position": [
        1152,
        352
      ],
      "parameters": {
        "table": "social_posts",
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "columns": {
          "value": {},
          "schema": [],
          "mappingMode": "autoMapInputData",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "1b36c38f-c288-4517-b5ef-7a037218dfd3",
      "name": "Prepare Slack notification",
      "type": "n8n-nodes-base.code",
      "position": [
        1152,
        544
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Create formatted Slack notification message\nconst data = $input.item.json;\n\nconst statusEmoji = data.allPlatformsSuccess ? '\u2705' : '\u26a0\ufe0f';\nconst statusText = data.allPlatformsSuccess ? 'Successfully Published' : 'Partially Published';\n\nconst postLinks = JSON.parse(data.postLinks || '{}');\n\nlet linkSection = '';\nfor (const [platform, link] of Object.entries(postLinks)) {\n  linkSection += `\\n\u2022 *${platform}:* <${link}|View Post>`;\n}\n\nif (!linkSection) {\n  linkSection = '\\n_No post links available_';\n}\n\nconst message = `${statusEmoji} *Social Media Post ${statusText}*\\n\\n` +\n  `*Post ID:* ${data.postId}\\n` +\n  `*Category:* ${data.category}\\n` +\n  `*Content Type:* ${data.contentType}\\n` +\n  `*Tone:* ${data.tone}\\n` +\n  `*Platforms:* ${data.successfulPlatforms}/3 successful\\n` +\n  `*Hashtags Used:* ${data.totalHashtags}\\n` +\n  `*Word Count:* ${data.wordCount}\\n\\n` +\n  `*Post Links:*${linkSection}\\n\\n` +\n  `*Preview:*\\n_${data.baseContent.substring(0, 150)}${data.baseContent.length > 150 ? '...' : ''}_`;\n\nreturn {\n  json: {\n    ...data,\n    slackMessage: message,\n    slackTitle: `${statusEmoji} Social Media Post ${statusText}`\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "2f08c1c1-ad8c-4331-b760-34049e7b5b3d",
      "name": "Send confirmation to Slack",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1376,
        544
      ],
      "parameters": {
        "url": "YOUR_SLACK_WEBHOOK_URL",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"text\": \"{{ $json.slackTitle }}\",\n  \"blocks\": [\n    {\n      \"type\": \"section\",\n      \"text\": {\n        \"type\": \"mrkdwn\",\n        \"text\": \"{{ $json.slackMessage }}\"\n      }\n    }\n  ]\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "8801c163-69e4-4843-98df-c0ad31aad74f",
      "name": "Log success and update statistics",
      "type": "n8n-nodes-base.code",
      "position": [
        1376,
        352
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Log successful execution and track statistics\nconst data = $input.item.json;\nconst timestamp = new Date().toISOString();\n\nconsole.log(`\u2705 SUCCESS: Social post ${data.postId} | Status: ${data.status} | Platforms: ${data.successfulPlatforms}/3 | Category: ${data.category} | Time: ${timestamp}`);\n\n// Update cumulative statistics\nconst stats = $getWorkflowStaticData('global').socialStats || {\n  totalPosts: 0,\n  successfulPosts: 0,\n  partialPosts: 0,\n  failedPosts: 0,\n  totalHashtags: 0,\n  platformBreakdown: {\n    linkedin: 0,\n    twitter: 0,\n    facebook: 0\n  },\n  categoryBreakdown: {},\n  lastPosted: null\n};\n\nstats.totalPosts++;\nif (data.status === 'PUBLISHED') stats.successfulPosts++;\nelse if (data.status === 'PARTIAL') stats.partialPosts++;\nelse stats.failedPosts++;\n\nstats.totalHashtags += data.totalHashtags || 0;\nstats.lastPosted = timestamp;\n\n// Update category stats\nif (!stats.categoryBreakdown[data.category]) {\n  stats.categoryBreakdown[data.category] = 0;\n}\nstats.categoryBreakdown[data.category]++;\n\n// Update platform stats from results\nconst platformResults = JSON.parse(data.platformResults || '{}');\nfor (const [platform, result] of Object.entries(platformResults)) {\n  if (result.success) {\n    const platformKey = platform.toLowerCase().replace(/\\/x$/, '');\n    if (stats.platformBreakdown[platformKey] !== undefined) {\n      stats.platformBreakdown[platformKey]++;\n    }\n  }\n}\n\n$getWorkflowStaticData('global').socialStats = stats;\n\nreturn {\n  json: {\n    success: true,\n    postId: data.postId,\n    status: data.status,\n    platformsPublished: data.successfulPlatforms,\n    category: data.category,\n    timestamp,\n    cumulativeStats: stats\n  }\n};"
      },
      "typeVersion": 2
    }
  ],
  "active": true,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "6c7f4a8a-07c3-4bec-9d09-7c25460d62da",
  "connections": {
    "Post to Facebook": {
      "main": [
        [
          {
            "node": "Aggregate all platform results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post to LinkedIn": {
      "main": [
        [
          {
            "node": "Aggregate all platform results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post to Twitter/X": {
      "main": [
        [
          {
            "node": "Aggregate all platform results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare database record": {
      "main": [
        [
          {
            "node": "Store post record in PostgreSQL",
            "type": "main",
            "index": 0
          },
          {
            "node": "Prepare Slack notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Slack notification": {
      "main": [
        [
          {
            "node": "Send confirmation to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route to appropriate platform": {
      "main": [
        [
          {
            "node": "Post to LinkedIn",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Post to Twitter/X",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Post to Facebook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Select content topic and type": {
      "main": [
        [
          {
            "node": "Generate content with OpenAI GPT-4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate all platform results": {
      "main": [
        [
          {
            "node": "Prepare database record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split content for each platform": {
      "main": [
        [
          {
            "node": "Route to appropriate platform",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Store post record in PostgreSQL": {
      "main": [
        [
          {
            "node": "Log success and update statistics",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Daily content generation at 10 AM": {
      "main": [
        [
          {
            "node": "Select content topic and type",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate content with OpenAI GPT-4": {
      "main": [
        [
          {
            "node": "Parse AI response and extract content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Optimize content for each platform": {
      "main": [
        [
          {
            "node": "Split content for each platform",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI response and extract content": {
      "main": [
        [
          {
            "node": "Optimize content for each platform",
            "type": "main",
            "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

Automatically generates engaging marketing posts using OpenAI and publishes them across LinkedIn, Twitter (X), and Facebook. Creates platform-optimized content with hashtags, emojis, and proper formatting. Trigger — Runs daily at 10 AM or manual trigger for on-demand content…

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

More Social Media workflows → · Browse all categories →

Related workflows

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

Social Media

Automatically discovers trending topics in your niche and generates ready-to-use content ideas with AI. Twitter/X trending topics and hashtags Reddit hot posts from niche subreddits Google Trends dail

HTTP Request, Email Send, Slack +1
Social Media

Marketing teams and social media managers in Japan who want to automate content creation while maintaining high quality standards and cultural appropriateness. Perfect for businesses that need consist

HTTP Request, Notion, Email Send
Social Media

This n8n workflow is designed for content curators, digital marketers, and social media managers who want to automate the process of discovering, translating, and publishing news content from multiple

Edit Image, Facebook Graph Api, WordPress +9
Social Media

This template is ideal for sales teams, recruiters, business development professionals, and relationship managers who need to monitor changes in their network's LinkedIn profiles. Perfect for agencies

Google Sheets, HTTP Request, Slack
Social Media

Social media managers, creators, and brand accounts that rely on retweets for reach but want an automated, hands-off cleanup after campaigns to keep profiles tidy and on-brand.

HTTP Request, Twitter, Slack +1