Google reviews to BigQuery
Every Google review as a row in your own project, carrying the site that earned it. Which means the question stops being what the rating is and becomes which site diverges from the ones that look like it.
- Set up in under five minutes
- No demo required
They love how easy we've made it
10 000 Slack notifications

Online Pet Supplies Retailer
6000 reviews routed to Zendesk

European Bank
Monitoring 12 platforms

Marketing Software Company
100 000 reviews across 97 tours

Tour operator in Iceland
4500 locations monitored

Luggage Storage & Lockers
5000 AI replies generated

Sushi Restaurant Chain
The question is which site diverges
Google Business Profile shows a rating per location but never puts them side by side. Reviewflowz writes the site name onto every review row, so thirty-one sites between 4.5 and 4.7 and one at 3.4 is a GROUP BY and an ORDER BY. The whole estate drifting together reads as a price change. One site falling while its neighbours hold is a local problem.
-- which sites are behind their own region
SELECT r.location,
ROUND(AVG(r.score), 1) AS rating,
COUNT(*) AS reviews
FROM `halcyon-analytics.reviews.google_reviews` r
JOIN `halcyon-analytics.ops.sites` s USING (location)
WHERE r.review_date >= '2026-03-01'
GROUP BY r.location
ORDER BY rating How the rows actually reach BigQuery
There is no managed BigQuery destination. Reviewflowz keeps a Google Sheet current in your own Drive: a new review is a new row within half an hour, and an edit updates its row. One CREATE EXTERNAL TABLE against the sheet URL and google_reviews queries like any other table. For a native partitioned table, load from the Review API or its webhook instead.
reviews Sheet in
your Drive External table
in BigQuery
CREATE EXTERNAL TABLE
`halcyon-analytics.reviews.google_reviews`
OPTIONS (
format = 'GOOGLE_SHEETS',
uris = ['https://docs.google.com/spreadsheets/d/1a9F...'],
skip_leading_rows = 1
) Reads the sheet at query time, so there is nothing to schedule and nothing to keep alive.
Try it Free for 14 days
Your review history imports the moment you connect, so there is something to reply to from the first minute.
Join it to what you already keep per site
Every multi-site business keeps a table with a row per site: revenue, staffing hours, footfall, the date of the last refit. Google reviews arrive tagged by site, so combining them is a JOIN. Rating beside rota hours shows whether the site everyone complains about is the site nobody staffed. Join your own segments and compare a site to its peers.
A table, not a report
One row per Google review: location, review id, timestamp, score, full text, detected language, tags and a link back to the review on Maps. The text is a STRING column, so the term you care about is a WHERE clause. Language is detected from the text itself. The table carries the review, not the reply, so reply coverage per site is not in it.
One row per review, tagged to the site
| review_id | STRING | Stable, so updates land in place |
| review_date | TIMESTAMP | When the review was posted |
| score | FLOAT64 | 1.0 to 5.0 |
| review_text | STRING | The full text, queryable |
| language | STRING | Detected from the text |
| tags | STRING | Themes, filled as reviews arrive |
| review_url | STRING | Back to the review on Google Maps |
Google gives one profile per location, so the site name is on every row.
FAQs
Is there a native BigQuery connector?
No, and it would be dishonest to imply one. Reviewflowz syncs a Google Sheet in your own Drive, and BigQuery reads that sheet as an external table with a single CREATE EXTERNAL TABLE statement. If you would rather have a native partitioned table, the Review API plus a scheduled load job gets you there. Both are ordinary work for a data team, and neither one needs a demo.
Does the location really land on every row?
Yes. Google gives you one profile per location, and Reviewflowz keeps that one-to-one, so every review row carries the site it belongs to. It arrives as the location name Google holds rather than as an id of yours, so you declare that column as location when you create the external table and map the names to your own site keys once. After that it is an ordinary join key.
How current is the table?
The sheet resyncs every 30 minutes, and an external table reads the sheet at query time, so a query you run now sees whatever the last sync wrote. A load job into a native table is as current as whatever schedule you give it.
Which columns does the table have?
The synced sheet has a fixed 28 column header, one row per review: the review id, the location, the platform, the review date, the score, the title, the full text, the detected language, the reviewer name, the tags, a link back to the review, and the rest. There is no reply column and there are no per-platform tabs, so everything sits in one flat table you can point a schema at.
Does the first load include our Google review history?
Yes, on a paid plan: one click loads every past Google review across your locations, so the trend line is full from day one rather than in three months. During the free trial new reviews arrive as they are posted, and the history loads once you subscribe.
What happens when a reviewer edits or deletes their review?
The row updates in place with the new score and text, so a query over it moves with the correction. When a review comes off your Google listing, its row goes on the next sync, which means the table never holds a version of the truth that Google no longer does.
Do I need a demo to get started?
No. Connect your Google Business Profile and the Google Sheet yourself in under five minutes, then run one CREATE EXTERNAL TABLE against it. 14 day free trial, no credit card.
A rating on its own explains nothing. The site beside it does.
Set up in under five minutes. No demo required.