Google Sheets to LinkedIn, posts published for you
Your LinkedIn consistency usually breaks for the same boring reason. You have ideas, maybe even a rough title list, but turning those into polished posts (with a decent image) keeps getting pushed to “later.” Later turns into next week. Then nothing ships.
This Sheets LinkedIn automation hits marketing managers hard, but founders and solo consultants feel it too. You need a reliable queue that publishes without you babysitting it, so your content doesn’t disappear when your calendar gets messy.
This workflow watches a Google Sheet for “pending” ideas, uses Gemini to write the post and generate an on-brand visual, stores the image in Drive, and publishes to LinkedIn. Below, you’ll see exactly what it automates and what you get back.
How This Automation Works
The full n8n workflow, from trigger to final output:
n8n Workflow Template: Google Sheets to LinkedIn, posts published for you
flowchart LR
subgraph sg0["Sheets Update Flow"]
direction LR
n0@{ icon: "mdi:play-circle", form: "rounded", label: "Sheets Update Trigger", pos: "b", h: 48 }
n1@{ icon: "mdi:swap-horizontal", form: "rounded", label: "Status Condition Check", pos: "b", h: 48 }
n2@{ icon: "mdi:cog", form: "rounded", label: "Cap Records", pos: "b", h: 48 }
n3@{ icon: "mdi:robot", form: "rounded", label: "LinkedIn Post Composer", pos: "b", h: 48 }
n4["<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/>Escape Line Breaks"]
n5@{ icon: "mdi:brain", form: "rounded", label: "Gemini Chat Engine", pos: "b", h: 48 }
n6@{ icon: "mdi:robot", form: "rounded", label: "Parse Structured Output", pos: "b", h: 48 }
n7@{ icon: "mdi:robot", form: "rounded", label: "Create Social Image", pos: "b", h: 48 }
n8@{ icon: "mdi:cog", form: "rounded", label: "Drive File Upload", pos: "b", h: 48 }
n9@{ icon: "mdi:cog", form: "rounded", label: "Public Share File", pos: "b", h: 48 }
n10@{ icon: "mdi:database", form: "rounded", label: "Save Image Link", 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/httprequest.dark.svg' width='40' height='40' /></div><br/>LinkedIn User Lookup"]
n12["<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/>Init Image Upload"]
n13@{ icon: "mdi:cog", form: "rounded", label: "Fetch Drive File", 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/>Send Image Binary"]
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/>Publish LinkedIn Post"]
n16@{ icon: "mdi:database", form: "rounded", label: "Mark Sheet Row", pos: "b", h: 48 }
n1 --> n2
n4 --> n7
n2 --> n3
n3 --> n4
n9 --> n10
n8 --> n9
n11 --> n12
n13 --> n14
n15 --> n16
n10 --> n11
n0 --> n1
n12 --> n13
n5 -.-> n3
n6 -.-> n3
n14 --> n15
n7 --> n8
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 trigger
class n3,n6,n7 ai
class n5 aiModel
class n1 decision
class n10,n16 database
class n11,n12,n14,n15 api
class n4 code
classDef customIcon fill:none,stroke:none
class n4,n11,n12,n14,n15 customIcon
The Problem: LinkedIn Posting Falls Apart at the Finish Line
Most teams don’t struggle with “coming up with ideas.” They struggle with production. A simple post title turns into 30 minutes of writing, rewriting, formatting, and second-guessing, then another chunk of time hunting for an image that doesn’t look like stock-photo soup. And when you finally post, there’s no clean system that tells you what shipped, what’s still pending, and what’s stuck half-done. It’s mentally heavy work, so it’s the first thing you drop when client work, launches, or meetings pile up.
It adds up fast. Here’s where the friction compounds.
- Drafts live in too many places, which means your “content plan” becomes guesswork.
- Writing hooks and closing questions takes longer than it should, especially when you are tired.
- Images are a constant bottleneck because “good enough” is surprisingly hard to find.
- Without a status field and a posting trail, you end up reposting topics or forgetting the best ones.
The Solution: Google Sheets → Gemini → LinkedIn Auto-Publishing
This workflow turns your Google Sheet into a content conveyor belt. When a row is marked “pending,” n8n pulls the post title, sends it to Gemini, and gets back a LinkedIn-ready draft with a hook, a few structured paragraphs, a question to drive comments, and a small set of hashtags. Then it generates a matching image using Gemini’s image model, uploads that image to Google Drive, and makes it accessible for LinkedIn’s upload process. Finally, it publishes the post (text plus image) to your LinkedIn profile and marks the original row as “posted,” so your queue stays clean and trustworthy. One idea in. One finished post out.
The workflow starts by monitoring Google Sheets for new “pending” items and intentionally caps it to one post at a time for controlled execution. Next, Gemini handles both the writing and the visual. After that, LinkedIn’s API steps register the image, upload it properly, publish the post, and update your spreadsheet so you always know what happened.
What You Get: Automation vs. Results
| What This Workflow Automates | Results You’ll Get |
|---|---|
|
|
Example: What This Looks Like
Say you publish 5 LinkedIn posts per week. Manually, a reasonable “good post” pace is about 30 minutes to write, plus maybe 15 minutes to find or design an image, plus a few minutes to upload and format. That’s roughly 4 hours every week. With this workflow, you add five titles to a Sheet and set them to “pending” (maybe 10 minutes total), then n8n generates and publishes each post automatically on schedule. You get most of those hours back, without losing consistency.
What You’ll Need
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- Google Sheets to manage titles and post status.
- Google Drive to store and share generated images.
- Google Gemini API key (get it from Google AI Studio / Google Cloud credentials).
- LinkedIn API credentials (get them from LinkedIn Developer portal for posting permissions).
Skill level: Intermediate. You’ll connect accounts, paste API keys, and verify a few permissions in Google and LinkedIn.
Don’t want to set this up yourself? Talk to an automation expert (free 15-minute consultation).
How It Works
Google Sheets triggers the run. When a row changes (or when the scheduled trigger checks), n8n looks for a post idea with status set to “pending.” If nothing is pending, nothing publishes.
The workflow verifies and limits what gets processed. An “if” check filters out anything that isn’t ready, and a cap keeps it to one post per execution. That prevents accidental bulk posting and makes failures easier to spot.
Gemini writes the post and produces a matching image. The text is generated in a structured format (hook, paragraphs, question, hashtags), then line breaks are cleaned up so LinkedIn renders it the way you expect. Next, Gemini generates a high-resolution 16:9 image with a professional look and no text baked into the graphic.
Drive stores the image, LinkedIn publishes, and the Sheet gets updated. The image is uploaded to Google Drive, shared so it can be fetched, then LinkedIn’s upload flow registers and attaches the media to the post. When publishing succeeds, the spreadsheet row is marked “posted” (plus the image link is saved), which keeps your queue honest.
You can easily modify the posting frequency to match your calendar (daily, three times a week, specific weekdays). See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Google Sheets Trigger
Set up the workflow to watch for new or updated rows in your posting spreadsheet.
- Add and open Sheets Update Trigger.
- Set Document to your spreadsheet:
[YOUR_ID](cached name:Linkedin Post). - Set Sheet Name to
Posts(value:[YOUR_ID]). - Confirm Poll Times is set to
everyMinute. - Credential Required: Connect your
googleSheetsTriggerOAuth2Apicredentials.
ID, LinkedIn Post Title, and Status, or the downstream updates will fail.Step 2: Filter and Limit Pending Rows
Only rows marked as pending should continue through the workflow.
- Open Status Condition Check and ensure the condition compares Status to
pendingusing={{ $json.Status }}on the left. - Connect Status Condition Check to Cap Records to limit processing.
- Keep Cap Records as-is (default limit) unless you want to process multiple rows per run.
Step 3: Set Up the AI Post Composer
Compose a LinkedIn-ready post with structured JSON output and prepare it for API submission.
- Open LinkedIn Post Composer and confirm the prompt uses the title expression
{{ $json['LinkedIn Post Title'] }}and returns JSON withtitleandpost. - Ensure Gemini Chat Engine is connected as the language model for LinkedIn Post Composer. Credential Required: Connect your
googlePalmApicredentials in Gemini Chat Engine. - Verify Parse Structured Output is attached to LinkedIn Post Composer with the provided JSON schema. This is an AI sub-node; add credentials to the parent LinkedIn Post Composer via Gemini Chat Engine, not here.
- Open Escape Line Breaks and confirm the JS Code replaces newlines using
item.json.output.post.replace(/\n/g, "\\n").
Step 4: Generate and Store the Social Image
Create a Gemini-generated image, upload it to Drive, and save the shareable link back to the sheet.
- Open Create Social Image and keep the Prompt as the multi-line prompt using
{{ $json.output.post }}with Resource set toimage. - Credential Required: Connect your
googlePalmApicredentials in Create Social Image. - In Drive File Upload, set Name to
=linkedin_{{$now.format('YYYYMMDD_HHmmss')}}.{{$binary.data.fileExtension || 'png'}}and choose the target folderlinkedin images. Credential Required: Connect yourgoogleDriveOAuth2Apicredentials. - In Public Share File, set Operation to
shareand File ID to={{ $json.id }}, with permissionsanyone+reader. Credential Required: Connect yourgoogleDriveOAuth2Apicredentials. - In Save Image Link, set Operation to
updateand map columns: ID to={{ $('Status Condition Check').item.json.ID }}and imageUrl to={{$node["Drive File Upload"].json.webViewLink}}. Credential Required: Connect yourgoogleSheetsOAuth2Apicredentials.
Step 5: Upload to LinkedIn and Publish the Post
Register the image upload, send the binary file, and publish the LinkedIn post.
- Configure LinkedIn User Lookup with URL
https://api.linkedin.com/v2/userinfoand Authentication set togenericCredentialType. Credential Required: Connect yourhttpHeaderAuthcredentials. - In Init Image Upload, set URL to
https://api.linkedin.com/v2/assets?action=registerUploadand JSON Body to the provided template with ownerurn:li:person:{{ $('LinkedIn User Lookup').item.json.sub }}. Credential Required: Connect yourhttpHeaderAuthcredentials. - In Fetch Drive File, set Operation to
downloadand File ID to={{ $('Save Image Link').item.json.imageUrl }}. Credential Required: Connect yourgoogleDriveOAuth2Apicredentials. - Configure Send Image Binary with URL
={{$node["Init Image Upload"].json.value.uploadMechanism["com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest"].uploadUrl}}, MethodPOST, Content TypebinaryData, and headerContent-Typeset to={{$binary.data.mimeType || 'image/png'}}. - In Publish LinkedIn Post, keep the URL
https://api.linkedin.com/v2/ugcPostsand the JSON Body mapping to:{{ $('Escape Line Breaks').item.json.output.post }},{{ $('LinkedIn Post Composer').item.json.output.title }}, and{{ $('Init Image Upload').item.json.value.asset }}. Credential Required: Connect yourhttpHeaderAuthcredentials. - Update the status in Mark Sheet Row with Status set to
postedand ID set to={{ $('Cap Records').item.json.ID }}. Credential Required: Connect yourgoogleSheetsOAuth2Apicredentials.
The execution order follows a single path: Sheets Update Trigger → Status Condition Check → Cap Records → LinkedIn Post Composer → Escape Line Breaks → Create Social Image → Drive File Upload → Public Share File → Save Image Link → LinkedIn User Lookup → Init Image Upload → Fetch Drive File → Send Image Binary → Publish LinkedIn Post → Mark Sheet Row.
Step 6: Test and Activate Your Workflow
Validate the workflow end-to-end and enable it for production use.
- In your Google Sheet, add a row with Status set to
pendingand a valid LinkedIn Post Title. - Click Execute Workflow to run a manual test.
- Confirm a Drive image file is created and the imageUrl column is updated by Save Image Link.
- Verify LinkedIn receives a new post with the generated image and text.
- Check the sheet row is updated by Mark Sheet Row with Status =
posted. - Turn on the workflow by clicking Activate to run automatically every minute.
Common Gotchas
- LinkedIn API credentials can expire or lack the right posting scope. If things break, check your LinkedIn Developer app permissions and token status 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 sharing settings can silently block the image fetch. Confirm the uploaded file is publicly accessible (or at least accessible to the workflow) before the LinkedIn upload step runs.
Frequently Asked Questions
About an hour if you already have your LinkedIn and Gemini credentials.
No. You’ll mostly connect accounts and paste API keys. The only “technical” part is checking permissions when LinkedIn or Google rejects a request.
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 Gemini API usage costs, which depend on how long your posts are and how many images you generate.
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 one of the best tweaks to make. You can adjust the Schedule Trigger so posts only run on weekdays or at a specific hour, and keep the “pending/posted” status logic the same. Common customizations include adding an “Approved” column in Google Sheets, changing the Gemini prompt to match your brand voice, and switching the image style to match your design system.
Usually it’s an expired token or missing posting permissions on your LinkedIn Developer app. Regenerate the credentials and update them in n8n, then re-run with a single pending row. If it fails only sometimes, you may be hitting rate limits during the image upload sequence, so spacing out executions helps.
A lot, but it’s designed to process one pending row per run for safety.
For this specific job, n8n is usually the smoother choice because the LinkedIn upload flow is multi-step and you often need branching, data cleanup, and retries. n8n also gives you a self-hosting path, which matters when you want lots of runs without paying per task. Zapier and Make can work, but you’ll feel the complexity when you start attaching images, saving Drive links, and updating statuses reliably. Frankly, the real difference is control: n8n lets you see and adjust every part of the chain when something changes in an API. If you want a second opinion for your setup, Talk to an automation expert.
Once this is running, your spreadsheet becomes a real publishing queue, not a wish list. The workflow handles the repetitive parts so you can focus on the ideas that actually move your business.
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.