Skip to main content

Generate a QBR deck per account from Airtable with n8n

On the first day of each quarter, one Google Slides QBR deck per account, built from your Airtable base, delivered to Google Drive, with the link written back to the account record.

Source
Airtable
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: first day of each quarter

    Trigger Interval is Custom (Cron) with the expression 0 8 1 1,4,7,10 *, which fires at 8am on the first day of January, April, July and October. Move the day later if your quarter's numbers land in Airtable after the quarter closes.

  2. 02

    SourceToDocs: Document, Generate

    Pick the split Google Slides document that reads your Airtable base. In its Split step, the Accounts table is the driver and the Split by expression {{ name }} gives one deck per account. The driver's own rows are not content, so every data set, Accounts included, is set to Only matching rows with a match key. Rows Come From stays on Connected Data Sources, the default, so the document reads Airtable 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

    Airtable: Record, Update

    Optional. With Wait for Completion on, the default, the SourceToDocs node outputs one item per deck, each with file_url and split_key, the account name that deck was generated for. This node matches the account record on Name and writes file_url into a QBR deck link field.

Airtable fields and the template placeholders they fill
Airtable field Template placeholder
Accounts: Name {{ name }}
Accounts: Tier {{ tier }}
Accounts: Executive sponsor {{ executive_sponsor }}
Accounts: Primary CSM {{ primary_csm }}
Accounts: Renewal date {{ renewal_date }}
Outcomes: Outcome (first row) {{ outcomes[1].outcome }}
Outcomes: Target (first row) {{ outcomes[1].target }}
Outcomes: Actual (first row) {{ outcomes[1].actual }}
Outcomes: Delta (first row) {{ outcomes[1].delta }}

Or have Claude set it up

The QBR decks skill works through the SourceToDocs connector at https://app.sourcetodocs.com/api/mcp. Install the skill, connect, then paste:

Use the qbr-decks skill. My accounts are in the Airtable base "Customer Success", table "Accounts", one row per account, with linked "Outcomes" records that carry Quarter, Outcome, Target, Actual and Delta. I will pick the Google Slides QBR template and the Drive folder "QBRs 2026" when you send me the links. Set up one deck per account, with the outcomes slide showing only that account's rows for Q4 2026. Show me the placeholder mapping and the number of decks before you run anything.

Get the skill file

To produce a QBR deck per account from n8n, schedule the workflow once a quarter and let the SourceToDocs node start a split document that reads your Airtable base: one Google Slides deck per account, delivered to Google Drive. The node returns one item per deck, so an optional last node writes each link back to the account record. The build is three nodes. Most of the work is the one-time setup of the split document, described first.

What you need

  • An Airtable base with an Accounts table, one row per account, and at least one table of quarterly rows linked to it. This page uses Outcomes, with a linked Account field and the fields Quarter, Outcome, Target, Actual and Delta. Account names must be unique, because the name is what separates the decks. The QBR template post lays out the full five-table base and the five sections of the deck.
  • A QBR deck link URL field on Accounts, if you want the links written back.
  • A QBR template in Google Slides with a cover slide and an outcomes slide carrying the placeholders listed below. The QBR deck 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, an Airtable connection for the data, a Google Slides connection for the template and a Google Drive connection for delivery. Every Google tile is a separate connection.
  • 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 an Airtable credential in n8n if you use the last node.

Set up the document in SourceToDocs

The document reads Airtable itself. n8n only starts it.

  1. Create a Google Slides document and connect your Airtable base as its data source.
  2. Add a data set named Accounts on the Accounts table and tick the fields the cover slide prints: Name, Tier, Executive sponsor, Primary CSM, Renewal date.
  3. Add a data set named Outcomes on the Outcomes table. Tick Outcome, Target, Actual and Delta, then tick the linked Account field and Name under it. The match key in step 6 reads that linked name, and it can only read linked fields the data set picks.
  4. Add a subset on each data set with Add Subset. On the Outcomes subset, add a filter on Quarter for the quarter you report on.
  5. On the Split step, set the driver: your Airtable source, the Accounts table, and the Split by expression {{ name }}. Expressions use the column alias, a snake-case identifier derived from the field name. You get one deck per distinct value, and rows with a blank value are skipped.
  6. In the participation table on the same step, set both data sets to Only matching rows. The match key for Accounts is {{ name }} and for Outcomes it is {{ account.0.name }}. The driver’s own rows are not content: the Accounts data set on Only matching rows is what puts each account’s own row on its cover slide.
  7. Press Estimate to see the number of decks before anything runs.
  8. In Template Config, add a dynamic_slide entry on the Accounts subset for the cover slide and one on the Outcomes subset for the outcomes slide, with a capacity equal to the number of outcome rows the slide has room for. 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.
  9. Add a Google Drive distribution and choose the folder.

