This workflow corresponds to n8n.io template #15195 — we link there as the canonical source.
This workflow follows the Agent → Google Sheets 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 →
{
"nodes": [
{
"id": "b1f0c9e3-e5f4-4604-bd65-9544500f9e8c",
"name": "Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2352,
-624
],
"parameters": {
"color": 4,
"width": 508,
"height": 1236,
"content": "## Daily Facebook Social Sharing Automation \u2014 Sheets + GPT-4o-mini + Ideogram + Facebook\n\nFor SEO agencies and social media managers who want to publish daily keyword-driven Facebook posts without any manual work. Every morning at 6AM the workflow reads today's scheduled keywords from a Google Sheet \u2014 filtered by day of week \u2014 loops through each one, generates a headline and content using GPT-4o-mini, creates a professional 1280x704 image with Ideogram, posts the photo and caption directly to a Facebook Page, and logs the live URL back to the sheet. A 1-minute wait between posts respects Facebook rate limits.\n\n## How it works\n- **1. Schedule \u2014 Daily 6AM** triggers the workflow every morning automatically\n- **2. Google Sheets \u2014 Read Today Keywords** reads rows where Work Day matches today (Mon, Tue, etc.) to get only today's scheduled content\n- **3. Split \u2014 Loop Over Each Row** processes one keyword row at a time using SplitInBatches\n- **4. AI Agent \u2014 Generate Post Content** uses GPT-4o-mini to write a 6\u20138 word headline, plain text content with max 50-word paragraphs, and an image prompt \u2014 first 250 chars must work as a Twitter summary\n- **7. HTTP \u2014 Generate Image Ideogram** generates a realistic 1280x704 professional image using Ideogram v3 TURBO based on the AI prompt\n- **8. Code \u2014 Prepare Post Data** assembles the final post text as headline + content + landing page link, plus extracts Domain ID for logging\n- **9. HTTP \u2014 Post to Facebook** publishes the photo with caption to the Facebook Page via Graph API v23\n- **10. Google Sheets \u2014 Log Posted URL** appends timestamp, Domain ID, link type, and live URL to the log sheet\n- **11. Wait \u2014 1 Minute Rate Limit** pauses before the next keyword to avoid Facebook rate limiting\n\n## Set up steps\n1. In **2. Google Sheets \u2014 Read Today Keywords** \u2014 connect your Google Sheets credential and set the correct Sheet ID and tab\n2. In **5. OpenAI \u2014 GPT-4o-mini Model** \u2014 connect your OpenAI credential\n3. In **7. HTTP \u2014 Generate Image Ideogram** \u2014 replace REPLACE_WITH_IDEOGRAM_API_KEY with your Ideogram API key\n4. In **9. HTTP \u2014 Post to Facebook** \u2014 replace REPLACE_WITH_FB_PAGE_ACCESS_TOKEN with your Facebook Page access token and update the Page ID in the URL if different\n5. In **10. Google Sheets \u2014 Log Posted URL** \u2014 connect your Google Sheets credential and set the correct log sheet tab\n6. In your Google Sheet \u2014 ensure columns exist: Work Day, Keyword, Landing Page, Title, Content, Critical Instructions, Domain ID"
},
"typeVersion": 1
},
{
"id": "28e247a2-630f-43ca-996c-8de554e10ef4",
"name": "Section \u2014 Daily Schedule, Keyword Sheet Read, and Loop",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1792,
-336
],
"parameters": {
"color": 5,
"width": 676,
"height": 372,
"content": "## Daily Schedule, Keyword Sheet Read, and Loop\nTriggers at 6AM daily. Reads rows from Google Sheets where Work Day matches today's short day name. SplitInBatches loops one row at a time \u2014 when all rows are processed the loop exits cleanly."
},
"typeVersion": 1
},
{
"id": "e614fefd-e8ac-4915-a40d-80eb51a3105e",
"name": "Section \u2014 AI Content Writing and Image Generation",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1088,
-448
],
"parameters": {
"color": 6,
"width": 676,
"height": 884,
"content": "## AI Content Writing and Image Generation\nGPT-4o-mini writes a 6\u20138 word headline, plain text content in max 50-word paragraphs, and an image prompt. The first 250 characters must stand alone as a Twitter summary. Ideogram v3 generates a realistic 1280x704 professional image in TURBO mode."
},
"typeVersion": 1
},
{
"id": "83c4a4f7-f5ff-4dfe-bd10-a08e2b1cafbe",
"name": "Section \u2014 Post Assembly, Facebook Publishing, Logging, and Rate Limit",
"type": "n8n-nodes-base.stickyNote",
"position": [
-336,
-336
],
"parameters": {
"color": 4,
"width": 980,
"height": 372,
"content": "## Post Assembly, Facebook Publishing, Logging, and Rate Limit\nAssembles headline, content, and landing page URL into the final post. Posts the image and caption to the Facebook Page. Logs the live URL and Domain ID to the sheet. Waits 1 minute before the next row to respect Facebook rate limits."
},
"typeVersion": 1
},
{
"id": "ee6f7197-6b0c-49b9-b4a0-469d83eb29eb",
"name": "1. Schedule \u2014 Daily 6AM",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-1728,
-224
],
"parameters": {
"rule": {
"interval": [
{
"triggerAtHour": 6
}
]
}
},
"typeVersion": 1.2
},
{
"id": "cc7d0b91-ab90-4767-adc5-4848c85c0a32",
"name": "2. Google Sheets \u2014 Read Today Keywords",
"type": "n8n-nodes-base.googleSheets",
"position": [
-1504,
-224
],
"parameters": {
"options": {},
"filtersUI": {
"values": [
{
"lookupValue": "={{ new Date().toLocaleDateString('en-US', {weekday: 'short'}) }}",
"lookupColumn": "Work Day"
}
]
},
"sheetName": {
"__rl": true,
"mode": "list",
"value": 356701633
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1JhOvSwfCK8IDdPVRwV532k09Cq5MClOMMYj_8_Qs3zo"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.5
},
{
"id": "cca158d0-7e3d-4f10-97e4-45999109e73d",
"name": "3. Split \u2014 Loop Over Each Row",
"type": "n8n-nodes-base.splitInBatches",
"position": [
-1280,
-224
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "8a8d52ad-657f-41de-8e54-6d9daf2a637f",
"name": "4. AI Agent \u2014 Generate Post Content",
"type": "@n8n/n8n-nodes-langchain.agent",
"onError": "continueRegularOutput",
"position": [
-992,
-208
],
"parameters": {
"text": "=Role: You are a content rewriting specialist. Minimal changes, just reformat for social reposting.\n\nContext:\n- Keyword: {{ $json.Keyword }}\n- Landing Page: {{ $json['Landing Page'] }}\n- Title: {{ $json.Title }}\n- Content: {{ $json.Content }}\n- Critical Instructions: {{ $json['Critical Instructions'] }}\n\nGoal: Create an informational social sharing post with headline that adds value.\n\nRules:\n- Headline: 6-8 words, informational, no special chars like \"*\"\n- Content: plain text, paragraphs of max 50 words, no intro/conclusion, no links\n- First 250 chars (including headline) must stand alone as a Twitter-ready summary\n- Image prompt: realistic, professional, business-appropriate. NO brand logos, NO cyberpunk themes, NO brand references\n- Paragraphs must use real line breaks (\\n\\n between paragraphs)\n\nDo not invent information. Intent must match the source.",
"options": {},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 1.9
},
{
"id": "6ba3b718-f7af-4e3a-bf33-b10a7d331812",
"name": "5. OpenAI \u2014 GPT-4o-mini Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
-992,
272
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "8f9d4dbd-a668-4466-b5f9-98fa37194b18",
"name": "6. Parser \u2014 Structured Post Output",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
-928,
128
],
"parameters": {
"autoFix": true,
"jsonSchemaExample": "{\n \"Headline\": \"\",\n \"Content\": \"\",\n \"image prompt\": \"\"\n}"
},
"typeVersion": 1.3
},
{
"id": "8b98ad28-bb8b-4d80-aa95-226b79136762",
"name": "7. HTTP \u2014 Generate Image Ideogram",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"position": [
-656,
-208
],
"parameters": {
"url": "https://api.ideogram.ai/v1/ideogram-v3/generate",
"method": "POST",
"options": {},
"sendBody": true,
"contentType": "multipart-form-data",
"sendHeaders": true,
"bodyParameters": {
"parameters": [
{
"name": "prompt",
"value": "={{ $json.output['image prompt'] }}"
},
{
"name": "rendering_speed",
"value": "TURBO"
},
{
"name": "resolution",
"value": "1280x704"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "Api-Key",
"value": "REPLACE_WITH_IDEOGRAM_API_KEY"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "e608b995-480c-4076-8bce-27e906b36964",
"name": "8. Code \u2014 Prepare Post Data",
"type": "n8n-nodes-base.code",
"position": [
-240,
-208
],
"parameters": {
"jsCode": "// Combine AI output + image + row data into one clean object\nconst imgResponse = $input.first().json;\nconst imageUrl = imgResponse?.data?.[0]?.url || '';\n\nconst ai = $('4. AI Agent \u2014 Generate Post Content').first().json.output;\nconst row = $('3. Split \u2014 Loop Over Each Row').item.json;\n\nconst headline = ai.Headline || '';\nconst content = ai.Content || '';\nconst landingPage = row['Landing Page'] || '';\nconst domainId = row['Domain ID'] || '';\n\nconst postText = `${headline}\\n\\n${content}\\nRead more: ${landingPage}`;\n\nreturn [{\n json: { headline, content, landingPage, domainId, imageUrl, postText }\n}];"
},
"typeVersion": 2
},
{
"id": "ba5c7d37-91bc-4a11-b267-d480daa01981",
"name": "9. HTTP \u2014 Post to Facebook",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"position": [
-32,
-208
],
"parameters": {
"url": "https://graph.facebook.com/v23.0/628386143694589/photos",
"method": "POST",
"options": {},
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "message",
"value": "={{ $json.postText }}"
},
{
"name": "access_token",
"value": "REPLACE_WITH_FB_PAGE_ACCESS_TOKEN"
},
{
"name": "url",
"value": "={{ $json.imageUrl }}"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "b35a0a36-ee75-44a6-92b7-9d81978faf39",
"name": "10. Google Sheets \u2014 Log Posted URL",
"type": "n8n-nodes-base.googleSheets",
"onError": "continueRegularOutput",
"position": [
208,
-208
],
"parameters": {
"columns": {
"value": {
"Domain ID": "={{ $('8. Code \u2014 Prepare Post Data').item.json.domainId }}",
"Link Type": "Social Sharing Fb",
"Live URLs": "={{ $json.post_id ? 'https://www.facebook.com/' + $json.post_id.split('_')[1] : '' }}",
"Timestamp": "={{ $now.format('MM-DD HH:mm:ss') }}"
},
"schema": [
{
"id": "Timestamp",
"type": "string",
"display": true,
"displayName": "Timestamp"
},
{
"id": "Domain ID",
"type": "string",
"display": true,
"displayName": "Domain ID"
},
{
"id": "Link Type",
"type": "string",
"display": true,
"displayName": "Link Type"
},
{
"id": "Live URLs",
"type": "string",
"display": true,
"displayName": "Live URLs"
}
],
"mappingMode": "defineBelow",
"matchingColumns": []
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 237523545
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1JhOvSwfCK8IDdPVRwV532k09Cq5MClOMMYj_8_Qs3zo"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.5
},
{
"id": "1e3045b1-a93e-4b83-9567-975a93344864",
"name": "11. Wait \u2014 1 Minute Rate Limit",
"type": "n8n-nodes-base.wait",
"position": [
432,
-208
],
"parameters": {
"unit": "minutes",
"amount": 1
},
"typeVersion": 1.1
}
],
"connections": {
"1. Schedule \u2014 Daily 6AM": {
"main": [
[
{
"node": "2. Google Sheets \u2014 Read Today Keywords",
"type": "main",
"index": 0
}
]
]
},
"9. HTTP \u2014 Post to Facebook": {
"main": [
[
{
"node": "10. Google Sheets \u2014 Log Posted URL",
"type": "main",
"index": 0
}
]
]
},
"8. Code \u2014 Prepare Post Data": {
"main": [
[
{
"node": "9. HTTP \u2014 Post to Facebook",
"type": "main",
"index": 0
}
]
]
},
"3. Split \u2014 Loop Over Each Row": {
"main": [
[],
[
{
"node": "4. AI Agent \u2014 Generate Post Content",
"type": "main",
"index": 0
}
]
]
},
"5. OpenAI \u2014 GPT-4o-mini Model": {
"ai_languageModel": [
[
{
"node": "4. AI Agent \u2014 Generate Post Content",
"type": "ai_languageModel",
"index": 0
},
{
"node": "6. Parser \u2014 Structured Post Output",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"11. Wait \u2014 1 Minute Rate Limit": {
"main": [
[
{
"node": "3. Split \u2014 Loop Over Each Row",
"type": "main",
"index": 0
}
]
]
},
"7. HTTP \u2014 Generate Image Ideogram": {
"main": [
[
{
"node": "8. Code \u2014 Prepare Post Data",
"type": "main",
"index": 0
}
]
]
},
"10. Google Sheets \u2014 Log Posted URL": {
"main": [
[
{
"node": "11. Wait \u2014 1 Minute Rate Limit",
"type": "main",
"index": 0
}
]
]
},
"6. Parser \u2014 Structured Post Output": {
"ai_outputParser": [
[
{
"node": "4. AI Agent \u2014 Generate Post Content",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"4. AI Agent \u2014 Generate Post Content": {
"main": [
[
{
"node": "7. HTTP \u2014 Generate Image Ideogram",
"type": "main",
"index": 0
}
]
]
},
"2. Google Sheets \u2014 Read Today Keywords": {
"main": [
[
{
"node": "3. Split \u2014 Loop Over Each Row",
"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.
googleSheetsOAuth2ApiopenAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Set up your keyword schedule once in a Google Sheet and the workflow publishes daily Facebook posts automatically every morning at 6AM. For each keyword scheduled for today, it generates a headline and post content with GPT-4o-mini, creates a professional 1280x704 image with…
Source: https://n8n.io/workflows/15195/ — 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.
This n8n automation workflow automates the creation, scripting, production, and posting of YouTube videos. It leverages AI (OpenAI), image generation (PIAPI), video rendering (Shotstack), and platform
This workflow is designed for: Content creators and marketers E-commerce and product-based businesses Agencies producing social media visuals and videos Automation builders looking for AI-powered crea
Generate product images with NanoBanana Pro to Veo videos and Blotato - vide 2 ok. Uses httpRequest, editImage, googleDrive, googleSheets. Scheduled trigger; 76 nodes.
Created by: Peyton Leveillee Last updated: October 2025
SEO Blog Article Generation Workflow. Uses outputParserStructured, httpRequest, agent, lmChatOpenAi. Scheduled trigger; 56 nodes.