Google Sheets + LinkedIn, repeat free content posting
You already have the content. What’s broken is the distribution. Someone still has to pick an article, write two versions of a post, avoid repeats, then publish to LinkedIn and X without it turning into a daily chore.
This hits marketing managers first, because consistency is the job. But founders trying to stay visible and agency owners managing multiple client calendars feel the same grind. With this sitemap posting automation, your old articles turn into fresh social posts on a schedule, while Google Sheets keeps you from recycling the same link.
Below is the exact workflow logic, what you need to run it, and where teams typically tweak it for their brand voice and posting rhythm.
How This Automation Works
See how this solves the problem:
n8n Workflow Template: Google Sheets + LinkedIn, repeat free content posting
flowchart LR
subgraph sg0["When clicking ‘Execute workflow’ Flow"]
direction LR
n0@{ icon: "mdi:play-circle", form: "rounded", label: "When clicking ‘Execute workf..", pos: "b", h: 48 }
n1@{ icon: "mdi:cog", form: "rounded", label: "parse sitemap", pos: "b", h: 48 }
n2["<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/>fetch sitemap"]
n3@{ icon: "mdi:swap-vertical", form: "rounded", label: "get list of articles", pos: "b", h: 48 }
n4@{ icon: "mdi:swap-horizontal", form: "rounded", label: "filter out ToC pages", pos: "b", h: 48 }
n5@{ icon: "mdi:swap-vertical", form: "rounded", label: "rename fields", pos: "b", h: 48 }
n6@{ icon: "mdi:database", form: "rounded", label: "get processed articles", pos: "b", h: 48 }
n7@{ icon: "mdi:cog", form: "rounded", label: "availableArticles", pos: "b", h: 48 }
n8@{ icon: "mdi:cog", form: "rounded", label: "processedArticles", 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/merge.svg' width='40' height='40' /></div><br/>Merge"]
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/code.svg' width='40' height='40' /></div><br/>pick random not processed ar.."]
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/html.dark.svg' width='40' height='40' /></div><br/>extract HTML content"]
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/>fetch article"]
n13@{ icon: "mdi:swap-vertical", form: "rounded", label: "add metadata", pos: "b", h: 48 }
n14@{ icon: "mdi:robot", form: "rounded", label: "AI Agent", pos: "b", h: 48 }
n15@{ icon: "mdi:brain", form: "rounded", label: "Google Gemini Chat Model", pos: "b", h: 48 }
n16@{ icon: "mdi:robot", form: "rounded", label: "Structured Output Parser", pos: "b", h: 48 }
n17@{ icon: "mdi:database", form: "rounded", label: "add processed article", pos: "b", h: 48 }
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/x.dark.svg' width='40' height='40' /></div><br/>Create Tweet"]
n19@{ icon: "mdi:swap-vertical", form: "rounded", label: "parameters", pos: "b", h: 48 }
n20@{ icon: "mdi:swap-horizontal", form: "rounded", label: "If Twitter post created", pos: "b", h: 48 }
n21@{ icon: "mdi:swap-horizontal", form: "rounded", label: "If LinkedIn post created", pos: "b", h: 48 }
n22["<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/>normalize list of images"]
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/linkedin.svg' width='40' height='40' /></div><br/>Create a post"]
n24@{ icon: "mdi:play-circle", form: "rounded", label: "Schedule Trigger", pos: "b", h: 48 }
n9 --> n10
n14 --> n17
n19 --> n2
n19 --> n6
n13 --> n14
n12 --> n11
n2 --> n1
n1 --> n3
n5 --> n7
n24 --> n19
n8 --> n9
n7 --> n9
n11 --> n13
n4 --> n5
n3 --> n22
n17 --> n20
n17 --> n21
n6 --> n8
n20 --> n18
n15 -.-> n14
n21 --> n23
n16 -.-> n14
n22 --> n4
n10 --> n12
n0 --> n19
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,n24 trigger
class n14,n16 ai
class n15 aiModel
class n4,n20,n21 decision
class n6,n17 database
class n2,n12 api
class n10,n22 code
classDef customIcon fill:none,stroke:none
class n2,n9,n10,n11,n12,n18,n22,n23 customIcon
The Challenge: Staying consistent without reposting the same link
Repurposing long-form content sounds easy until you do it for a month. You open your blog, scroll for something “still relevant,” copy the URL, then write a LinkedIn version and an X version that don’t look like a lazy cross-post. Next week you forget what you already shared, so you either repeat yourself or burn more time checking old posts. The mental load is the annoying part: it’s not hard work, it’s just endless work.
It adds up fast. Here’s where it breaks down in real life.
- You lose about 20 minutes per post just deciding what to share and confirming it hasn’t already run.
- Writing for LinkedIn and X takes two different angles, so “quick repurposing” becomes a mini copywriting session.
- Manual tracking lives in someone’s head, which means repeats happen as soon as that person gets busy or goes on vacation.
- Even when you use schedulers, they don’t pick the next article from your sitemap or stop you from reusing the same URL.
The Fix: Turn your sitemap into scheduled LinkedIn + X posts
This workflow starts with what you already own: your sitemap. On a schedule (daily by default), it pulls the sitemap, parses out article URLs, filters out pages you don’t want to promote (like table-of-contents or utility pages), and builds a clean list of candidates. At the same time, it looks at a Google Sheet where past posts were logged, compiles the URLs that already ran, then chooses an unused article at random so your feed stays varied. Once a URL is selected, the workflow fetches the article page, extracts the HTML, attaches useful metadata, and asks Gemini to generate platform-specific copy. Finally, it publishes to LinkedIn and X (only if those channels are enabled) and logs what happened back into Google Sheets so you won’t repeat the same link tomorrow.
The workflow begins with a scheduled trigger and your input settings (sitemap URL, language, channels). It then merges “available articles” with “already processed URLs” to pick the next unused piece. Gemini writes two drafts, and n8n publishes them and records the URL, timestamp, and the exact text that went out.
What Changes: Before vs. After
| What This Eliminates | Impact You’ll See |
|---|---|
|
|
Real-World Impact
Say you publish one syndicated post per day to two channels (LinkedIn + X). Manually, it’s usually 10 minutes to pick an article and confirm it’s not a repeat, then about 15 minutes to write and tailor the two versions. Call it 25 minutes a day, or roughly 2 hours a week. With this workflow, the “human time” is close to zero after setup: it triggers automatically at noon, generates the copy, posts, and logs everything while you keep working.
Requirements
- n8n instance (try n8n Cloud free)
- Self-hosting option if you prefer (Hostinger works well)
- Google Sheets for tracking posted URLs and drafts.
- LinkedIn to publish the finished post automatically.
- X/Twitter to publish the tweet version automatically.
- Google Gemini API key (get it from Google AI Studio / Gemini API in Google Cloud).
Skill level: Beginner. You’ll connect accounts, paste in a sitemap URL, and map a few spreadsheet columns.
Need help implementing this? Talk to an automation expert (free 15-minute consultation).
The Workflow Flow
A schedule kicks things off. The workflow runs automatically (daily at noon by default), or you can test it with a manual run. Your settings node controls the sitemap URL, language, and which channels are turned on.
Your sitemap becomes the content source. n8n fetches the sitemap via HTTP request, parses the XML into individual URLs, cleans up edge cases like weird image lists, and filters out pages you don’t want promoted (for example, TOC pages).
Google Sheets prevents repeats. In parallel, it reads your “processed articles” sheet, compiles a list of URLs already used, then merges that list with the fresh sitemap list. A selection step picks an unused article so you don’t post the same link twice.
Gemini writes, then publishing happens. The workflow fetches the chosen article’s HTML, attaches metadata, and sends it to a Gemini-powered agent that generates a LinkedIn draft and a tweet draft. If a draft exists for a channel, n8n publishes it and logs the URL, timestamp, and final copy back to Google Sheets.
You can easily modify the schedule and the filtering rules to match your cadence and your site structure. See the full implementation guide below for customization options.
Step-by-Step Implementation Guide
Step 1: Configure the Manual and Scheduled Triggers
Set up how the workflow starts, either manually or on a schedule, and pass initial configuration values downstream.
- Open Manual Run Trigger to allow on-demand testing and execution.
- Open Scheduled Run Trigger and set the rule to run at 12 using the interval configuration shown in the node.
- In Input Settings, set sitemapURL to
https://example.com/sitemap.xml. - In Input Settings, set language to
Englishand enable linkedinPostEnabled and twitterPostEnabled astrue. - Confirm the flow: Input Settings outputs to both Retrieve Sitemap and Retrieve Processed Rows in parallel.
Step 2: Connect Google Sheets for Processed Article Tracking
These nodes read and log processed URLs to prevent re-posting the same article.
- Open Retrieve Processed Rows and choose your target spreadsheet Document and Sheet (leave values as list selections in the node UI).
- Credential Required: Connect your googleApi credentials in Retrieve Processed Rows.
- Open Log Published Article and keep Operation set to
appendwith Authentication asserviceAccount. - Credential Required: Connect your googleApi credentials in Log Published Article.
- Verify column mappings in Log Published Article, including url, status (
ready), timestamp ({{$now.format('dd.MM.yyyy HH:mm:ss')}}), and AI outputs for Twitter post and LinkedIn post.
Step 3: Build the Sitemap Parsing and Article Selection Pipeline
This sequence fetches your sitemap, filters valid articles, and selects an unprocessed URL.
- In Retrieve Sitemap, set URL to
{{ $json.sitemapURL }}. - In Parse Sitemap XML, keep XML options enabled (ignore attributes, no explicit arrays) as configured.
- In Split Article Entries, set Field to Split Out to
urlset.url. - Keep Normalize Image List as-is to wrap single image objects into arrays for consistent filtering.
- In Exclude TOC Pages, confirm the filter checks
{{ $json["image:image"] }}for exists and not empty. - In Map Field Names, map url to
{{ $json.loc }}, lastModified to{{ $json.lastmod }}, and images to{{ $json["image:image"] }}. - In Compile Available Articles, set Aggregate to
aggregateAllItemDataand Destination Field Name toavailableArticles. - In Compile Processed URLs, set Fields to Include to
urland Destination Field Name toprocessedArticles. - Confirm Combine Streams merges Compile Available Articles and Compile Processed URLs, then flows into Select Unused Article.
Step 4: Fetch Article Content and Generate Social Copy with AI
This section downloads the selected article, extracts the HTML, attaches metadata, and generates social media drafts.
- In Retrieve Article Page, set URL to
{{ $json.url }}. - In Extract Page HTML, keep Operation set to
extractHtmlContentand use the CSS selectordiv.single-post-contentwith return valuehtml. - In Attach Article Metadata, map url to
{{ $('Select Unused Article').item.json.url }}, lastModified to{{ $('Select Unused Article').item.json.lastModified }}, images to{{ $('Select Unused Article').item.json.images }}, and content to{{ $json.content }}. - In Social Copy Generator, keep the prompt as provided; it references Input Settings with
{{ $('Input Settings').first().json.language }}and enabled platform flags. - Credential Required: Connect your googlePalmApi credentials in Gemini Chat Engine, which powers Social Copy Generator.
- Ensure Structured Result Parser remains attached as the output parser for Social Copy Generator; add credentials to the parent Gemini Chat Engine, not this sub-node.
Step 5: Configure Social Publishing and Conditional Checks
These nodes decide which posts to publish and send them to Twitter/X and LinkedIn.
- Verify Log Published Article outputs to both Check Twitter Draft and Check LinkedIn Draft in parallel.
- In Check Twitter Draft, confirm the conditions check
{{ $json["Twitter post"] }}for exists and not empty. - In Publish Tweet, set Text to
{{ $json["Twitter post"] }}and connect your Twitter credentials. - In Check LinkedIn Draft, confirm the conditions check
{{ $json["LinkedIn post"] }}for exists and not empty. - In Publish LinkedIn Post, set Text to
{{ $json["LinkedIn post"] }}and keep Share Media Category asARTICLE. - Credential Required: Add credentials for Publish Tweet and Publish LinkedIn Post since they are not pre-configured.
Step 6: Test and Activate Your Workflow
Validate that data flows end-to-end and the social posts are generated correctly before turning on the schedule.
- Click Execute Workflow from Manual Run Trigger to test the full flow.
- Confirm Retrieve Sitemap returns data and Select Unused Article outputs a single article.
- Verify Social Copy Generator outputs structured JSON with TwitterPost and LinkedInPost fields.
- Check Log Published Article appends a new row to Google Sheets with the URL, timestamp, and draft posts.
- When results are correct, toggle the workflow to Active to enable Scheduled Run Trigger.
Watch Out For
- Google Sheets credentials can expire or lack access to the right spreadsheet. If the workflow stops logging, check the Google Sheets node credentials and the document selection in “get processed articles” 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.
- LinkedIn or X permissions can be the silent killer. If publishing fails, re-auth the LinkedIn/X connection in n8n and confirm your app/account can post on behalf of the profile or page you selected.
Common Questions
About 30 minutes if your accounts and sitemap are ready.
Yes. You’ll mostly be connecting accounts and filling in the sitemap URL plus a few Sheet columns.
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 Google Gemini API usage, which is typically pennies for a small daily posting workflow.
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.
You can adjust the schedule in the Scheduled Run Trigger, change what counts as “promotable” content in the Exclude TOC Pages filter, and rewrite the prompt inside the Social Copy Generator to match your voice. If you prefer another model provider, swap the Gemini Chat Engine for your provider’s chat node and keep the same inputs (article text + metadata). Common customizations include adding UTM parameters to URLs, forcing a specific post format (hook, body, CTA), and disabling X or LinkedIn when you only want one channel active.
Usually it’s expired authorization or missing permissions on the LinkedIn account you connected. Reconnect the LinkedIn credential in n8n, then confirm you’re posting to the right destination (profile vs. company page). If it fails only sometimes, you may also be hitting platform limits or trying to publish an empty draft because the AI node didn’t return the expected fields.
For most teams posting once per day, capacity isn’t the constraint.
Often, yes, because this workflow isn’t just “send A to B.” You’re parsing a sitemap, excluding certain pages, merging two data streams (available vs. already used), randomly selecting an unused URL, then generating structured outputs before publishing. n8n handles that kind of branching and data shaping cleanly, and you can self-host for unlimited runs. Zapier or Make can still work, but the logic tends to get spread across multiple scenarios and paid steps. If you’re torn, Talk to an automation expert and you’ll get a straight recommendation.
Once this is running, your content library stops gathering dust. The workflow handles the repetitive parts, and you get a steady stream of posts without the “what did we share last time?” headache.
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.