Multi-site GA4 dashboard with one-click client reports

By General Input

See every Google Analytics property your login can reach in one table, catch broken tracking instantly, and let an agent write each client's monthly report.

Integrations

  • Google Analytics
  • Google Docs
  • Google Sheets

Type

App

Categories

  • Marketing
  • Operations

Build me an app that replaces the monthly GA4 reporting sprint I run across several websites. I manage multiple Google Analytics properties, some for my own sites and some for clients, and today reporting means exporting from each property one at a time into fragmented spreadsheets. I want one board that shows the whole portfolio and can write each client's monthly report for me.

The app opens on a portfolio table with one row per GA4 property my login can reach. Discover the properties automatically with the Google Analytics List Account Summaries operation and use the numeric property IDs it returns, so I never type or paste a property ID anywhere. Show the account name alongside the property name, since one login often spans several client accounts. Cache the discovered list so the board loads fast, and give me a refresh action that rediscovers properties when I add or lose access to a client.

For each property, pull last 30 days versus the prior 30 days with Run Report (GA4), for total users, sessions, engagement rate and key events. Run Report accepts two date ranges in a single request and labels each returned row with which range it came from, so fetch both windows in one call per property rather than two. Each row shows the current-period value, the prior-period value and the percent change for each metric. Sort so the biggest decliners are at the top, because the drops are what I need to act on, and let me flip the sort to biggest gainers or alphabetical when I am just looking something up.

Properties that come back with zero rows get pinned above everything else in a distinct check tracking state, styled as a warning rather than as a row of zeros. Silent tracking breakage is the single thing I most need to catch, and a property that has genuinely stopped reporting looks identical to a slow month unless you call it out. Handle the failure cases separately too: if a property returns a permission error or the request fails, mark that row as unavailable with the reason instead of folding it into the check tracking group, so I can tell a lost login from a broken tag.

Clicking a row opens a drill-down panel for that property covering the same selected window. The panel shows channel mix by session default channel group, top landing pages by landing page plus query string, and the device category split, each with sessions and engagement rate and each compared against the prior period the same way the main table is. All three come from Run Report (GA4) scoped to that one property. Let me switch the window for the whole board between last 30 days versus prior 30 and last calendar month versus the month before, and have the drill-down follow whatever the board is set to.

The board is backed by a Google Sheets tracker that I point it at once in settings. Read that sheet with the Sheets values operations, using Batch Get Values so a single call covers the tracker rows and the target column. Every property row on the board shows when its last report went out and links straight to the Google Doc for it, resolved by matching the property ID in the tracker. The sheet also holds a per client monthly traffic target, and the board compares the current window's users against that target, showing progress and whether the property is pacing ahead or behind. Let me edit a target inline on the board and write it back with Update Values, and if the tracker sheet is empty on first use, lay down the header row with Update Values so the columns are right from the start: property ID, property name, month, users, sessions, engagement rate, key events, percent change versus prior period, monthly users target, report date and document link.

Every row also has a Write this month's report button that kicks off a background agent scoped to that single property. The agent runs the period comparison with Run Report (GA4), then the channel report and the landing page report for the same property and window, and reads the tracker with the Sheets values operations so it knows that client's monthly target and what last month's report said. It then writes a client-ready narrative: what moved, why it likely moved based on which channels and landing pages drove the change, how the property is tracking against its target, and what to do next. It should read like something I can send to a client with light editing, not a table dump, and it should name specific channels and pages rather than generic statements about traffic being up or down.

The agent creates the report with Create Document in Google Docs, titled with the client or property name and the month, and then fills it in with Batch Update Document. Give the document real structure: a headline summary at the top, then the numbers for the period, then the channel and landing page analysis, then recommendations. Remember that Docs indexes shift as content is inserted, so build the batch carefully and apply heading and emphasis styling in the same batch rather than in a long chain of one-off edits.

Once the document is written, the agent appends a row to the tracker with Append Values in Google Sheets carrying the property ID and name, the month, the headline numbers, the percent change and the document link. The board picks that row up on its next read, so the property's row immediately shows a fresh report date and a working link. While a report is generating, show that state on the row so I can fire off several at once and watch them land, and surface a clear error on the row if a run fails so I can retry it.

Two practical notes. List Account Summaries lives on the Google Analytics admin host while the reporting operations live on the data host, and the same read-only Analytics access covers both. Google Analytics is read-only in this app, so every write goes to Google Docs or Google Sheets and nothing is ever written back into Analytics. Fan the per-property report calls out with sensible concurrency and back off on rate limit responses, because a portfolio of a dozen or more properties can otherwise hit the Analytics quota on a single board load.

Related prompts

Explore more prompts
Call overdue Xero customers with an AI collections agentLocal listing health board for every location you manageLet support send one-off Loops emails without an engineerStop cold emails to anyone with a live deal in PipedriveiMessage campaign console with pre-flight checks and delivery boardA searchable RFP answer library your bid team drafts fromLinkedIn Ads budget pacing dashboard for every client accountFront desk appointment confirmation board for the next 3 daysGive your team Looker numbers without buying more seatsBuild audience segments from product usage and push to Loops