This workflow follows the Google Sheets → 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 →
{
"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.
googleSheetsOAuth2ApihttpHeaderAuthopenAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
How this works
This workflow automates the creation and posting of engaging social media content across multiple platforms, saving hours of manual effort for busy marketers and content creators. It leverages AI to generate tailored posts based on your content calendar stored in Google Sheets, ensuring consistent and relevant messaging without the need for constant brainstorming. The key step involves OpenAI analysing the calendar to produce optimised text, which is then scheduled and distributed via HTTP requests to platforms like Twitter or LinkedIn, streamlining your entire publishing process.
Use this workflow when managing a regular social media schedule with predefined themes in Google Sheets, particularly for teams handling daily or weekly posts across several channels. Avoid it for one-off campaigns or highly customised content requiring human oversight, as the AI outputs may need review for brand voice accuracy. Common variations include adding image generation nodes for visual posts or integrating with email alerts for approval before scheduling.
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 →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Create and publish Instagram carousels using OpenAI gpt-image-1 and AI caption. Uses chainLlm, outputParserItemList, lmChatOpenAi, splitInBatches. Scheduled trigger; 32 nodes.
17 - AI LinkedIn Responder. Uses httpRequest, openAi, stickyNote, scheduleTrigger. Scheduled trigger; 13 nodes.
AI Story Generator. Uses chatTrigger, httpRequest, openAi, googleSheets. Chat trigger; 14 nodes.
RoboNuggets - Faceless POV AI Machine (R24). Uses scheduleTrigger, googleSheets, chainLlm, lmChatOpenAi. Scheduled trigger; 31 nodes.
Video Automation (images only). Uses chainLlm, lmChatOpenAi, outputParserStructured, splitOut. Scheduled trigger; 28 nodes.