Generate a monthly SEO report deck per client with n8n
Every month, one branded Google Slides SEO report per client, built from the metrics in your Google Sheet, delivered to Google Drive, with the link written back to the client's row.
- Source
- Google Sheets
- Output
- Google Slides
- Delivered to
- Google Drive
n8n workflow
The importable workflow file for this recipe is being tested and will be added here. The steps below show exactly what it does, so you can build it now in a few minutes with the SourceToDocs n8n node.
How the workflow runs
- 01
Schedule Trigger: monthly
Trigger Interval is Months, Months Between Triggers is 1, Trigger at Day of Month is 3 and Trigger at Hour is 8am. Pick a day by which last month's numbers are in the sheet.
- 02
SourceToDocs: Document, Generate
Pick the split Google Slides document that reads your metrics sheet. In its Split step, the metrics tab is the driver and the Split by expression {{ client }} gives one deck per client. The driver's own rows are not content, so the data set holding the metrics is set to Only matching rows with the match key {{ client }}. Rows Come From stays on Connected Data Sources, the default, so the document reads the sheet itself and delivers the decks into a folder for that run inside your Drive folder. A split run produces decks and no PDFs.
- 03
Google Sheets: Update Row
Optional. With Wait for Completion on, the default, the SourceToDocs node outputs one item per deck, each with file_url and split_key, the client that deck was generated for. This node matches the row on Client and writes file_url into the Report link column.
| Google Sheets field | Template placeholder |
|---|---|
| Client | {{ client }} |
| Month | {{ month }} |
| Clicks | {{ clicks }} |
| Clicks change | {{ clicks_change }} |
| Impressions | {{ impressions }} |
| CTR | {{ ctr }} |
| Average position | {{ average_position }} |
| Top page | {{ top_page }} |
| Top query | {{ top_query }} |
| Summary | {{ summary }} |
Or have Claude set it up
The Report decks from a spreadsheet skill
works through the SourceToDocs connector at https://app.sourcetodocs.com/api/mcp. Install the skill, connect, then paste:
Use the report-decks skill. My SEO metrics are in the Google Sheets spreadsheet "SEO reporting", tab "This month", one row per client, with the columns Client, Month, Clicks, Clicks change, Impressions, CTR, Average position, Top page, Top query and Summary. I will pick the spreadsheet, the Google Slides SEO report template and the Drive folder "SEO reports 2026" when you send me the links. Set up one deck per client. Show me the placeholder mapping and the number of decks before you run anything.
To produce an SEO report deck per client from n8n, schedule the workflow once a month and let the SourceToDocs node start a split document that reads your metrics sheet: one Google Slides report per client, delivered to Google Drive. The node returns one item per deck, so an optional last node writes each link back to the client’s row. The build is three nodes. The one-time setup of the split document comes first.
What you need
- A Google Sheet with a tab named
This monthholding one row per client for the month you report on, and the columnsClient,Month,Clicks,Clicks change,Impressions,CTR,Average position,Top page,Top query,SummaryandReport link. Client names must be unique in the tab. Change the metric columns to the ones you report; the pattern stays the same. - An SEO report template in Google Slides with the placeholders listed below. The SEO report template is a fuller design with its own placeholder names: a design reference, not a drop-in file.
- A SourceToDocs workspace and an API token for it. A workspace owner or admin creates the token on the API Tokens page.
- On the Accounts page, a Google Sheets connection for the data, a Google Slides connection for the template and a Google Drive connection for delivery. Every tile is a separate connection: one does not cover the others.
- n8n, Cloud or self-hosted, with the SourceToDocs node installed. On a self-hosted instance that is Settings, then Community nodes, then Install, with the package name
@twovmodules/n8n-nodes-sourcetodocs; on n8n Cloud, add it from the nodes panel, where it has a verified listing. Add a Google Sheets credential in n8n if you use the last node.
How the sheet gets its numbers is outside this workflow. Type them in, paste an export from the tool you use, or have another workflow write the rows. What matters is that the tab holds the finished month before the schedule fires. If you keep history, keep it in another tab, so This month never holds two rows for the same client.
Set up the document in SourceToDocs
The document reads the sheet itself. n8n only starts it.
- Create a Google Slides document and connect Google Sheets as its data source. Press Choose a spreadsheet, pick your metrics spreadsheet, and choose the
This monthtab in the data set’s Sheet field. - Name the data set and tick the columns the report prints. Each column gets an alias, a snake-case identifier derived from its name. The template uses the alias: column
Average positionis{{ average_position }}. - Add a subset on the data set with Add Subset.
- On the Split step, set the driver: your Google Sheets source, the
This monthtab, and the Split by expression{{ client }}. You get one deck per distinct value, and rows with a blank Client are skipped. - In the participation table on the same step, set the data set to Only matching rows with the match key
{{ client }}. The driver’s own rows are not content: the driver decides how many decks there are, and this setting is what puts each client’s row into that client’s deck. - Press Estimate to see the number of decks before anything runs.
- In Template Config, add a
dynamic_slideentry on the subset for every template slide that shows the client’s metrics. Pick your template in Presentation Access, map each entry to its slide in the Slide Editor and press Save Mappings. A Slides document will not generate until the entries exist and are mapped. The Slide Editor lists each slide’s placeholders as Matched, Available or Unresolved. - Add a Google Drive distribution and choose the folder.
A slide with no client data, such as a methodology or contact slide, takes a static_slide entry. Row placeholders on a static slide print blank, so keep the metrics on the bound slides.
Generate once from the app and read the first decks before you schedule anything. Check how the numbers read, percentages and positions in particular, and adjust them in the sheet or in the document until the deck is right.
Build it in n8n
Add the nodes in this order and connect them in a line.
| Node | Operation | Key settings |
|---|---|---|
| Schedule Trigger | Trigger Interval: Months | Months Between Triggers: 1. Trigger at Day of Month: 3. Trigger at Hour: 8am. |
| SourceToDocs | Resource: Document. Operation: Generate | Document: your SEO report document. Rows Come From: Connected Data Sources, the default. Under Options, raise Max Wait above the default 300 seconds if you have many clients. Wait for Completion stays on. |
| Google Sheets | Operation: Update Row | Document and Sheet: the metrics spreadsheet, This month tab. Column to match on: Client. Values: see below. |
The values the Google Sheets node writes:
| Column | Value |
|---|---|
| Client | {{ $json.split_key }} |
| Report link | {{ $json.file_url }} |
What the node returns
With Wait for Completion on, the SourceToDocs node outputs one item per deck. Each item carries file_url and file_name at the top level and split_key, the client that deck was generated for. The Google Sheets node runs once per item, which is why matching on Client with split_key puts every link on the right row.
In Drive, the decks sit together in a folder created for that run inside the folder you chose, named after the document and the time the run started, so one month’s reports never mix with the next. With the default file name each deck is named after its client.
If the run is still going when Max Wait ends, the node does not fail. It returns an item with timed_out set to true and the run_id, and the decks still arrive in Drive.
Or have Claude set it up
The setup steps above can be done by Claude instead of by hand. With the SourceToDocs connector added to Claude and the report-decks skill installed, paste the prompt from the block at the top of this page. Claude creates the document, attaches the sheet, reads the placeholders in your template, configures the data set, the slide entries and their mappings, the split and the Drive destination, shows you the mapping and the deck count, and starts a run when you ask.
Claude asks first whether you need PDFs. One deck per client from a split run delivers Google Slides decks and no PDFs; a PDF with every deck means one run per client, which suits a few clients.
Three things stay with you. Claude sends links for you to pick the spreadsheet, the template and the Drive folder in Google’s own picker, because it cannot browse your Drive. It cannot edit the template file, so a missing placeholder is yours to add in Google Slides. And Claude runs when you ask: the monthly schedule is the n8n workflow above.
Where this fits
This workflow covers one report type from one sheet. When the same clients also get paid media, social or a combined monthly report, or each client needs its own branding, the client reporting automation guide covers the wider setup. If your client data lives in Airtable instead of a sheet, the Airtable to Google Slides walkthrough builds the same one-deck-per-client run from a base.
Related
- client reporting automation: the full guide this recipe belongs to.
- Free SEO report template for Google Slides: the template this workflow fills.
- The SourceToDocs n8n node: every action and setting.
- The SourceToDocs MCP server: what Claude can do through the connector.