On the outcomes slide, each row slot is written with an index, starting at 1: {{ outcomes[1].outcome }}, {{ outcomes[1].target }}, {{ outcomes[1].actual }}, {{ outcomes[1].delta }}, then [2], [3] and so on up to the capacity. The Slide Editor lists each slide’s placeholders as Matched, Available or Unresolved, which is the quickest check that the names in your template agree with the data set.

Usage metrics, risks and asks follow the same pattern as Outcomes: a data set on the table with the linked account name ticked, a subset filtered to the quarter, Only matching rows with the match key {{ account.0.name }}, and a dynamic_slide entry mapped to its slide.

Keeping the quarter filter current

The quarter filter is a saved setting, so it does not move on its own. Either change its value before each cycle, or filter on a field your base computes. A formula field is filtered by its result type, so a formula in Airtable that marks the current quarter’s rows gives the subset a value to filter on that you do not have to edit. Check the result with the data set preview before you rely on it.

Build it in n8n

Add the nodes in this order and connect them in a line.

NodeOperationKey settings
Schedule TriggerTrigger Interval: Custom (Cron)Expression: 0 8 1 1,4,7,10 *. That is 8am on the first day of January, April, July and October, in the workflow’s timezone.
SourceToDocsResource: Document. Operation: GenerateDocument: your QBR document. Rows Come From: Connected Data Sources, the default. Under Options, raise Max Wait above the default 300 seconds if you have many accounts. Wait for Completion stays on.
AirtableResource: Record. Operation: UpdateBase and Table: your base, Accounts. In Columns, match on Name in place of the record ID. Values: see below.

The values the Airtable node writes:

ColumnValue
Name{{ $json.split_key }}
QBR deck link{{ $json.file_url }}

The Schedule Trigger also offers Trigger Interval Months with Months Between Triggers set to 3, plus Trigger at Day of Month and Trigger at Hour. The cron expression is used here because it names the four months outright.

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 account name that deck was generated for. The Airtable node runs once per item, which is why matching on Name with split_key puts every link on the right record. The Airtable node updates the first record that matches, one more reason account names must be unique.

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 quarter’s decks never mix with the next. With the default file name each deck is named after its account.

Or have Claude set it up

The nine setup steps above can be done by Claude instead of by hand. With the SourceToDocs connector added to Claude and the qbr-decks skill installed, paste the prompt from the block at the top of this page. Claude creates the document, attaches your Airtable base through the connected account, reads the placeholders in your template, configures the data sets, 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 account from a split run delivers Google Slides decks and no PDFs; a PDF with every deck means one run per account, which suits a handful of key accounts.

Two things stay with you. Claude sends links for you to pick the template and the Drive folder in Google’s own picker, and it cannot edit the template file, so a missing placeholder is yours to add in Google Slides. And Claude runs when you ask: the quarterly schedule is the n8n workflow above.

Where this fits

The workflow removes the copying, not the thinking. The CSM still owns the narrative, the risks and the asks on each deck before the meeting. When that prep is the bottleneck, or the numbers come from more than one system, the QBR automation guide covers the wider process. For the split setup itself in more depth, see the Airtable to Google Slides walkthrough.

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.
Can each QBR deck also be delivered as a PDF? +
Not from this workflow. A split document, one file per account, delivers Google Slides decks and no PDFs. If one account needs a PDF, download it from Google Slides, or generate that account as a single run from a document without split, where Also generate PDF applies.
How do I run QBRs for only some accounts? +
Filter the driver. On the Split step the driver carries its own filters, so you can keep one tier, one CSM or the accounts with a renewal coming up. Estimate on the same step shows how many decks the current settings produce before you run anything.
What if the batch takes longer than the node waits? +
The node waits 300 seconds by default. Raise Max Wait under Options for a large book of accounts. If the run is still going when the 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.
Does it email the deck to the CSM or the customer? +
No. SourceToDocs delivers to Google Drive and returns links. The CSM still writes the narrative and the asks before the meeting, so the link in the account record is the handover. Add a Gmail or Slack node after the Airtable node if you want n8n to notify the owner.