On a schedule
Weekly GA4 top pages report in Google Sheets
Every Monday a new tab lists last week's top 50 pages by views, with users, engagement time and change against the week before.
- Runs
- On a schedule
- Apps
- Google Analytics, Google Sheets
- AI
- Not needed
- Access
- analytics.readonly; Google Sheets read+write
Send this to your assistant
Create a ClickRuntime automation: every Monday at 7am, add a new tab to my GA4 sheet named after last week with the top 50 pages by views, their users, average engagement time and percentage change in views from the week before.
First time? Adding ClickRuntime to your assistant takes about two minutes.
Why use it
Why teams use this automation
Content teams want to know every week which pages are pulling their weight and which are slipping. In GA4 that means building an exploration, picking dates and comparing two periods by eye.
This automation adds a tab every Monday with the top 50 pages by views, their users and engagement time, and how each moved compared with the week before.
Content marketers, SEO leads and site owners use it as the agenda for their weekly content review.
What you get out of it
Winners and losers at a glance
The change column shows which pages grew or dropped against last week.
New pages spotted
Freshly published pages are marked new, so launches are easy to track.
Engagement next to views
A page with many views but little time spent may need better content or a clearer call to action.
Weekly archive
Each week keeps its own tab, so you can look back at any week.
No GA4 explorations to maintain
The report is built from the Data API, not from saved views that break.
How it works
What happens, step by step
Every Monday ClickRuntime runs two GA4 reports by page: last week and the week before.
It picks the 50 pages with the most views last week and works out the change from the previous week.
A new tab named after the week, such as Week of 2026-11-02, is added with the table.
Before it runs live
- Connect Google Analytics
- Connect your Google Sheets account and pick the spreadsheets it may use
What you get
Build your own
Need it to work differently?
Your own rules
Conditions, thresholds, filters and exceptions, written the way you'd explain them to a colleague.
Any number of apps
One automation can read from one app and update several others. Over 248 apps are ready, and anything with an API works too.
AI where it helps
Summaries, classification, extraction and drafts use ClickRuntime's built-in AI, with no extra key.
On a schedule or on each event
Runs as often as every 5 minutes, or the moment an app sends an event, and keeps track of what it already handled.
Changes you can ask for
- Run it at a different time, more or less often, or only on weekdays
- Add an AI step, for example to summarize, sort or draft a reply
- Add another app, for example also send it to Slack
- Combine it with other Google Analytics and Google Sheets steps into one automation
Under the hood
The code that runs this automation
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
from datetime import date, timedelta
from clickruntime import on_trigger, credentials, http
PROPERTY = "123456789"
SHEET_ID = "your-spreadsheet-id"
def ga(body):
r = http.post(f"https://analyticsdata.googleapis.com/v1beta/properties/{PROPERTY}:runReport", json=body,
headers={"Authorization": f"Bearer {credentials.connection('google', 'work')}"})
r.raise_for_status()
return r.json().get("rows", [])
def pages(start, end, limit):
rows = ga({"dateRanges": [{"startDate": str(start), "endDate": str(end)}], "dimensions": [{"name": "pagePath"}],
"metrics": [{"name": "screenPageViews"}, {"name": "totalUsers"}, {"name": "userEngagementDuration"}],
"orderBys": [{"metric": {"metricName": "screenPageViews"}, "desc": True}], "limit": limit})
return {r["dimensionValues"][0]["value"]: [float(v["value"]) for v in r["metricValues"]] for r in rows}
@on_trigger
def run(event):
monday = date.today() - timedelta(days=date.today().weekday() + 7)
this, prev = pages(monday, monday + timedelta(days=6), 50), pages(monday - timedelta(days=7), monday - timedelta(days=1), 1000)
table = [["Page", "Views", "Users", "Avg engagement (s)", "Change in views"]]
for path, (views, users, secs) in this.items():
before = prev.get(path, [0])[0]
change = f"{(views - before) / before:+.0%}" if before else "new"
table.append([path, int(views), int(users), round(secs / max(users, 1)), change])
name = f"Week of {monday}"
book = build("sheets", "v4", credentials=Credentials(credentials.connection("google", "work")), cache_discovery=False).spreadsheets()
book.batchUpdate(spreadsheetId=SHEET_ID, body={"requests": [{"addSheet": {"properties": {"title": name, "index": 0}}}]}).execute()
book.values().update(spreadsheetId=SHEET_ID, range=f"'{name}'!A1", valueInputOption="RAW", body={"values": table}).execute()
return {"tab": name, "pages": len(table) - 1}FAQ
Common questions
Why a new tab each week instead of one long table?
How is engagement time worked out?
What does "new" mean in the change column?
What permissions does it need?
Does it need AI?
How many runs does it use?
Can I change how it works?
Related
You might also like
Log daily GA4 traffic by source to Google Sheets
Each morning yesterday's GA4 sessions, users and key events per source / medium are appended to a Traffic tab.
See how it worksLog your weekly website numbers to a sheet
Every week your key GA4 numbers are added as a row in your reporting sheet, and you get an email summarising what changed.
See how it worksLog daily website KPIs and get alerted when one drops
Every day yesterday's key numbers go into a sheet, and you are alerted in Slack and by email if any falls well below its recent average.
See how it worksKeep exploring
Set up “Weekly GA4 top pages report in Google Sheets” from your assistant
Copy the prompt above, or connect your assistant first. Free plan, no credit card.