AutomationFlowsGeneral › Generate and schedule social media content across platforms using AI and Google Sheets

Generate and schedule social media content across platforms using AI and Google Sheets

Generate and schedule social media content across platforms using AI and Google Sheets. Uses stickyNote, googleSheets, openAi, httpRequest. Scheduled trigger; 16 nodes.

Cron / scheduled trigger★★★★☆ complexityAI-powered16 nodesGoogle SheetsOpen AiHttp Request
General Trigger: Cron / scheduled Nodes: 16 Complexity: ★★★★☆ AI nodes: yes

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
{
  "name": "Generate and schedule social media content across platforms using AI and Google Sheets",
  "tags": [
    {
      "id": "social-media",
      "name": "Social Media",
      "createdAt": "2025-01-01T00:00:00.000Z",
      "updatedAt": "2025-01-01T00:00:00.000Z"
    },
    {
      "id": "ai-content",
      "name": "AI Content",
      "createdAt": "2025-01-01T00:00:00.000Z",
      "updatedAt": "2025-01-01T00:00:00.000Z"
    }
  ],
  "nodes": [
    {
      "id": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
      "name": "Daily Content Generation Trigger",
      "type": "n8n-nodes-base.cron",
      "position": [
        240,
        300
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 9 * * *"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "b2c3d4e5-f6g7-8901-2345-678901bcdefg",
      "name": "Workflow Instructions",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -200,
        100
      ],
      "parameters": {
        "color": 4,
        "width": 432,
        "height": 464,
        "content": "## \ud83d\udcf1 AI Social Media Content Automation\n\n**What this workflow does:**\nAutomatically generates and schedules social media content across multiple platforms using AI, based on your content calendar in Google Sheets.\n\n**How it works:**\n1. Runs daily at 9 AM to check your content calendar\n2. Reads scheduled topics from Google Sheets\n3. Uses OpenAI to generate platform-specific content\n4. Creates accompanying images with DALL-E\n5. Schedules posts across Twitter, LinkedIn, and Instagram\n6. Updates the spreadsheet with posting status\n7. Tracks engagement and performance metrics\n\n**Setup Requirements:**\n- Google Sheets with content calendar template\n- OpenAI API key (GPT-4 + DALL-E)\n- Buffer or Hootsuite account for scheduling\n- Social media platform API access\n- Google Drive for image storage\n\n**Customization Options:**\n- Adjust posting times and frequency\n- Customize AI prompts for your brand voice\n- Add more social platforms\n- Modify content types and formats\n- Include hashtag research and trends\n\n**Perfect for:**\n- Marketing teams managing multiple accounts\n- Content creators with consistent posting schedules\n- Small businesses automating social presence\n- Agencies managing client social media"
      },
      "typeVersion": 1
    },
    {
      "id": "c3d4e5f6-g7h8-9012-3456-789012cdefgh",
      "name": "Configuration Variables",
      "type": "n8n-nodes-base.set",
      "position": [
        480,
        300
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "GOOGLE_SHEET_ID",
              "name": "GOOGLE_SHEET_ID",
              "type": "string",
              "value": "your-sheet-id-here"
            },
            {
              "id": "CONTENT_WORKSHEET",
              "name": "CONTENT_WORKSHEET",
              "type": "string",
              "value": "Content Calendar"
            },
            {
              "id": "BRAND_VOICE",
              "name": "BRAND_VOICE",
              "type": "string",
              "value": "professional, engaging, and informative"
            },
            {
              "id": "COMPANY_NAME",
              "name": "COMPANY_NAME",
              "type": "string",
              "value": "Your Company"
            },
            {
              "id": "TARGET_AUDIENCE",
              "name": "TARGET_AUDIENCE",
              "type": "string",
              "value": "marketing professionals and business owners"
            }
          ]
        }
      },
      "typeVersion": 3.2
    },
    {
      "id": "d4e5f6g7-h8i9-0123-4567-890123defghi",
      "name": "Read Calendar Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        640,
        120
      ],
      "parameters": {
        "width": 280,
        "height": 180,
        "content": "\ud83d\udcca **Step 1: Read Content Calendar**\n\nReads today's scheduled content from Google Sheets:\n- Topic/theme for the day\n- Target platforms\n- Content type (educational, promotional, etc.)\n- Special instructions or keywords\n- Posting times\n\nExpected sheet columns:\nDate | Topic | Platforms | Content Type | Keywords | Status"
      },
      "typeVersion": 1
    },
    {
      "id": "e5f6g7h8-i9j0-1234-5678-901234efghij",
      "name": "Read Content Calendar",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        720,
        300
      ],
      "parameters": {
        "options": {
          "range": "A:G"
        },
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $('Configuration Variables').first().json.CONTENT_WORKSHEET }}"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Configuration Variables').first().json.GOOGLE_SHEET_ID }}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "f6g7h8i9-j0k1-2345-6789-012345fghijk",
      "name": "Filter Content Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        880,
        120
      ],
      "parameters": {
        "width": 280,
        "height": 160,
        "content": "\ud83c\udfaf **Step 2: Filter Today's Content**\n\nFilters the calendar data to find:\n- Posts scheduled for today\n- Pending/unprocessed content\n- Valid topic entries\n- Platform-specific requirements\n\nSkips completed posts and invalid entries."
      },
      "typeVersion": 1
    },
    {
      "id": "g7h8i9j0-k1l2-3456-7890-123456ghijkl",
      "name": "Filter Today's Content",
      "type": "n8n-nodes-base.code",
      "position": [
        960,
        300
      ],
      "parameters": {
        "jsCode": "// Filter content calendar for today's posts\nconst today = new Date().toISOString().split('T')[0];\nconst calendarData = $input.all();\n\n// Skip header row and filter for today's content\nconst todaysContent = calendarData.slice(1).filter(row => {\n  const rowData = row.json;\n  \n  if (!rowData.Date || !rowData.Topic) return false;\n  \n  let postDate;\n  if (rowData.Date.includes('/')) {\n    const [month, day, year] = rowData.Date.split('/');\n    postDate = `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`;\n  } else {\n    postDate = rowData.Date;\n  }\n  \n  return postDate === today && \n         rowData.Status !== 'Completed' && \n         rowData.Status !== 'Posted' &&\n         rowData.Topic.trim() !== '';\n});\n\nif (todaysContent.length === 0) {\n  return [{\n    json: {\n      message: \"No content scheduled for today\",\n      date: today,\n      hasContent: false\n    }\n  }];\n}\n\n// Process each content item\nreturn todaysContent.map((item, index) => {\n  const rowData = item.json;\n  \n  return {\n    json: {\n      rowIndex: index + 2,\n      topic: rowData.Topic || '',\n      platforms: rowData.Platforms || 'Twitter,LinkedIn',\n      contentType: rowData['Content Type'] || 'Educational',\n      keywords: rowData.Keywords || '',\n      date: today,\n      hasContent: true,\n      brandVoice: $('Configuration Variables').first().json.BRAND_VOICE,\n      companyName: $('Configuration Variables').first().json.COMPANY_NAME,\n      targetAudience: $('Configuration Variables').first().json.TARGET_AUDIENCE\n    }\n  };\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "h8i9j0k1-l2m3-4567-8901-234567hijklm",
      "name": "Check if Content Exists",
      "type": "n8n-nodes-base.if",
      "position": [
        1200,
        300
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "has_content",
              "operator": {
                "type": "boolean",
                "operation": "equal"
              },
              "leftValue": "={{ $json.hasContent }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "i9j0k1l2-m3n4-5678-9012-345678ijklmn",
      "name": "AI Content Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1360,
        120
      ],
      "parameters": {
        "width": 280,
        "height": 180,
        "content": "\ud83e\udd16 **Step 3: Generate AI Content**\n\nFor each platform, creates optimized content:\n- **Twitter**: 280 chars, trending hashtags, engaging hooks\n- **LinkedIn**: Professional tone, 1300 chars, industry insights\n- **Instagram**: Visual focus, story-driven, 2200 chars\n\nUses platform-specific best practices and your brand voice."
      },
      "typeVersion": 1
    },
    {
      "id": "j0k1l2m3-n4o5-6789-0123-456789jklmno",
      "name": "Generate Social Content with AI",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        1440,
        260
      ],
      "parameters": {
        "options": {
          "maxTokens": 1000,
          "temperature": 0.7
        },
        "resource": "chat",
        "chatInput": {
          "messages": {
            "values": [
              {
                "role": "system",
                "content": "You are an expert social media content creator. Generate platform-specific content that drives engagement.\n\nFor each platform:\n\n**TWITTER:**\n- Max 280 characters\n- Include 2-3 hashtags\n- Engaging hooks\n- Strategic emojis\n\n**LINKEDIN:**\n- Professional tone, 1000-1300 characters\n- Industry insights\n- 3-5 hashtags\n- Call-to-action\n\n**INSTAGRAM:**\n- Visual-first, up to 2200 characters\n- Storytelling format\n- 5-10 hashtags\n- Questions for engagement\n\nReturn JSON:\n{\n  \"twitter\": {\n    \"text\": \"content\",\n    \"hashtags\": [\"tag1\", \"tag2\"],\n    \"character_count\": number\n  },\n  \"linkedin\": {\n    \"text\": \"content\",\n    \"hashtags\": [\"tag1\", \"tag2\"],\n    \"character_count\": number\n  },\n  \"instagram\": {\n    \"text\": \"content\",\n    \"hashtags\": [\"tag1\", \"tag2\"],\n    \"character_count\": number\n  }\n}"
              },
              {
                "role": "user",
                "content": "Create social media content for:\n\n**Topic:** {{ $json.topic }}\n**Content Type:** {{ $json.contentType }}\n**Brand Voice:** {{ $json.brandVoice }}\n**Company:** {{ $json.companyName }}\n**Target Audience:** {{ $json.targetAudience }}\n**Keywords:** {{ $json.keywords }}\n**Platforms:** {{ $json.platforms }}"
              }
            ]
          }
        },
        "operation": "create"
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "k1l2m3n4-o5p6-7890-1234-567890klmnop",
      "name": "Process & Schedule Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1600,
        120
      ],
      "parameters": {
        "width": 280,
        "height": 160,
        "content": "\u2705 **Step 4: Process & Schedule**\n\nProcesses AI response and schedules via Buffer:\n- Parses platform-specific content\n- Validates character limits\n- Schedules posts at optimal times\n- Updates spreadsheet status\n- Sends success notifications"
      },
      "typeVersion": 1
    },
    {
      "id": "l2m3n4o5-p6q7-8901-2345-678901lmnopq",
      "name": "Process Generated Content",
      "type": "n8n-nodes-base.code",
      "position": [
        1680,
        260
      ],
      "parameters": {
        "jsCode": "// Process AI content and prepare for scheduling\nconst contentInput = $('Generate Social Content with AI').first();\nconst originalData = $('Filter Today\\'s Content').first();\n\nlet socialContent;\ntry {\n  const aiResponse = contentInput.json.choices[0].message.content;\n  socialContent = JSON.parse(aiResponse);\n} catch (error) {\n  // Fallback content\n  socialContent = {\n    twitter: {\n      text: `Sharing insights about ${originalData.json.topic}! \ud83d\ude80`,\n      hashtags: [\"business\", \"insights\"],\n      character_count: 80\n    },\n    linkedin: {\n      text: `Today let's explore ${originalData.json.topic}. What are your thoughts?`,\n      hashtags: [\"business\", \"leadership\"],\n      character_count: 120\n    },\n    instagram: {\n      text: `\u2728 ${originalData.json.topic} \u2728\\n\\nWhat's your experience? Share below! \ud83d\udc47`,\n      hashtags: [\"business\", \"motivation\"],\n      character_count: 100\n    }\n  };\n}\n\n// Process platforms\nconst requestedPlatforms = originalData.json.platforms.toLowerCase().split(',').map(p => p.trim());\nconst results = [];\n\nrequerestedPlatforms.forEach(platform => {\n  const platformKey = platform === 'twitter' ? 'twitter' : \n                     platform === 'linkedin' ? 'linkedin' : \n                     platform === 'instagram' ? 'instagram' : null;\n  \n  if (platformKey && socialContent[platformKey]) {\n    results.push({\n      json: {\n        platform: platform,\n        content: socialContent[platformKey].text,\n        hashtags: socialContent[platformKey].hashtags || [],\n        topic: originalData.json.topic,\n        row_index: originalData.json.rowIndex,\n        date: originalData.json.date,\n        scheduled_time: new Date().toISOString()\n      }\n    });\n  }\n});\n\nreturn results.length > 0 ? results : [{\n  json: {\n    error: \"No valid platforms found\",\n    topic: originalData.json.topic\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "m3n4o5p6-q7r8-9012-3456-789012mnopqr",
      "name": "Schedule Post via Buffer",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1920,
        260
      ],
      "parameters": {
        "url": "https://api.bufferapp.com/1/updates/create.json",
        "method": "POST",
        "sendBody": true,
        "contentType": "form-urlencoded",
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "text",
              "value": "={{ $json.content }}"
            },
            {
              "name": "profile_ids[]",
              "value": "YOUR_PROFILE_ID_HERE"
            },
            {
              "name": "now",
              "value": "false"
            }
          ]
        },
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/x-www-form-urlencoded"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "n4o5p6q7-r8s9-0123-4567-890123nopqrs",
      "name": "Update Sheet Status",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2160,
        260
      ],
      "parameters": {
        "fieldsUi": {
          "values": [
            {
              "column": "F",
              "fieldValue": "Scheduled"
            },
            {
              "column": "G",
              "fieldValue": "{{ $json.content.substring(0, 100) }}..."
            }
          ]
        },
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $('Configuration Variables').first().json.CONTENT_WORKSHEET }}"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Configuration Variables').first().json.GOOGLE_SHEET_ID }}"
        },
        "valueToMatchOn": "={{ $json.date }}",
        "columnToMatchOn": "A"
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "o5p6q7r8-s9t0-1234-5678-901234opqrst",
      "name": "Setup Instructions",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        240,
        500
      ],
      "parameters": {
        "color": 6,
        "width": 400,
        "height": 320,
        "content": "\u2699\ufe0f **CONFIGURATION REQUIRED**\n\n**Before using:**\n\n1. **Set up credentials:**\n   - OpenAI API key\n   - Google Sheets OAuth2\n   - Buffer API token\n\n2. **Create Google Sheets template:**\n   - Column A: Date (YYYY-MM-DD)\n   - Column B: Topic\n   - Column C: Platforms\n   - Column D: Content Type\n   - Column E: Keywords\n   - Column F: Status\n   - Column G: Generated Content\n\n3. **Update Configuration Variables:**\n   - GOOGLE_SHEET_ID\n   - BRAND_VOICE\n   - COMPANY_NAME\n   - TARGET_AUDIENCE\n\n4. **Configure Buffer:**\n   - Get profile IDs\n   - Update Schedule Post node\n\n5. **Test workflow:**\n   - Add test content\n   - Run manually\n   - Verify posts scheduled"
      },
      "typeVersion": 1
    },
    {
      "id": "p6q7r8s9-t0u1-2345-6789-012345pqrstu",
      "name": "No Content Response",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1200,
        420
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "{\n  \"status\": \"no_content\",\n  \"message\": \"No content scheduled for today\",\n  \"date\": \"{{ $json.date }}\"\n}"
      },
      "typeVersion": 1
    }
  ],
  "settings": {
    "executionOrder": "v1"
  },
  "updatedAt": "2025-01-01T00:00:00.000Z",
  "versionId": "auto-generate",
  "staticData": {},
  "connections": {
    "Read Content Calendar": {
      "main": [
        [
          {
            "node": "Filter Today's Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Today's Content": {
      "main": [
        [
          {
            "node": "Check if Content Exists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if Content Exists": {
      "main": [
        [
          {
            "node": "Generate Social Content with AI",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No Content Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Configuration Variables": {
      "main": [
        [
          {
            "node": "Read Content Calendar",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Post via Buffer": {
      "main": [
        [
          {
            "node": "Update Sheet Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Generated Content": {
      "main": [
        [
          {
            "node": "Schedule Post via Buffer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Social Content with AI": {
      "main": [
        [
          {
            "node": "Process Generated Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Daily Content Generation Trigger": {
      "main": [
        [
          {
            "node": "Configuration Variables",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "triggerCount": 1
}

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.

About this workflow

Generate and schedule social media content across platforms using AI and Google Sheets. Uses stickyNote, googleSheets, openAi, httpRequest. Scheduled trigger; 16 nodes.

Source: https://github.com/ScraperNode/awesome-n8n-templates/blob/main/templates/ai-and-llm/7517-generate-schedule-social-media-content-with-gpt-4-and-buffer-from-google-sheets/workflow.json — original creator credit. Request a take-down →

More General workflows → · Browse all categories →