Google Docs to LinkedIn, approved posts ready to publish
Your “final” LinkedIn post is never final. It’s scattered notes in a doc, a half-edited draft in someone’s inbox, and a last-minute rewrite because the tone feels off.
If you run content for a brand, marketing managers feel this weekly. Founders doing their own posting get pulled into it too. And agencies managing multiple voices? Docs LinkedIn automation becomes the difference between shipping and stalling.
This n8n workflow turns your Google Docs guidelines into LinkedIn-ready posts, routes drafts through Gmail approval, then publishes and archives everything cleanly. You’ll see how it works, what you need, and where teams usually trip up.
How This Automation Works
The full n8n workflow, from trigger to final output:
n8n Workflow Template: Google Docs to LinkedIn, approved posts ready to publish
flowchart LR
subgraph sg0["When chat message received Flow"]
direction LR
n0@{ icon: "mdi:play-circle", form: "rounded", label: "When chat message received", pos: "b", h: 48 }
n1@{ icon: "mdi:wrench", form: "rounded", label: "X-Twiter", pos: "b", h: 48 }
n2@{ icon: "mdi:wrench", form: "rounded", label: "Instagram", pos: "b", h: 48 }
n3@{ icon: "mdi:memory", form: "rounded", label: "Window Buffer Memory", pos: "b", h: 48 }
n5@{ icon: "mdi:wrench", form: "rounded", label: "Facebook", pos: "b", h: 48 }
n6@{ icon: "mdi:wrench", form: "rounded", label: "LinkedIn", pos: "b", h: 48 }
n7@{ icon: "mdi:wrench", form: "rounded", label: "Short", pos: "b", h: 48 }
n8@{ icon: "mdi:wrench", form: "rounded", label: "YouTube Short", pos: "b", h: 48 }
n15["<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/>Instagram Image"]
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/x.dark.svg' width='40' height='40' /></div><br/>X Post"]
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/facebook.svg' width='40' height='40' /></div><br/>Instragram Post"]
n18["<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/facebook.svg' width='40' height='40' /></div><br/>Facebook Post"]
n19["<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/linkedin.svg' width='40' height='40' /></div><br/>LinkedIn Post"]
n20@{ icon: "mdi:message-outline", form: "rounded", label: "Gmail User for Approval", pos: "b", h: 48 }
n21["<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/>Get Social Post Image"]
n22@{ icon: "mdi:brain", form: "rounded", label: "gpt-40-mini1", pos: "b", h: 48 }
n40@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Social Media Publishing Router", pos: "b", h: 48 }
n41@{ icon: "mdi:robot", form: "rounded", label: "Prepare Email Contents", pos: "b", h: 48 }
n42@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Is Approved?", pos: "b", h: 48 }
n43@{ icon: "mdi:swap-vertical", form: "rounded", label: "File Id", pos: "b", h: 48 }
n44@{ icon: "mdi:cog", form: "rounded", label: "Get Social Post from Google ..", pos: "b", h: 48 }
n45@{ icon: "mdi:cog", form: "rounded", label: "Extract as JSON", pos: "b", h: 48 }
n46["<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/merge.svg' width='40' height='40' /></div><br/>Merge Image and Post Contents"]
n47@{ icon: "mdi:cog", form: "rounded", label: "Implement Threads Here", pos: "b", h: 48 }
n48@{ icon: "mdi:cog", form: "rounded", label: "Implement YouTube Shorts Here", pos: "b", h: 48 }
n49@{ icon: "mdi:swap-vertical", form: "rounded", label: "X Response", pos: "b", h: 48 }
n50@{ icon: "mdi:swap-vertical", form: "rounded", label: "Instagram Response", pos: "b", h: 48 }
n51@{ icon: "mdi:swap-vertical", form: "rounded", label: "Facebook Response", pos: "b", h: 48 }
n52@{ icon: "mdi:swap-vertical", form: "rounded", label: "LinkedIn Response", pos: "b", h: 48 }
n53@{ icon: "mdi:robot", form: "rounded", label: "🤖Social Media Router Agent", pos: "b", h: 48 }
n56@{ icon: "mdi:brain", form: "rounded", label: "gpt-4o", pos: "b", h: 48 }
n7 -.-> n53
n16 --> n49
n56 -.-> n53
n43 --> n44
n5 -.-> n53
n6 -.-> n53
n1 -.-> n53
n2 -.-> n53
n42 --> n21
n22 -.-> n41
n18 --> n51
n19 --> n52
n8 -.-> n53
n45 --> n46
n45 --> n41
n15 --> n17
n17 --> n50
n3 -.-> n53
n21 --> n46
n41 --> n20
n20 --> n42
n0 --> n53
n46 --> n40
n53 --> n43
n40 --> n16
n40 --> n15
n40 --> n18
n40 --> n19
n40 --> n47
n40 --> n48
n44 --> n45
end
subgraph sg1["When Executed by Another Workflow Flow"]
direction LR
n4@{ icon: "mdi:play-circle", form: "rounded", label: "When Executed by Another Wor..", 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/httprequest.dark.svg' width='40' height='40' /></div><br/>pollinations.ai1"]
n10["<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/>Save Image to imgbb.com"]
n11@{ icon: "mdi:message-outline", form: "rounded", label: "Gmail", pos: "b", h: 48 }
n12@{ icon: "mdi:cog", form: "rounded", label: "Social Media Schema", pos: "b", h: 48 }
n13@{ icon: "mdi:cog", form: "rounded", label: "Social Media System Prompt", pos: "b", h: 48 }
n14@{ icon: "mdi:brain", form: "rounded", label: "gpt-40-mini", pos: "b", h: 48 }
n23@{ icon: "mdi:brain", form: "rounded", label: "gpt-4o-mini", pos: "b", h: 48 }
n24@{ icon: "mdi:swap-vertical", form: "rounded", label: "Schema", pos: "b", h: 48 }
n25@{ icon: "mdi:swap-vertical", form: "rounded", label: "System Prompt", pos: "b", h: 48 }
n26["<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/code.svg' width='40' height='40' /></div><br/>Parse Schema"]
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/code.svg' width='40' height='40' /></div><br/>Parse System Prompt"]
n28@{ icon: "mdi:swap-vertical", form: "rounded", label: "Compose Prompt & Schema", pos: "b", h: 48 }
n29@{ icon: "mdi:robot", form: "rounded", label: "Social Media Content Creator", pos: "b", h: 48 }
n30["<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/merge.svg' width='40' height='40' /></div><br/>Merge Prompts and Schema"]
n31@{ icon: "mdi:swap-vertical", form: "rounded", label: "Social Content", pos: "b", h: 48 }
n32@{ icon: "mdi:cog", form: "rounded", label: "Save Image to Google Drive", pos: "b", h: 48 }
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/merge.svg' width='40' height='40' /></div><br/>Merge"]
n34@{ icon: "mdi:cog", form: "rounded", label: "Save Social Post to Google D..", pos: "b", h: 48 }
n35@{ icon: "mdi:swap-vertical", form: "rounded", label: "Google Drive Image Meta", pos: "b", h: 48 }
n36@{ icon: "mdi:swap-vertical", form: "rounded", label: "Social Post JSON", pos: "b", h: 48 }
n37@{ icon: "mdi:swap-vertical", form: "rounded", label: "Respond with Google Drive Id", pos: "b", h: 48 }
n38["<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/telegram.svg' width='40' height='40' /></div><br/>Telegram Success Message (Op.."]
n39["<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/telegram.svg' width='40' height='40' /></div><br/>Telegram Error Message (Opti.."]
n54@{ icon: "mdi:wrench", form: "rounded", label: "SerpAPI", pos: "b", h: 48 }
n55@{ icon: "mdi:robot", form: "rounded", label: "Prepare Social Media Email C..", pos: "b", h: 48 }
n33 --> n55
n33 --> n35
n24 --> n26
n54 -.-> n29
n14 -.-> n55
n23 -.-> n29
n26 --> n30
n25 --> n27
n31 --> n9
n36 --> n34
n9 --> n38
n9 --> n10
n9 --> n32
n9 --> n33
n9 --> n39
n27 --> n30
n12 --> n24
n28 --> n29
n35 --> n36
n10 --> n33
n30 --> n28
n32 --> n33
n13 --> n25
n29 --> n31
n34 --> n37
n4 --> n13
n4 --> n12
n4 --> n30
n55 --> n11
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 n0,n4 trigger
class n41,n53,n29,n55 ai
class n22,n56,n14,n23 aiModel
class n1,n2,n5,n6,n7,n8,n54 ai
class n3 ai
class n40,n42 decision
class n15,n17,n18,n21,n9,n10 api
class n26,n27 code
classDef customIcon fill:none,stroke:none
class n15,n16,n17,n18,n19,n21,n46,n9,n10,n26,n27,n30,n33,n38,n39 customIcon
The Problem: LinkedIn Drafts Drift Off-Brand
Most teams don’t struggle to “write a post.” They struggle to write the right post, consistently, while approvals drag on. Brand rules live in a Google Doc, but the draft gets created somewhere else. Someone paraphrases the guidelines from memory, a reviewer asks for “more punch,” and suddenly you’re in round three with no clear source of truth. Multiply that by a few posts a week and it quietly eats about 2 hours you thought you’d spend on strategy, not rewriting intros and fixing tone.
It adds up fast. Here’s where it breaks down in real life:
- Guidelines and schemas sit in Google Docs, but writers still guess what “on brand” means on Tuesday afternoon.
- Approvals happen in email threads that don’t match the final post, so you can’t tell what was actually approved.
- Publishing is manual, which means missed windows and “we’ll post it tomorrow” more often than you’d like.
- There’s no reliable archive of the final copy and asset, so repurposing later becomes another scavenger hunt.
The Solution: Google Docs Rules In, Approved LinkedIn Posts Out
This workflow runs like a small content factory inside n8n. It starts with a prompt (your post idea) and immediately pulls your system prompt and platform schema from Google Docs, so the “rules” are always current and shared. Then an AI agent generates a LinkedIn-optimized draft using those guidelines, with optional web research via SerpAPI when you need fact-checking or fresher context. It can also generate a matching image, upload it for hosting, and save the assets to Google Drive. Before anything publishes, the draft gets sent through Gmail for approval, and only then does the workflow post to LinkedIn and log the outcome.
The workflow kicks off on a schedule or a chat-style trigger, routes the request to the right platform, and composes a dynamic prompt from your Google Docs. After content and assets are generated, Gmail becomes the gatekeeper. Approved posts publish to LinkedIn, and the final JSON plus image get archived to Drive for traceability and reuse.
What You Get: Automation vs. Results
| What This Workflow Automates | Results You’ll Get |
|---|---|
|
|
Example: What This Looks Like
Say you publish 3 LinkedIn posts per week and each one takes about 40 minutes of “process” work: pulling brand rules, rewriting to fit tone, sending a draft, chasing approval, and formatting for LinkedIn. That’s roughly 2 hours weekly before you even count new ideas. With this workflow, you drop the idea once, wait for the draft and image to generate (often around 10–20 minutes), then approve from Gmail. The human time becomes closer to 10 minutes per post, not 40.
What You’ll Need
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- Google Docs to store your system prompt and schema.
- Gmail to send and capture approvals.
- LinkedIn to publish approved posts.
- Google Drive to archive final copy and images.
- OpenAI API key (get it from your OpenAI dashboard).
- SerpAPI key (get it from your SerpAPI account) for research.
- ImgBB API key (get it from imgbb.com API settings) for image hosting.
Skill level: Intermediate. You’ll mostly connect accounts and paste IDs/keys, but you should be comfortable testing runs and reading execution logs.
Don’t want to set this up yourself? Talk to an automation expert (free 15-minute consultation).
How It Works
A prompt kicks things off. A schedule trigger can run this on a cadence, or you can start it from a chat-style message when you want a new draft on demand.
Google Docs becomes the source of truth. The workflow fetches two Docs: your system prompt (brand voice, rules, examples) and your platform schema (the required output format for LinkedIn and other channels). It parses those Docs and assembles a “fresh” instruction set every run.
AI generates the draft and optional research. The content agent writes the post using your rules, and it can call a web search tool (SerpAPI) to sanity-check claims or add timely context. This is where your brand consistency is won or lost, so the prompt quality matters.
Approval, publishing, and archiving happen automatically. A Gmail approval email is sent, the workflow waits for the decision, and an “approved” path routes to the LinkedIn publish node. At the same time, the final post JSON plus the image file get saved in Google Drive so you always know what shipped.
You can easily modify the approval rules to support multiple reviewers or stricter checks based on your needs. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Chat Trigger
Set up the entry point so chat input can drive the platform routing and content creation.
- Add the Chat Message Trigger node and keep default options.
- Connect Chat Message Trigger to 🤖Platform Router Agent as shown in the workflow.
- Ensure Windowed Chat Memory is connected as memory to 🤖Platform Router Agent (AI memory connection).
$json.chatInput, which is referenced by 🤖Platform Router Agent.Step 2: Configure AI Routing and Tooling
Route the chat prompt to the correct platform tool and prepare the AI context for generation.
- Open 🤖Platform Router Agent and verify the Text field includes
User prompt: {{ $json.chatInput }}. - Connect GPT Router Model as the language model for 🤖Platform Router Agent. Credential Required: Connect your openAiApi credentials.
- Attach the tool workflows: X/Twitter Tool, Instagram Tool, Facebook Tool, LinkedIn Tool, Threads Tool, and YouTube Shorts Tool to 🤖Platform Router Agent via AI Tool connections.
- For each tool workflow, confirm the route field is set to the correct value (e.g.,
=xtwitter,=instagram,=facebook,=linkedin,=threads,=youtube_short).
Step 3: Connect Prompt Sources and Parse Configuration
Load system instructions and platform schemas from Google Docs, then parse them to build the prompt payload.
- Configure Triggered by Sub-Workflow with inputs user_prompt and route.
- In Fetch Social Schema Doc, set Document URL to
=[YOUR_ID]. Credential Required: Connect your googleDocsOAuth2Api credentials. - In Fetch System Prompt Doc, set Document URL to
=[YOUR_ID]. Credential Required: Connect your googleDocsOAuth2Api credentials. - Confirm Assign Schema Fields maps schema to
{{$json.content}}and platform to{{$('Triggered by Sub-Workflow').item.json.route}}. - Confirm Assign System Prompt maps system_prompt to
{{$json.content}}. - Verify parsing nodes: Assign Schema Fields → Parse Schema XML and Assign System Prompt → Parse Prompt XML.
- Ensure Combine Prompt Inputs is set to Mode
combineand Combine BycombineByPositionwith Number of Inputs3.
Step 4: Configure AI Content Generation
Assemble prompt data and generate platform-specific social content with the AI agent and web search tool.
- In Assemble Prompt Data, verify it maps route, user prompt, system config, and schema objects using expressions like
{{$json.system_config.system}}and{{$json.schema}}. - Connect GPT Content Model as the language model for Social Content Agent. Credential Required: Connect your openAiApi credentials.
- Attach Web Search Tool to Social Content Agent as an AI tool. Credential Required: Connect your serpApi credentials. Add credentials to the Web Search Tool node (not the agent).
- Confirm Social Content Agent text includes
Social Media Platform: {{ $json.route }}andUser Prompt: {{ $json.user_prompt }}. - Set Store Social Output to capture output as
{{$json.output}}.
Step 5: Generate and Store Media Assets
Generate an image, upload it, and store metadata and content to Google Drive for approvals and publishing.
- In Image Generation Request, set URL to
=https://image.pollinations.ai/prompt/{{ $json.output.common_schema.image_suggestion.replaceAll(' ','-').replaceAll(',','').replaceAll('.','').slice(0,100) }}. - Configure Upload Image to ImgBB with URL
https://api.imgbb.com/1/upload, MethodPOST, and Content Typemultipart-form-data. Use query parameterkey={{ $env.IMGBB_API_KEY}}. - In Save Image to Drive, set Name to
{{$json.output.root_schema.name.replaceAll(' ','-').replaceAll(',','').replaceAll('.','')}}, and choose your Drive and Folder IDs. Credential Required: Connect your googleDriveOAuth2Api credentials. - Ensure Merge Assets combines the outputs with Mode
combine, Combine BycombineByPosition, and Number of Inputs3. - Verify Drive Image Metadata maps thumbnailLink, webViewLink, and webContentLink from the Drive file output.
- In Build Post JSON, ensure response is set to the full JSON object using
{ "route": "{{ $('Triggered by Sub-Workflow').item.json.route }}", "social_image": {{ $('Merge Assets').item.json.data.toJsonString() }}, "social_content": {{ $('Store Social Output').item.json.output.toJsonString() }}, "google_drive_image": {{ $json.toJsonString() }} }. - Configure Archive Post to Drive with Operation
createFromText, Name{{$json.response.google_drive_image.id}}, and Content{{$json.response.toJsonString()}}. Credential Required: Connect your googleDriveOAuth2Api credentials.
Step 6: Configure Approval Email and Routing for Publishing
Create approval emails, wait for approval, then route the approved content to the correct platform publishing action.
- In Parse JSON File, set Operation to
fromJson, then ensure it splits to both Combine Image and Post and Prepare Approval Email in parallel. - Connect Mini GPT for Email as the language model to Prepare Approval Email. Credential Required: Connect your openAiApi credentials.
- In Gmail Approval Request, set Operation to
sendAndWait, Subject to=🔥FOR APPROVAL🔥 {{$('Parse JSON File').item.json.data.social_content.root_schema.name }}, and Send To to{{$env.TELEGRAM_CHAT_ID}}. Credential Required: Connect your gmailOAuth2 credentials. - Verify Approval Check evaluates
{{$json.data.approved}}and continues to Download Post Image when true. - Ensure Combine Image and Post receives inputs from both Parse JSON File and Download Post Image, then routes to Route to Platform.
rightValue of =linkedin. Make sure the incoming route matches exactly, or update the rule to linkedin to avoid misrouting.Step 7: Configure Platform Publishing Actions
Send the final post to the correct social platform and generate output summaries.
- In Post to X, set Text to
{{$json.data.social_content.schema.post}}. Credential Required: Connect your twitterOAuth2Api credentials. - For Instagram, configure Create IG Media with URL
https://graph.facebook.com/v20.0/[your-unique-id]/mediaand query parametersimage_url={{ $json.output.social_image.medium.url }}andcaption={{ $json.output.caption }}. Credential Required: Connect your facebookGraphApi credentials. - Configure Publish IG Media to publish the created media using Edge
media_publishand Node[your-unique-id]. Credential Required: Connect your facebookGraphApi credentials. - Configure Publish Facebook Photo with Edge
photos, Node[your-unique-id], and Binary Property Namedata. Credential Required: Connect your facebookGraphApi credentials. - Configure Publish LinkedIn Post with Text
{{$json.data.social_content.schema.post}} {{$json.data.social_content.schema.call_to_action}} {{$json.data.social_content.common_schema.hashtags}}and Organization[YOUR_ID]. Credential Required: Connect your linkedInOAuth2Api credentials. - Leave Threads Placeholder and YouTube Shorts Placeholder as no-op nodes for future expansion.
- Confirm output summaries are captured by X Output Summary, Instagram Output Summary, Facebook Output Summary, and LinkedIn Output Summary.
Step 8: Configure Reporting and Notifications
Send reporting emails and Telegram notifications once assets are generated and posts are published.
- Connect Compact GPT Model as the language model to Prepare Report Email. Credential Required: Connect your openAiApi credentials.
- In Prepare Report Email, keep the template intact and ensure it references
{{$('Image Generation Request').item.json.output.toJsonString()}}and{{$('Assemble Prompt Data').item.json.route}}. - In Send Gmail Summary, set Send To to
{{$env.TELEGRAM_CHAT_ID}}, Message to{{$json.output}}, and Subject to=Social Media Content - {{ $('Store Social Output').item.json.output.title }}. Credential Required: Connect your gmailOAuth2 credentials. - Configure Telegram Success Notice and Telegram Error Notice with Chat ID
{{$env.TELEGRAM_CHAT_ID}}. Credential Required: Connect your telegramApi credentials.
Step 9: Test and Activate Your Workflow
Validate the end-to-end workflow with a manual test and then activate it for production use.
- Manually execute Chat Message Trigger and provide a sample prompt (e.g., “Create a LinkedIn post about product launch”).
- Confirm 🤖Platform Router Agent outputs a route and Extract File Identifier passes the response to Download Post from Drive.
- Verify successful parallel operations: Parse JSON File outputs to both Combine Image and Post and Prepare Approval Email in parallel.
- Approve the email from Gmail Approval Request and confirm a platform node (like Post to X or Publish LinkedIn Post) runs.
- Check that Send Gmail Summary is delivered and Google Drive contains the archived JSON file from Archive Post to Drive.
- When everything works, toggle the workflow to Active for production use.
Common Gotchas
- Google Docs access can fail if the Doc isn’t shared correctly or the token loses permissions. If a fetch node errors, check the Google connection in n8n and confirm the Doc is accessible to that account.
- If you’re using Wait nodes or external rendering, processing times vary. Bump up the wait duration if downstream nodes fail on empty responses.
- Default prompts in AI nodes are generic. Add your brand voice early or you’ll be editing outputs forever.
Frequently Asked Questions
Plan on about 45 minutes if your Google and LinkedIn accounts are ready.
No. You’ll paste API keys, connect accounts, and update the Google Doc IDs in the right nodes.
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 OpenAI API usage, SerpAPI usage, and your image hosting costs from ImgBB.
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, but you’ll want to adjust the Gmail approval path and the “Approval Check” logic so it waits for the right signal. Many teams add a second approver email, require an “APPROVE” keyword, or route “needs edits” back to a draft folder in Google Drive. You can also tweak the Google Docs system prompt to enforce different voices for executives vs. brand accounts. If you publish to other platforms too, the platform router can be extended so LinkedIn is just one destination.
Usually it’s an expired OAuth connection or a missing permission on the LinkedIn app. Reconnect the LinkedIn credential in n8n, then confirm the account has access to post on the selected company page or profile. If it fails only on some runs, rate limits or blocked media URLs can also be the culprit, especially when the image host changes.
A lot, as long as your plan and APIs can keep up.
For this specific setup, n8n is usually the better fit because the workflow logic is more branching-heavy and you’re composing prompts from Google Docs, running an AI agent, generating images, and waiting on approvals. Zapier and Make can do parts of it, but long approval waits and multi-step routing tend to get awkward (and pricey) at scale. n8n also gives you the option to self-host, which matters when you start running this daily. If you only need “Doc changes → send email,” Zapier is fine. If you want the full factory with archiving and publishing, n8n wins more often than not. Talk to an automation expert if you want a quick recommendation based on volume.
Once your rules live in Google Docs and approvals happen the same way every time, LinkedIn publishing stops being a recurring scramble. Set it up, run it, and keep your creative energy for the ideas that actually move the needle.
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.