Slack + Google Sheets for approved social posts
You’ve got ideas. You’ve got a brand brief. And somehow you still end up rewriting the same post twice, hunting for the “latest” image, and wondering what actually got approved.
This is where Slack Sheets approval automation pays off. Marketing managers feel it when approvals stall. Agency owners feel it when clients change their mind mid-week. And founders doing their own content? Honestly, they feel it every day.
This workflow turns one intake form into a week of LinkedIn and Facebook posts, routes images for Slack approval, logs everything in Google Sheets, and schedules the final posts once they’re greenlit. You’ll see the flow, the outcomes, and what you need to run it.
How This Automation Works
The full n8n workflow, from trigger to final output:
n8n Workflow Template: Slack + Google Sheets for approved social posts
flowchart LR
subgraph sg0["On form submission Flow"]
direction LR
n0@{ icon: "mdi:robot", form: "rounded", label: "AI Agent2", pos: "b", h: 48 }
n1@{ icon: "mdi:robot", form: "rounded", label: "Structured Output Parser1", pos: "b", h: 48 }
n2@{ icon: "mdi:brain", form: "rounded", label: "OpenRouter Chat Model2", pos: "b", h: 48 }
n3@{ icon: "mdi:brain", form: "rounded", label: "OpenRouter Chat Model3", pos: "b", h: 48 }
n4@{ icon: "mdi:memory", form: "rounded", label: "Simple Memory1", pos: "b", h: 48 }
n5@{ icon: "mdi:cog", form: "rounded", label: "Message a model in Perplexity1", pos: "b", h: 48 }
n6@{ icon: "mdi:wrench", form: "rounded", label: "Think1", pos: "b", h: 48 }
n7@{ icon: "mdi:swap-vertical", form: "rounded", label: "Split Out3", pos: "b", h: 48 }
n8@{ icon: "mdi:swap-vertical", form: "rounded", label: "Edit Fields", pos: "b", h: 48 }
n9["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/form.svg' width='40' height='40' /></div><br/>On form submission"]
n10@{ icon: "mdi:swap-vertical", form: "rounded", label: "Loop Over Items", pos: "b", h: 48 }
n11["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/slack.svg' width='40' height='40' /></div><br/>Send message and wait for re.."]
n12@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Switch7", pos: "b", h: 48 }
n13@{ icon: "mdi:database", form: "rounded", label: "Append or update row in sheet8", pos: "b", h: 48 }
n14["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Edit Image Nano Banana2"]
n15@{ icon: "mdi:cog", form: "rounded", label: "Upload file", pos: "b", h: 48 }
n16["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Download Image File"]
n17["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Download Image 1st"]
n18@{ icon: "mdi:swap-vertical", form: "rounded", label: "Set Original Image URL", pos: "b", h: 48 }
n19@{ icon: "mdi:swap-vertical", form: "rounded", label: "Set Edited Image URL", pos: "b", h: 48 }
n20@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Merge Image Paths", pos: "b", h: 48 }
n21@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Switch", pos: "b", h: 48 }
n22@{ icon: "mdi:swap-vertical", form: "rounded", label: "Loop Over Items1", pos: "b", h: 48 }
n23["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/slack.svg' width='40' height='40' /></div><br/>Send message and wait for re.."]
n24@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Switch8", pos: "b", h: 48 }
n25["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Edit Image Nano Banana"]
n26@{ icon: "mdi:cog", form: "rounded", label: "Upload file1", pos: "b", h: 48 }
n27["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Download Image File1"]
n28@{ icon: "mdi:swap-vertical", form: "rounded", label: "Set Original Image URL1", pos: "b", h: 48 }
n29@{ icon: "mdi:swap-vertical", form: "rounded", label: "Set Edited Image URL1", pos: "b", h: 48 }
n30@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Merge Image Paths1", pos: "b", h: 48 }
n31["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Image Generation"]
n32["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Image Generation 2"]
n33["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Download Image 1st 2"]
n34@{ icon: "mdi:database", form: "rounded", label: "Append or update row in sheet", pos: "b", h: 48 }
n35["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Schedule Post"]
n36["<div style='background:#f5f5f5;padding:10px;border-radius:8px;display:inline-block;border:1px solid #e0e0e0'><img src='https://flowpast.com/wp-content/uploads/n8n-workflow-icons/httprequest.dark.svg' width='40' height='40' /></div><br/>Schedule Post1"]
n21 --> n31
n21 --> n32
n6 -.-> n0
n12 --> n18
n12 --> n14
n24 --> n28
n24 --> n25
n0 --> n7
n7 --> n21
n8 --> n0
n15 --> n13
n26 --> n34
n35 --> n10
n36 --> n22
n4 -.-> n0
n10 --> n11
n31 --> n17
n22 --> n23
n20 --> n16
n20 --> n11
n17 --> n10
n32 --> n33
n30 --> n27
n30 --> n23
n9 --> n8
n16 --> n15
n33 --> n22
n27 --> n26
n19 --> n20
n29 --> n30
n25 --> n29
n2 -.-> n1
n3 -.-> n0
n18 --> n20
n14 --> n19
n28 --> n30
n1 -.-> n0
n34 --> n36
n13 --> n35
n5 -.-> n0
n23 --> n24
n11 --> n12
end
%% Styling
classDef trigger fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
classDef ai fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
classDef aiModel fill:#e8eaf6,stroke:#3f51b5,stroke-width:2px
classDef decision fill:#fff8e1,stroke:#f9a825,stroke-width:2px
classDef database fill:#fce4ec,stroke:#c2185b,stroke-width:2px
classDef api fill:#fff3e0,stroke:#e65100,stroke-width:2px
classDef code fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef disabled stroke-dasharray: 5 5,opacity: 0.5
class n9 trigger
class n0,n1 ai
class n2,n3 aiModel
class n6 ai
class n4 ai
class n12,n20,n21,n24,n30 decision
class n13,n34 database
class n14,n16,n17,n25,n27,n31,n32,n33,n35,n36 api
classDef customIcon fill:none,stroke:none
class n9,n11,n14,n16,n17,n23,n25,n27,n31,n32,n33,n35,n36 customIcon
The Problem: Social content gets stuck in approval limbo
Planning a week of posts should be a focused hour, not a messy back-and-forth scattered across DMs, email threads, and half-updated spreadsheets. But that’s what happens when your “system” is copy-paste plus someone remembering to ask for approvals. You draft the LinkedIn version, then “adapt it” for Facebook, then reformat again when the image doesn’t fit. Next thing you know, it’s Thursday, you’ve posted twice, and you can’t even tell what’s queued versus what’s still waiting on feedback.
It adds up fast. Here’s where it breaks down.
- Approvals live in Slack, but the content calendar lives somewhere else, so nothing stays in sync.
- Platform-specific tweaks happen late, which means last-minute rewrites and weaker consistency.
- Images are the bottleneck because nobody knows which version is final.
- Tracking gets skipped, so you lose the history that makes scaling easier next month.
The Solution: Generate posts, approve in Slack, track in Sheets, then schedule
This n8n workflow acts like a lightweight content ops system that starts with one structured brand brief and ends with scheduled posts on LinkedIn and Facebook. A form submission collects about 10 brand variables (industry, audience, tone, and other essentials). From there, an AI content planning agent generates six distinct posts: three written for LinkedIn’s professional tone and three for Facebook’s more community-driven style. Each post then triggers an image generation path with platform-friendly sizing, and those images are pushed into Slack for human approval using interactive prompts. If someone adds feedback, the workflow sends the instructions back to the image editor, fetches the revised image, and asks for approval again. Once approved, the final asset is uploaded to Google Drive, the details are logged to Google Sheets, and the scheduling request is sent to the publishing API connected to your accounts.
It starts with a single form submission. Then the workflow splits posts by platform, generates and refines images with approval loops in Slack, and stores everything in Drive and Google Sheets. Finally, it schedules each post through the Late (GetLate) API so publishing is consistent without you babysitting it.
What You Get: Automation vs. Results
| What This Workflow Automates | Results You’ll Get |
|---|---|
|
|
Example: What This Looks Like
Say you publish six posts per week across two platforms (LinkedIn and Facebook). Manually, a common routine is about 20 minutes per post to rewrite, format, upload an image, and record it somewhere, which is roughly 2 hours for the week, plus extra time chasing approvals. With this workflow, you submit one brief in a few minutes, let the system generate all six drafts and images, then spend maybe 10 minutes total approving or leaving feedback in Slack. The rest runs in the background, and your Google Sheets tracker updates itself.
What You’ll Need
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- Slack for approval requests and feedback.
- Google Sheets to log content and schedules.
- Google Drive to store approved images.
- OpenRouter API key (get it from your OpenRouter dashboard).
- Replicate API key (get it from your Replicate account settings).
- GetLate (Late) API key (get it from getlate.dev).
Skill level: Intermediate. You’ll connect a few accounts, paste API keys, and update IDs (sheet, folders, Slack channel) without writing code.
Don’t want to set this up yourself? Talk to an automation expert (free 15-minute consultation).
How It Works
A brand brief kicks everything off. Someone fills out your form once (brand name, industry, audience, and a few positioning details), and n8n maps those fields into variables the AI can reliably use.
AI generates the written plan and parses it into clean structure. The content planning agent creates six posts, then the workflow converts the output into predictable JSON so each post can be processed one by one without chaos.
Posts split by platform and get matching images. LinkedIn items go down one path and Facebook items go down another. Each path generates an image, fetches it, and sends an approval message into Slack that asks for either approval or feedback.
Approved assets get stored, logged, then scheduled. Final images upload to Google Drive with organized naming, a Google Sheets row is updated with URLs and timing, and an HTTP request schedules the post via Late for LinkedIn or Facebook.
You can easily modify the number of posts per week or the approval rules based on your needs. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Form Trigger
Start by setting up the intake form that triggers the workflow and captures brand inputs for content planning.
- Add and open Form Submission Trigger.
- Set Form Title to
Company Infromation. - Set Form Description to
Please fill up teh variables below to generate the weekly content.. - In Form Fields, include labels exactly as configured:
BRAND_NAME,INDUSTRY,TARGET_DEMOGRAPHICS,TARGET_LOCATION,PRIMARY_VALUE_PROPOSITION,CUSTOMER_CHALLENGE,DESIRED_OUTCOME,BRAND_VOICE,SPECIFIC_TOPICS_TO_FOCUS, andCOMPANY_WEBSITE.
Step 2: Connect and Map Brand Inputs
Normalize incoming form data so the AI agent can reference consistent variables.
- Open Map Brand Variables and verify each assignment uses the correct expressions.
- Set BRAND_NAME to
{{ $json.BRAND_NAME }}and INDUSTRY to{{ $json.INDUSTRY }}. - Set TARGET_LOCATION to
{{ $json.TARGET_LOCATION }}and BRAND_VOICE to{{ $json.BRAND_VOICE }}. - Confirm SPECIFIC_TOPICS_TO_FOCUS uses
{{ $json.SPECIFIC_TOPICS_TO_FOCUS }}and COMPANY_WEBSITE uses{{ $json.COMPANY_WEBSITE }}.
=COMPANY_WEBSITE — keep it exactly as configured to avoid breaking downstream references.Step 3: Set Up the AI Content Planning Pipeline
Configure the content planner, language models, and parsing tools that generate structured post data.
- Open Content Planning Agent and set Text to the expression:
Execute a month content for {{ $json.BRAND_NAME }} for next week {{ $now.startOf('week').plus({weeks: 1}).toFormat('yyyy-MM-dd') }}. Company Brand Voice and guidelines: {{ $json.BRAND_VOICE }} This is the current time and date: {{ $now }} - Ensure Content Planning Agent has Has Output Parser enabled and is connected to Structured JSON Parser.
- Verify Structured JSON Parser uses Auto Fix and the provided JSON schema example.
- OpenRouter Chat Engine B is the language model for Content Planning Agent — Credential Required: Connect your
openRouterApicredentials. - OpenRouter Chat Engine A is connected as the language model for Structured JSON Parser — Credential Required: Connect your
openRouterApicredentials. - Perplexity Research Tool, Session Memory Buffer, and Reasoning Helper are AI sub-nodes attached to Content Planning Agent — add or verify credentials at the parent agent connection level (not on the sub-nodes).
fieldToSplitOut = output.posts and includes output.campaign_theme; ensure your AI output matches this structure.Step 4: Configure Platform Routing, Image Generation, and Approvals
Split posts by platform, generate images, and route approvals through Slack for optional refinement.
- In Route by Platform, confirm the rules compare
{{ $json['output.posts'].platform }}tofacebookandlinkedin. - For LinkedIn, configure Generate Image B with URL
https://api.replicate.com/v1/models/google/imagen-4-ultra/predictionsand JSON Body using the expression that combinesimage_prompt,style, andoverlay_text. - For Facebook, configure Generate Image A with the same URL and JSON Body template.
- Credential Required: Connect your
httpHeaderAuthcredentials for Generate Image A, Generate Image B, Refine Image via Nano, and Refine Image via Nano B. - Ensure Slack Approval Request A and Slack Approval Request B use Operation =
sendAndWaitwith the approval form fields. - Credential Required: Connect your
slackOAuth2Apicredentials for Slack Approval Request A and Slack Approval Request B. - Confirm Approval Decision A and Approval Decision B check
{{ $json.data.Approval }}forApprovedvsReview. - Validate Set Original Image Link A/B and Set Edited Image Link A/B set final_image_url and image_source, then Choose Image Path A/B routes based on
{{ $json.image_source }}.
Step 5: Configure File Storage, Sheets, and Scheduling Outputs
Upload final images to Drive, update the spreadsheet, and schedule posts with the external API.
- In Drive File Upload A and Drive File Upload B, set Name to
{{ $('Iterate Facebook Items').item.json.id }}-{{ $now.toFormat('hh:mm-ddMMMyyyy').toUpperCase() }}(A) and{{ $('Iterate LinkedIn Items').item.json.id }}-{{ $now.toFormat('hh:mm-ddMMMyyyy').toUpperCase() }}(B). - Credential Required: Connect your
googleDriveOAuth2Apicredentials for Drive File Upload A and Drive File Upload B. - In Update Sheet Row A and Update Sheet Row B, confirm Operation =
appendOrUpdateand map fields such as TEXT to{{ $('Expand Posts List').item.json['output.posts'].post_text }}and DATE to{{ DateTime.fromISO($('Expand Posts List').item.json['output.posts'].posting_date).set({hour: 15, minute: 0, second: 0}).toUTC().toISO({suppressMilliseconds: true}) }}. - Credential Required: Connect your
googleSheetsOAuth2Apicredentials for Update Sheet Row A and Update Sheet Row B. - In Schedule Social Post A and Schedule Social Post B, set URL to
https://getlate.dev/api/v1/postsand JSON Body to the provided payload using{{ $json.TEXT }}and{{ $json.DATE }}. - Credential Required: Connect your
httpHeaderAuthcredentials for Schedule Social Post A and Schedule Social Post B.
==IMAGE("https://drive.google.com/uc?id={{ $json.id }}"). If your sheet doesn’t interpret the extra =, adjust it to a single =.Step 6: Test and Activate Your Workflow
Run a manual test, confirm approvals and outputs, then activate for production.
- Click Execute Workflow and submit a sample entry through Form Submission Trigger.
- Verify Content Planning Agent produces structured output that Structured JSON Parser can parse into
output.posts. - Confirm images are generated via Generate Image A/Generate Image B, approvals flow through Slack Approval Request A/Slack Approval Request B, and the correct image path is chosen in Choose Image Path A/Choose Image Path B.
- Check that files appear in Google Drive from Drive File Upload A/Drive File Upload B, sheet rows update via Update Sheet Row A/Update Sheet Row B, and posts are scheduled by Schedule Social Post A/Schedule Social Post B.
- Once successful, toggle Active to enable ongoing form-triggered execution.
Common Gotchas
- Slack credentials can expire or need specific permissions. If things break, check the n8n Credentials panel and your Slack app’s OAuth scopes first.
- If you’re using Wait nodes or external rendering, processing times vary. Bump up the wait duration if downstream nodes fail on empty responses.
- Google Drive uploads can fail if the folder ID is wrong or the connected account lacks access. Confirm the folder is shared with the same Google identity used in n8n.
Frequently Asked Questions
About an hour if your accounts and keys are ready.
No. You will mostly connect accounts and paste a few IDs and API keys.
Yes. n8n has a free self-hosted option and a free trial on n8n Cloud. Cloud plans start at $20/month for higher volume. You’ll also need to factor in OpenRouter, Replicate, and GetLate API usage costs.
Two options: n8n Cloud (managed, easiest setup) or self-hosting on a VPS. For self-hosting, Hostinger VPS is affordable and handles n8n well. Self-hosting gives you unlimited executions but requires basic server management.
Yes, and it’s straightforward. Change the prompt in the Content Planning Agent to generate more or fewer posts, then make sure the Split/iteration nodes (Expand Posts List and the platform batch loops) are aligned with the new output. Many teams also customize the Slack approval message fields, the Google Drive naming convention, and the scheduling logic (dates, cadence, timezone). If you only want LinkedIn or only Facebook, you can disable the other platform route in the Route by Platform switch.
Usually it’s expired OAuth or missing bot scopes. Reconnect the Slack credential in n8n, confirm the app is installed in the right workspace, and verify it can post to the chosen channel. If you’re using interactive approvals, also make sure your Slack app settings allow interactivity for the same request URL.
It can handle a week of posts per brand brief comfortably, and scaling mostly depends on your n8n execution limits and how fast your AI image generation returns.
Often, yes, if you want the full loop: generate content, split by platform, wait for Slack approval, optionally revise images, then schedule and log everything. That kind of branching can get awkward (and expensive) in tools priced per step. n8n also gives you the self-hosting option, which matters when you start running lots of approvals and iterations. Zapier or Make can still be a fine pick for a simple “draft to Slack” pipeline, especially if you don’t care about storing assets in Drive or updating a Sheets tracker. If you’re on the fence, Talk to an automation expert and describe your volume and approval needs.
Once this is running, content production stops being a weekly scramble. The workflow handles the repetitive approvals, file handling, and tracking so you can focus on the message.
Need Help Setting This Up?
Our automation experts can build and customize this workflow for your specific needs. Free 15-minute consultation—no commitment required.