A spend dashboard answers a few plain questions. What did we spend this month? On what? With whom? How much of it was tax? Is anything unusual?
The charts are the easy part. The hard part is getting every receipt and invoice into rows with clean numbers, a date you can group by and a category. This tutorial builds the whole thing with tools most small teams already have: a Google Drive folder, a Google Sheet, a short Apps Script and Looker Studio.
If you don't want to build anything, skip to the no-code option at the end. If you're a developer feeding your own finance dashboard from code, receipt and invoice data for finance dashboards covers that route.
What you are building
- You drop receipts and invoices (PDF, JPG or PNG) into a Drive folder called
Receipts Inbox. - Every 15 minutes, a script sends new files to a parsing API, writes one row per document to a sheet, and moves the file to
Receipts Processed. Anything that can't be read goes toReceipts Needs Attention. - A rules table assigns a category from the merchant name.
- Summary tables and a Looker Studio report show spend by month, category and vendor.
You need a Google account and a DocuParse API key. Sign up free for one: the free plan covers 20 documents a month with full API access, which is enough to build and test this.
Step 1: Set up the sheet
Create a Google Sheet with two tabs.
The Expenses tab gets these headers in row 1:
| A | B | C | D | E | F | G | H | I | J | K | L | M |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Date | Month | Merchant | Category | Currency | Subtotal | Tax | Total | Type | Number | Needs review | File | Document ID |
Before you add any data, select columns B and J and set them to plain text (Format, Number, Plain text). Otherwise Sheets turns a month like 2026-10 into a date and strips leading zeros from document numbers like 000412.
The Rules tab maps merchant text to a category. Column A is the text to look for, column B is the category:
| Merchant contains | Category |
|---|---|
| shell | Fuel |
| uber | Travel |
| amazon web services | Software and hosting |
| staples | Office supplies |
| starbucks | Meals |
Matching is case-insensitive and partial, so shell matches "Shell Station #4471". Start with your ten most common vendors. You'll add more as you go.
Step 2: Create the three Drive folders
Make Receipts Inbox, Receipts Processed and Receipts Needs Attention in Drive. Open each one and copy the folder ID from the URL, the long string after /folders/.
Step 3: Add the script
In the sheet, open Extensions, then Apps Script. Replace the contents of Code.gs with this:
Then store your key so it isn't sitting in the code. In the Apps Script editor, open Project Settings, scroll to Script Properties, and add DOCUPARSE_API_KEY with your key as the value.
A few notes on the script:
payload: { file: blob }is how Apps Script sends a file as a form upload. Google's UrlFetchApp reference documents that an object payload containing a blob is sent as form data.- Extraction is a two-step flow: the first call returns a
document_id, andfetchResultfetches the finished result. Reading fields off the first response is the most common integration bug. - Each file is submitted only once. The script saves its
document_idin Script Properties, so if a result isn't ready yet, the next run fetches it instead of uploading the file again. Every submit counts toward your monthly documents, so this matters. - A file that is rejected or can't be read moves to
Receipts Needs Attention, and the reason is in the execution log. If the reason is your monthly limit, move the files back to the inbox once it resets. - Each run handles at most three files and waits at most about 12 seconds for each, which keeps runs well under Apps Script's 6-minute limit and inside the daily trigger allowance of a free Google account.
- Amounts come back as decimal strings like
"34.17", soNumber()turns them into real numbers you can sum. The JSON schema lists every field if you want more columns.
Step 4: Run it on a timer
Run processInbox once by hand from the editor. Google will ask you to authorize access to Drive, Sheets and external requests. Drop a test receipt in the inbox first so you can see a row appear.
Then open Triggers (the clock icon), add a trigger for processInbox, choose "Time-driven", and set it to every 15 minutes.
iPhone photos are often saved as HEIC, which isn't an accepted format. Either set the camera to "Most Compatible" so it saves JPG, or upload receipts through an app that converts them.
Step 5: Summary tables with QUERY
Add a Summary tab. These formulas assume one main currency, USD here. Change 'USD' to yours.
Spend by month and category:
=QUERY(Expenses!A:M, "select B, D, sum(H) where E = 'USD' and B is not null group by B, D order by B label sum(H) 'Spent'", 1)
Top ten vendors:
=QUERY(Expenses!A:M, "select C, count(C), sum(H) where E = 'USD' group by C order by sum(H) desc limit 10 label count(C) 'Documents', sum(H) 'Spent'", 1)
Tax paid per month:
=QUERY(Expenses!A:M, "select B, sum(G) where E = 'USD' and B is not null group by B order by B label sum(G) 'Tax'", 1)
Documents waiting for review:
=FILTER(Expenses!A:L, Expenses!K:K = "Yes")
That last one is your to-do list. Rows marked Needs review are documents the extractor flagged as not adding up. Open the file link, compare, and fix the row. For more checks you can add yourself, see six checks that catch bad extractions.
Step 6: The Looker Studio report
Sheets formulas are enough for one person. If you want something to share, Looker Studio is free and reads the sheet directly.
- Go to Looker Studio, create a blank report, and add the Google Sheets connector. Pick your spreadsheet and the
Expensestab. - Check the field types in the data source.
Dateshould be a date,Total,TaxandSubtotalshould be numbers, everything else text. - Add these charts:
- Scorecards for sum of
Total, sum ofTaxand record count. - A time series of
TotalbyDate, set to monthly. - A bar chart of
TotalbyCategory. - A table of
Merchant, record count and sum ofTotal, sorted by spend.
- Scorecards for sum of
- Add a drop-down control on
Currencyand a date range control at the top.
The currency control matters. A dashboard that adds 100 EUR and 100 USD into "200" is wrong in a way nobody notices. If you have meaningful spend in several currencies, add a column with the amount converted at the rate on the document date and chart that column instead.
Keeping the categories honest
The rules table does most of the work, but some rows will land in Uncategorized. Once a week:
- Filter
ExpensestoUncategorized. - Fix each category by hand.
- Add a rule for any vendor you expect to see again.
After a few weeks, most new rows get a category on arrival. Vendors that sell many kinds of things, like a supermarket or Amazon, may never be safe to categorize from the name alone. Leave those for a person, or split them using the line_items the API returns.
The no-code option
If you would rather not run a script, DocuParse API has a built-in spend dashboard. Upload documents in the dashboard, one at a time or as a batch, or send them through the API. The dashboard shows total spend, document count, total tax and average document value, with filters for date range, document type and currency. Pick one currency in the filter before you read Total Spend: with All currencies selected, it adds every currency together. You can export the data to CSV or JSON, or download a formatted PDF report.
A simple routine is to upload during the month, export the CSV at month end, and import it into its own tab. The QUERY formulas and Looker Studio report above work on that tab too once you point them at the matching column letters.
For other routes into a spreadsheet, including n8n, Make and Zapier, see how to convert PDF invoices to Excel or Google Sheets automatically. For the full picture, from capture to record keeping, start with the receipt and invoice data entry guide.