Skip to main content

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

  1. 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.

  2. 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.

  3. 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 fields and the template placeholders they fill
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.

Get the skill file

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 month holding one row per client for the month you report on, and the columns Client, Month, Clicks, Clicks change, Impressions, CTR, Average position, Top page, Top query, Summary and Report 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.

  1. 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 month tab in the data set’s Sheet field.
  2. 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 position is {{ average_position }}.
  3. Add a subset on the data set with Add Subset.
  4. On the Split step, set the driver: your Google Sheets source, the This month tab, and the Split by expression {{ client }}. You get one deck per distinct value, and rows with a blank Client are skipped.
  5. 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.
  6. Press Estimate to see the number of decks before anything runs.
  7. In Template Config, add a dynamic_slide entry 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.
  8. 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.

NodeOperationKey settings
Schedule TriggerTrigger Interval: MonthsMonths Between Triggers: 1. Trigger at Day of Month: 3. Trigger at Hour: 8am.
SourceToDocsResource: Document. Operation: GenerateDocument: 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 SheetsOperation: Update RowDocument and Sheet: the metrics spreadsheet, This month tab. Column to match on: Client. Values: see below.

The values the Google Sheets node writes:

ColumnValue
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

Common questions, answered

Is there a workflow file to import? +
Not yet. The importable file is being tested and will be added to this page. Until then, the three nodes and their settings above are everything the workflow contains, so you can build it by hand.
Does it pull the numbers from Google Search Console or an SEO tool? +
No. SourceToDocs reads Airtable, Google Sheets, an uploaded CSV, or rows sent from n8n. This recipe starts from a Google Sheet that already holds the month's metrics. How the sheet is filled is up to you: by hand, from an export, or by another workflow that writes rows with n8n's Google Sheets node.
Can each client get a PDF of the report? +
Not from this workflow. A split document, one file per client, delivers Google Slides decks and no PDFs. For a PDF, download it from Google Slides, or generate that client as a single run from a document without split, where Also generate PDF applies.
Can the report list several pages or queries per client? +
Yes. Keep them in a second tab of the same spreadsheet with one row per page and a Client column, add a data set on that tab set to Only matching rows with the match key {{ client }}, and bind a slide to its subset with a capacity equal to the number of rows the slide has room for. On that slide the rows are written as numbered placeholders, counted from 1.
Does it send the report to the client? +
No. SourceToDocs delivers to Google Drive and returns links. Most agencies want a person to read the deck before it goes out, so the link in the sheet is the handover. Add a Gmail node after the last step if you want n8n to email the link to the account manager.