Generate a proposal from a Google Sheets row with n8n
Mark a row Ready and the workflow builds the proposal from your Google Docs template, saves the Doc and a PDF to Google Drive, and writes the link back into the sheet.
- Source
- Google Sheets
- Output
- Google DocsPDF (single runs only)
- 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
Google Sheets Trigger: Row Added or Updated
Outputs the rows of your deals sheet that were added or edited since the last check.
- 02
If: Status is equal to Ready
Only rows you have marked Ready continue, so half-filled rows never produce a proposal.
- 03
Loop Over Items: Batch Size 1
The SourceToDocs node starts one run for all the items it receives. The loop hands it one row at a time, so two deals marked Ready together still get one proposal each.
- 04
SourceToDocs: Document, Generate
Rows Come From is set to the Map Columns mode. Client, Project, Scope and Price come from the row; Valid until is thirty days from the run. Because this is a single run, switching on Also generate PDF delivers a PDF beside the Google Doc.
- 05
Google Sheets: Update Row
Writes file_url into the Proposal link column and changes Status, which also stops the same row from being generated twice.
| Google Sheets field | Template placeholder |
|---|---|
| Client | {{ client }} |
| Project | {{ project }} |
| Scope | {{ scope }} |
| Price | {{ price }} |
| (run date + 30 days) | {{ valid_until }} |
Or have Claude set it up
The Proposals, quotes and contracts skill
works through the SourceToDocs connector at https://app.sourcetodocs.com/api/mcp. Install the skill, connect, then paste:
Use the sales-documents skill. My deals are in the Google Sheet "Deals", one row per deal, with the columns Deal ID, Client, Project, Scope, Price and Valid until. I will pick the sheet, the Google Docs proposal template and the Drive folder when you ask. Generate the proposal for one Deal ID that I will give you, as a Google Doc with a PDF. Show me which placeholder each column fills before you run anything.
To generate a proposal from a Google Sheets row in n8n, trigger on added or updated rows, let only rows marked Ready through, pass the row’s columns to the SourceToDocs node to fill your Google Docs proposal template, and write the returned link back to the sheet. One row is one run, so SourceToDocs can deliver a PDF next to the Google Doc. The build is five nodes, described below.
What you need
- A Google Sheet with one row per deal and the columns
Deal ID,Client,Project,Scope,Price,StatusandProposal link. Deal ID must be unique per row. - A simple proposal template in Google Docs with just the placeholders
{{ client }},{{ project }},{{ scope }},{{ price }}and{{ valid_until }}. The business proposal 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 Docs connection for the template and a Google Drive connection for delivery. Every tile is a separate connection: Google Slides or Google Drive does not cover Google Docs.
- n8n, self-hosted or Cloud, with the SourceToDocs node installed. In n8n, open Settings, then Community nodes, and install
@twovmodules/n8n-nodes-sourcetodocs. On n8n Cloud, add it from the nodes panel, where it is listed as a verified node. - A Google Sheets credential in n8n.
Set up the document in SourceToDocs
The template and its settings live in SourceToDocs. n8n only sends the row.
- Create a Google Docs document.
- Upload a small CSV with the header row
Client,Project,Scope,Price,Valid untiland one sample line as the data source; it becomes a data set. The sample is enough, because the workflow sends the real rows in place of reading the source. - Each column gets an alias, a snake-case identifier derived from its name. The template uses the alias: column
Valid untilis{{ valid_until }}. - On the Document step, pick your Google Doc. Its Variables panel lists the exact placeholders for your data set; click one to copy it. Docs has no slide mapping step.
- Add a Google Drive distribution and choose the folder.
- Switch on Also generate PDF in the Output card.
- Leave split off. A split document produces no PDFs.
Build it in n8n
Add the nodes in this order. Connect the true output of If to Loop Over Items, the loop output to SourceToDocs, SourceToDocs to the Google Sheets node, and that node back into Loop Over Items.
| Node | Operation | Key settings |
|---|---|---|
| Google Sheets Trigger | Trigger On: Row Added or Updated | Document and Sheet: your deals sheet. Optional: under Options, set Columns to Watch to Status so edits to other cells do not start the workflow. |
| If | One condition | {{ $json.Status }} is equal to Ready. |
| Loop Over Items | Batch Size: 1 | No other settings. |
| SourceToDocs | Resource: Document. Operation: Generate | Document: your proposal document. Rows Come From: This Workflow — Map Columns. Data Set: the one with the five columns. Columns: see below. Wait for Completion stays on, which is the default. |
| Google Sheets | Operation: Update Row | Document and Sheet: the same deals sheet. Column to match on: Deal ID. Values: see below. |
The five column values in the SourceToDocs node:
| Column | Value |
|---|---|
| Client | {{ $json.Client }} |
| Project | {{ $json.Project }} |
| Scope | {{ $json.Scope }} |
| Price | {{ $json.Price }} |
| Valid until | {{ $now.plus({ days: 30 }).toFormat('d LLLL yyyy') }} |
The values the Google Sheets node writes:
| Column | Value |
|---|---|
| Deal ID | {{ $('Loop Over Items').item.json['Deal ID'] }} |
| Proposal link | {{ $json.file_url }} |
| Status | Generated |
The Column names are the data set’s column names, case included, not the template placeholders, which use the aliases.
Mapped values are sent as they resolve, so format Price in the sheet or in the expression the way it should read in the proposal.
Which link ends up in the sheet
The SourceToDocs node returns file_url and file_name at the top level of its output, and that link is what the last node writes. With Also generate PDF on, the deliveries list in the same output holds one entry per destination, and a Google Drive entry’s result carries pdf_url for the PDF. To keep both links, add a PDF link column and set it to {{ $json.deliveries[0].result.pdf_url }}.
When n8n’s Google Docs node is enough
n8n’s own Google Docs node can create, read and update a document. For a one-page letter with a few fields, copy the template with the Google Drive node and replace the placeholders one by one; exporting the PDF and moving the file are further steps. The SourceToDocs node does that as one Generate step, from a template whoever owns the proposal design can keep editing without touching the workflow. The n8n node page has the comparison table.
Do it with Claude instead
If you would rather ask for a proposal than build a workflow, the sales-documents skill lets Claude do the setup through the SourceToDocs connector. Claude reads the columns of your deals sheet or a CSV export of it, checks them against the placeholders in your Google Docs template, sets the Google Drive folder, switches on the PDF and runs the deal you name. You connect Google and pick the sheet, the template and the folder yourself from links Claude gives you. Claude cannot edit the template.
Three things to know before you choose this route:
- The sheet needs one more column for this route:
Valid until. It is not in the list under What you need, because the n8n workflow works out that date itself. Claude prints what is in the sheet and calculates nothing, and the prompt on this page assumes the column is there. - Claude works when you ask. It does not watch the sheet, so marking a row Ready does nothing until you tell Claude to generate that deal, and it does not write the link back into the sheet. For a proposal that appears when the row changes, use the n8n workflow above.
- The PDF rule is the same as in n8n. A PDF comes with a single run, so Claude generates one deal per run when you want the PDF. A run that splits into one Google Doc per deal covers many deals at once and delivers no PDFs. Claude asks which you want before it configures anything.
Where this fits
This workflow covers the simplest case: one row, one proposal, a person sending it. When proposals come from a CRM, need approval before they go out, or carry pricing rules, the proposal automation guide covers the wider design.
Related
- proposal automation: the full guide this recipe belongs to.
- Free business proposal template for Google Docs: the template this workflow fills.
- The SourceToDocs n8n node: every action and setting.
- The SourceToDocs MCP server: what Claude can do through the connector.