Hello, tech enthusiasts! ๐
Every Monday, many office teams do the same thing. They open Google Analytics, click through a few reports, copy the visitor numbers, and paste them into a spreadsheet. It takes 20 minutes, and it is easy to copy the wrong cell.
What if Python could do this for you? Google Analytics 4 (GA4) has an API for this. An API is like a waiter in a restaurant: you ask for something, and it brings the data back to your table. The GA4 API is called the Google Analytics Data API.
Today we will set it up step by step and get the data into a pandas table.
What you need
- A GA4 property where you are an Administrator (so you can add a new user)
- A Google account that can create a Google Cloud project (https://console.cloud.google.com)
- Python 3.9 or newer (https://www.python.org)
- These packages:
pip install google-analytics-data pandas openpyxl
Step 1: Create a Google Cloud project
A Google Cloud project is a folder that holds your API settings.
- Open the Google Cloud Console.
- At the top, click the project list, then New Project.
- Give it a name like “analytics-reports” and click Create.
Step 2: Turn on the Analytics Data API
Google keeps APIs switched off until you need them.
- In your new project, open APIs & Services โ Library.
- Search for Google Analytics Data API.
- Click it, then click Enable.
Step 3: Create a service account and a key
A service account is a robot user. It is not a person, so your script can log in without your own password.
- Go to IAM & Admin โ Service Accounts โ Create service account.
- Name it “ga4-reader” and finish the steps. It does not need any Cloud roles for this task.
- Open the new service account, go to the Keys tab, and choose Add key โ Create new key โ JSON.
- A file downloads. Rename it to
ga4-key.jsonand keep it in your project folder.
This JSON file is like a house key. Do not email it, do not put it in shared folders, and do not upload it to GitHub. If you use Git, add it to your .gitignore file.
Step 4: Give the robot access to GA4
The robot user has an email address. It looks like ga4-reader@your-project-id.iam.gserviceaccount.com. You can find it on the service account page, or inside the JSON file as client_email.
- Open Google Analytics and click Admin (the gear icon).
- Under your property, open Property access management.
- Click + โ Add users, paste the robot’s email, and choose the Viewer role.
- Click Add.
Viewer is enough, because the script only reads data. Always give the smallest role that does the job.
While you are in Admin, open Property details and copy the Property ID. It is a number like 123456789.
Step 5: Ask for a report
Now the fun part. We ask GA4 for daily active users and sessions for the last 28 days, split by country.
Dimensions are the “by what” part, like date or country. Metrics are the numbers, like users or sessions.
from google.analytics.data_v1beta import BetaAnalyticsDataClient
from google.analytics.data_v1beta.types import (
DateRange,
Dimension,
Metric,
RunReportRequest,
)
PROPERTY_ID = "123456789" # your GA4 property ID
KEY_FILE = "ga4-key.json" # the service account key
# Log in with the robot user's key
client = BetaAnalyticsDataClient.from_service_account_file(KEY_FILE)
request = RunReportRequest(
property=f"properties/{PROPERTY_ID}",
date_ranges=[DateRange(start_date="28daysAgo", end_date="yesterday")],
dimensions=[Dimension(name="date"), Dimension(name="country")],
metrics=[Metric(name="activeUsers"), Metric(name="sessions")],
limit=10000,
)
response = client.run_report(request)
print("Rows received:", response.row_count)
You can also use real dates like "2025-08-01". Words like "today", "yesterday" and "7daysAgo" work too.
Step 6: Turn the answer into a pandas table
The answer comes back as rows. Each row has dimension values and metric values, in the same order you asked for them. We put them into a DataFrame (a pandas table).
import pandas as pd
dim_names = [d.name for d in response.dimension_headers]
met_names = [m.name for m in response.metric_headers]
records = []
for row in response.rows:
record = {}
for name, value in zip(dim_names, row.dimension_values):
record[name] = value.value
for name, value in zip(met_names, row.metric_values):
record[name] = value.value
records.append(record)
df = pd.DataFrame(records)
# GA4 sends everything as text, so fix the types
df["date"] = pd.to_datetime(df["date"], format="%Y%m%d")
df[met_names] = df[met_names].astype(int)
df = df.sort_values(["date", "activeUsers"], ascending=[True, False])
print(df.head())
df.to_excel("ga4_report.xlsx", index=False)
GA4 sends dates as text like 20250830, so we convert them with a format. Now you have a clean table you can chart, filter, or send by email. ๐
Common problems
403 User does not have sufficient permissionsโ The robot email was not added in GA4, or you added it to a different property. Check Step 4.Google Analytics Data API has not been used in projectโ The API is not enabled in the same Cloud project as your key. Check Step 2.Field xyz is not a valid dimensionโ Use the API names, not the names you see on screen. For example,activeUsers, not “Active users”. Google lists them on the “API Dimensions & Metrics” page.- Numbers are a little different from the website โ GA4 may use sampling or thresholds, and today’s data is still being processed. Use
yesterdayas the end date for stable numbers.
Wrap-up
You created a robot user, gave it read-only access, and pulled real GA4 numbers into pandas. Your Monday copy-paste job is now one script.
Next idea: schedule the script to run every Monday morning with Windows Task Scheduler or cron, and save each report with the date in the file name.