Nightly Looker report snapshot into a Google Sheets log
Every night we run your saved Looker report, stamp each row with the date, and append it to a Google Sheet so you keep the history Looker overwrites.
Every night at 11pm, take a snapshot of one saved Looker Look and append its rows to a Google Sheets tab, so I build up a historical record that Looker itself does not retain once the underlying data is overwritten. This is a straight deterministic copy. Run the Look, stamp the date, append the rows. No summarizing, no filtering, no interpretation of the values.
Trigger: cron, every day at 23:00 in my timezone.
Step one, run the Look. Use the Looker Run Look operation with the json result format, passing the Look ID I configure. Looker returns ids as strings even when they look numeric, so treat every returned value as text and do not coerce types. If the Look returns more rows than a single page, page through using limit and offset, adding limit to offset until a short or empty page comes back, and collect all rows before writing anything. If the Look returns zero rows, end the run without touching the spreadsheet.
Step two, stamp the run date. Prepend a single Run Date column to every row, holding the date the workflow ran in YYYY-MM-DD format. This date column is the entire point of the workflow: it is what turns a series of identical-looking snapshots into a usable time series.
Step three, pick the quarterly tab. Derive the tab name from the run date using the pattern Snapshot YYYY-Qn, for example Snapshot 2026-Q3. Read the spreadsheet's existing tab names with the Google Sheets Get Spreadsheet operation. If the tab for the current quarter does not exist yet, create it with Batch Update Spreadsheet and write a header row first: Run Date, followed by the Look's field labels in the exact order Looker returned them.
Step four, append the rows. Use the Google Sheets Append Values operation against the current quarter's tab, which appends after the last row of the detected table. Column order is fixed and must never shift: Run Date first, then the Look's columns in the order established by that tab's header row. If a field the header expects is missing from a given row, write an empty cell rather than shifting the remaining values left. If the Look gains new fields mid-quarter, keep writing into the existing header order for the current tab; the next quarter's new tab will pick up the new shape. Send values as raw text so dates and ids are not reinterpreted by the spreadsheet, and split large result sets into batches of a few hundred rows per append call to stay well under the Sheets request size limit.
Make these configurable at the top of the workflow: the Looker Look ID, the destination spreadsheet ID, the tab name prefix, the rollover period (quarterly by default), and the timezone the schedule and date stamp use.
Example output
What does this prompt do?
- Runs one saved Looker report every night at 11pm and pulls back every row it returns.
- Adds the run date to each row, then appends them to a Google Sheet so tonight's numbers sit under last night's instead of replacing them.
- Keeps the column order fixed, so the charts and pivot tables you build on top of the sheet do not break.
- Starts a fresh tab each quarter so no single tab grows unbounded and slows the spreadsheet down.
What do I need to use this?
- A Looker account with permission to open and run the saved report you want to snapshot.
- Looker credentials, which a Looker admin creates for you from the Admin area.
- The saved report you want to capture, and its ID, which appears in the report's web address.
- A Google account with edit access to the spreadsheet that will hold the history.
- A destination Google Sheet, ready to receive a new tab each quarter.
How can I customize it?
- Change the timing. Nightly at 11pm suits most reporting, but hourly, every weekday morning, or weekly all work the same way.
- Point it at a different saved report, or run several reports into separate tabs of the same spreadsheet.
- Switch the tab rollover from quarterly to monthly or yearly, depending on how many rows your report returns each night.
FAQs
Why not use Looker's own scheduled delivery to a spreadsheet?
What happens if the report returns no rows one night?
Will this break the charts and pivot tables I build on the sheet?
How large can the spreadsheet get before it slows down?
Does this work with any saved Looker report?
Does it change anything inside Looker?
Related templates
Every Monday, check every S3 bucket for public exposure, missing encryption and weak backup settings, then get the risks ranked in Slack.
Every weekday at 7am, sign in to the tender portals you track, filter new notices against your bid criteria, and open a deal for the ones worth chasing.
Every weekday at 4pm, spot the threads that went quiet, stage a ready-to-send nudge in your mailbox, and get a ranked Slack recap.
Keep a spreadsheet of your most important senders, and every email from one gets labeled, posted to your team channel, and logged automatically.
The moment an order is fulfilled, we register it with Yotpo so the review request is timed off real delivery, and we log every sync so failures never go unnoticed.
Every night at 11pm we compare the day's Shopify orders with your Zoho Books invoices and payments, and flag only what does not match.
Keep the history Looker throws away.
Set this up once and every night's numbers stay put, ready to chart, pivot, and compare months later.