This workflow corresponds to n8n.io template #10551 — we link there as the canonical source.
This workflow follows the Emailsend → 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 →
{
"id": "BO9g2SCjZIC8telE",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Auto-Publish Meta Posts from Google Sheets with Slack & Email Alerts",
"tags": [],
"nodes": [
{
"id": "f0c752c3-2396-4c36-8300-e124323d4410",
"name": "Workflow Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2000,
-928
],
"parameters": {
"width": 498,
"height": 608,
"content": "## \ud83d\udccb Auto-Publish Meta Posts\n\n### How it works\nThis workflow automatically posts new content from a Google Sheet to your Facebook Page and notifies your team when it succeeds or fails. It checks the sheet every minute for rows marked \u201cpending.\u201d When one is found, it extracts the caption and image URL, posts to Facebook via the Graph API, and then sends Slack and email notifications. The workflow also updates the Google Sheet status to \u201cCompleted\u201d once a post is published, keeping everything organized and preventing duplicates.\n\n### Setup steps\n1. Connect your Google Sheets, Facebook Graph API, Slack, and Email (SMTP or Outlook) credentials.\n2. In Google Sheets, create a table with columns: `post_id`, `caption`, `image_url`, and `status`.\n3. Enter one or more pending posts with `status = pending`.\n4. Configure your Facebook Page ID and access token (use credentials, not hard-coded tokens).\n5. Adjust Slack channel, email addresses, or poll frequency if needed.\n6. Run once manually to verify posting works end-to-end.\n7. Once verified, enable the workflow \u2014 it will publish automatically whenever new rows appear.\n"
},
"typeVersion": 1
},
{
"id": "fcad0e1d-2523-492b-8c4e-8f77813fbe22",
"name": "Sheets Setup",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1984,
-288
],
"parameters": {
"color": 2,
"width": 624,
"height": 410,
"content": "## Input & Filtering \n\n\nChecks the Google Sheet every minute and filters for rows where `status = pending`. \nThe Code node ensures only the latest pending row is used. \nThen the data is extracted for posting (caption + image URL).\n"
},
"typeVersion": 1
},
{
"id": "998b413e-7413-4f7f-af7c-aedcdc5f700c",
"name": "Success Check",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1328,
-336
],
"parameters": {
"color": 2,
"width": 432,
"height": 454,
"content": "## Meta Publishing \n\n\nPublishes the image and caption to your Facebook Page using the Graph API. \nAfter posting, the IF node checks if a valid Post ID exists to confirm success before continuing.\n"
},
"typeVersion": 1
},
{
"id": "27171806-46fd-4889-a044-85766c8269a1",
"name": "Success Notifications",
"type": "n8n-nodes-base.stickyNote",
"position": [
-864,
-592
],
"parameters": {
"color": 2,
"width": 480,
"height": 598,
"content": "## Success Notifications & Sheet Update \n\n\nIf the post succeeds, sends a Slack and Outlook/Email confirmation with caption, image, and post ID. \nFinally, updates the Google Sheet to mark the post as \u201cCompleted.\u201d\n"
},
"typeVersion": 1
},
{
"id": "9d764a80-d3ff-4d41-a074-405faac0100c",
"name": "Error Notifications",
"type": "n8n-nodes-base.stickyNote",
"position": [
-864,
16
],
"parameters": {
"color": 2,
"width": 448,
"height": 422,
"content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Error Handling \n\n\nIf posting fails, sends a Slack and email alert containing the error message, caption, and image URL. \nHelps you quickly spot and fix issues with credentials or image links.\n"
},
"typeVersion": 1
},
{
"id": "bd4e17ad-641d-471b-ba10-60e4eb66396b",
"name": "rigger \u2013 Fetch Pending Posts (Google Sheets)",
"type": "n8n-nodes-base.googleSheetsTrigger",
"position": [
-1936,
-48
],
"parameters": {
"options": {},
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "",
"cachedResultUrl": "",
"cachedResultName": ""
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "="
}
},
"credentials": {
"googleSheetsTriggerOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "46269dca-9c92-4ffb-8aae-638200b11e67",
"name": "Filter Pending Posts (Code Node)",
"type": "n8n-nodes-base.code",
"position": [
-1712,
-48
],
"parameters": {
"jsCode": "// n8n Code Node\n// Purpose: Get the last row with status = \"pending\" from Google Sheets input data\n\n// Get input data from previous node\nconst data = $input.all().map(item => item.json);\n\n// Filter to only \"pending\" posts\nconst pendingRows = data.filter(item => item.status === \"pending\");\n\n// If no pending rows, return an error message\nif (pendingRows.length === 0) {\n return [{ message: \"No pending rows found\" }];\n}\n\n// Get the last pending row (highest row_number)\nconst lastRow = pendingRows.reduce((latest, current) => {\n return current.row_number > latest.row_number ? current : latest;\n});\n\n// Return the last pending row\nreturn [{ json: lastRow }];\n"
},
"typeVersion": 2
},
{
"id": "866cf0cb-bf26-48d7-9d07-efa7503b94a4",
"name": "Prepare Post Data",
"type": "n8n-nodes-base.set",
"position": [
-1488,
-48
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "caption-field",
"name": "caption",
"type": "string",
"value": "={{ $json.caption }}"
},
{
"id": "image-url-field",
"name": "image_url",
"type": "string",
"value": "={{ $json.image_url }}"
},
{
"id": "2c98f6f8-b7cf-4235-8080-e3915f8319e8",
"name": "status",
"type": "string",
"value": "={{ $json.status }}"
}
]
}
},
"typeVersion": 3.3
},
{
"id": "46abb3e3-ee59-403e-b863-c9b927aaf628",
"name": "Publish Post to Meta (Facebook Graph API)",
"type": "n8n-nodes-base.facebookGraphApi",
"position": [
-1264,
-48
],
"parameters": {
"edge": "photos",
"options": {
"queryParameters": {
"parameter": [
{
"name": "url",
"value": "={{ $json.image_url }}"
},
{
"name": "caption",
"value": "={{ $json.caption }}"
},
{
"name": "access_token",
"value": "="
}
]
}
},
"graphApiVersion": "v23.0",
"httpRequestMethod": "POST"
},
"credentials": {
"facebookGraphApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "291b95ed-08b5-4fa1-a540-077a411d0ba6",
"name": "Check Publish Success",
"type": "n8n-nodes-base.if",
"position": [
-1040,
-48
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "success-condition",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{ $json.post_id }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2
},
{
"id": "c882a92b-b4a3-49c5-b65b-916f2be96537",
"name": "Notify Success in Slack",
"type": "n8n-nodes-base.slack",
"position": [
-816,
-336
],
"parameters": {
"text": "=\u2705 Post successfully published to Meta!\n\nCaption: {{ $('Prepare Post Data').item.json.caption }}\nImage: {{ $('Prepare Post Data').item.json.image_url }}\nPost ID: {{ $json.id }}",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "id",
"value": "="
},
"otherOptions": {}
},
"credentials": {
"slackApi": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "aabd920d-ed41-4511-b722-411ee82d653c",
"name": "Send Success Email (Outlook/SMTP)",
"type": "n8n-nodes-base.microsoftOutlook",
"position": [
-816,
-144
],
"parameters": {
"subject": "\u2705 Meta Post Published Successfully",
"bodyContent": "=\u2705 <b>Post successfully published to Facebook Page!</b><br><br>\n<b>Caption:</b> {{ $('Prepare Post Data').item.json.caption }}<br>\n<b>Image URL:</b> <a href=\"{{ $('Prepare Post Data').item.json.image_url }}\">{{ $('Prepare Post Data').item.json.image_url }}</a><br>\n<b>Post ID:</b> {{ $json.id }}<br><br>\n\ud83d\udd52 Posted via n8n automation workflow.\n",
"additionalFields": {
"bodyContentType": "html"
}
},
"credentials": {
"microsoftOutlookOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "6be47779-6759-4f2b-96e1-3973f21292a9",
"name": "Update Post Status in Google Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
-592,
-336
],
"parameters": {
"columns": {
"value": {
"status": "Completed",
"post_id": "={{ $('Filter Pending Posts (Code Node)').item.json.post_id }}"
},
"schema": [
{
"id": "post_id",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "post_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "caption",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "caption",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "image_url",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "image_url",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "status",
"type": "string",
"display": true,
"required": false,
"displayName": "status",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"post_id"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "id",
"value": "="
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "="
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "079b3340-1229-49b3-ae92-0d0e0a760383",
"name": "Notify Failure in Slack",
"type": "n8n-nodes-base.slack",
"position": [
-816,
48
],
"parameters": {
"text": "=\u274c Failed to publish post to Meta!\n\nCaption: {{ $('Prepare Post Data').item.json.caption }}\nImage: {{ $('Prepare Post Data').item.json.image_url }}\nError: {{ $json.error.message || $json.message || 'Unknown error' }}",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "id",
"value": "="
},
"otherOptions": {},
"authentication": "oAuth2"
},
"credentials": {
"slackOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "03740964-7291-4b80-85d5-37baad0d38e6",
"name": "Send Failure Email",
"type": "n8n-nodes-base.emailSend",
"position": [
-608,
64
],
"parameters": {
"options": {},
"subject": "\u274c Meta Post Failed"
},
"credentials": {
"smtp": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "fb6c4ed8-0291-494f-b4b7-d31ac555e81d",
"connections": {
"Prepare Post Data": {
"main": [
[
{
"node": "Publish Post to Meta (Facebook Graph API)",
"type": "main",
"index": 0
}
]
]
},
"Check Publish Success": {
"main": [
[
{
"node": "Notify Success in Slack",
"type": "main",
"index": 0
},
{
"node": "Send Success Email (Outlook/SMTP)",
"type": "main",
"index": 0
}
],
[
{
"node": "Notify Failure in Slack",
"type": "main",
"index": 0
},
{
"node": "Send Failure Email",
"type": "main",
"index": 0
}
]
]
},
"Notify Success in Slack": {
"main": [
[
{
"node": "Update Post Status in Google Sheet",
"type": "main",
"index": 0
}
]
]
},
"Filter Pending Posts (Code Node)": {
"main": [
[
{
"node": "Prepare Post Data",
"type": "main",
"index": 0
}
]
]
},
"Publish Post to Meta (Facebook Graph API)": {
"main": [
[
{
"node": "Check Publish Success",
"type": "main",
"index": 0
}
]
]
},
"rigger \u2013 Fetch Pending Posts (Google Sheets)": {
"main": [
[
{
"node": "Filter Pending Posts (Code Node)",
"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.
facebookGraphApigoogleSheetsOAuth2ApigoogleSheetsTriggerOAuth2ApimicrosoftOutlookOAuth2ApislackApislackOAuth2Apismtp
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Simplify your social media publishing process by automating post scheduling from Google Sheets directly to Meta (Facebook Pages). 📅💬 This workflow detects pending posts, uploads images with captions to your Facebook Page, updates the sheet status, and sends real-time…
Source: https://n8n.io/workflows/10551/ — 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.
Hiring teams often struggle with document follow-ups, offer letter generation, and stakeholder communication. Manual checks, email back-and-forth, and missing files slow down hiring and create chaos d
This workflow creates PDF certificates using Stencil, stores them in Google Drive, and emails them to participants. A new row is added to the Google Sheets document (via form, webhook, or manual entry
This template is ideal for HR teams, startup founders, operations leads, remote-first companies, and freelancers managing onboarding manually or across multiple tools.
Categories: Payments, Project Operations, Client Onboarding
Automatically processes new orders added to Google Sheets. Small orders are approved instantly; large orders trigger an HTML email with one-click Approve / Reject links — each handled by an independen