От халепа... Ця сторінка ще не має українського перекладу, але ми вже над цим працюємо!

cookies

Hi! This website uses cookies. By continuing to browse or by clicking “I agree”, you accept this use. For more information, please see our Privacy Policy

bg

How to Connect Google Analytics to Claude — No Developer Needed

author

Volodymyr Khmil

/

CEO

9 min read

9 min read

A step-by-step guide. Two files to copy, one command to run!

If you use Google Analytics to track your website, there is a way to stop opening dashboards and just ask Claude questions instead.

  • “How many people visited my site last week?”
  • “What are my most read pages this month?”
  • “Which country sends me the most traffic?”

Claude will fetch the real numbers and answer you directly.

Here is everything you need to set it up. No coding experience required — just follow each step in order.

Article content:

Step 1 — Create a read-only access pass for Claude

Step 2 — Give that access pass permission to see your analytics

Step 3 — Install one software package

Step 4 — Create a folder and add three files

File 1 — Copy this into a file named: SKILL.md

File 2 — Copy this into a file named: query_script.py

Step 5 — Test that it works

Step 6 — Ask Claude

If something goes wrong

What you will need before you start

A Google Analytics account (the current version, called GA4)

A Google account that has access to that Analytics property

Claude Cowork installed on your computer (or Claude Code)

Python installed on your computer (free — download from python.org if needed)

nerdzlab - nerdzlab image Alt

Step 1 — Create a read-only access pass for Claude

Think of this step as creating a special key that lets Claude read your analytics data — but nothing else. It cannot change anything, it cannot delete anything. Read only.

  1. Open your browser and go to: console.cloud.google.com. Sign in with the same Google account you use for Analytics.
  2. At the top of the page, click the project dropdown (it may say “Select a project”). Click New Project give it any name (e.g. “My Analytics”) click Create. Wait a few seconds, then select your new project from the dropdown.
  3. In the search bar at the top, type: Google Analytics Data API. Click the result click the blue Enable button.
  4. In the left menu, click IAM & Admin Service Accounts + Create Service Account. In the name field, type anything — for example: claude-analytics-reader. Click Create and Continue skip the next two steps Done.
  5. You will now see your new account listed. Click on it. Go to the Keys tab Add Key Create new key select JSON click Create. A file will download to your computer. This is your access key — keep it safe. Also copy the email address shown for this account: claude-analytics-reader@your-project-name.iam.gserviceaccount.com  you will need this email in the next step.

How to Connect Google Analytics to Claude

Step 2 — Give that access pass permission to see your analytics

The key from Step 1 exists, but Google Analytics doesn’t know about it yet. You need to invite it.

  1. Go to: analytics.google.com
  2. Click the gear icon (⚙️) at the bottom left this opens Admin settings.
  3. In the middle column (Property), click Property Access Management.
  4. Click the + button (top right) Add users. Paste in the email address from Step 1. Set the role to Viewer. Uncheck “Notify new users by email” (it’s not a real inbox). Click Add.
  5. While still in Admin, click Property Settings (middle column). Find the Property ID — it is a plain number, like 123456789. Write this number down. You will need it in Step 4.

Step 3 — Install one software package

Open the Terminal app on your computer. (On Mac: press Cmd + Space, type Terminal, press Enter. On Windows: press the Windows key, type cmd, press Enter.)

Type the following and press Enter:

pip3 install google-analytics-data --break-system-packages

Wait until you see “Successfully installed”. That is all for this step.

(The –break-system-packages part is required on modern Mac and Linux computers. It just tells the installer to go ahead — it is safe.)

Step 4 — Create a folder and add three files

On your computer, navigate to this folder:

  • Mac/Linux: the folder called .claude/skills/ inside your home folder
  • Windows: C:\Users\YourName\.claude\skills\

If the skills folder does not exist yet, create it.

Inside that folder, create a new folder called: google-analytics. Move the key file you downloaded in Step 1 into this folder. Rename that file to: your-credentials.json

Inside the google-analytics folder, create two new text files. Copy the contents below exactly into each one. Your folder should look like this when done:

.claude/skills/google-analytics/
├── SKILL.md ← copy content from File 1 below
├── query_script.py ← copy content from File 2 below
└── your-credentials.json ← the key file from Step 1

 

nerdzlab - nerdzlab image Alt

File 1 — Copy this into a file named: SKILL.md

```

name: google-analytics
description: “Query Google Analytics 4 data. Use when the user asks about website traffic, page views, sessions, user counts, conversions, top pages, traffic sources, or any analytics/metrics questions. Trigger on keywords like \”analytics\”, \”traffic\”, \”visitors\”, \”page views\”, \”sessions\”, \”GA4\”, \”bounce rate\”, \”conversions\”, \”top pages\”, \”referrals\”.”
metadata:
version: 1.0.0
# Google Analytics 4 Skill
Query GA4 property data using the Google Analytics Data API v1.
## Setup
– **Credentials**: Service account JSON key — place it in the same folder as query_script.py with the filename your-credentials.json. The script resolves the path automatically.
– **Property ID**: 123456789
– **Python dependency**: google-analytics-data (install: pip3 install google-analytics-data –break-system-packages)
## How to Use
Run the query script using its absolute path:
python3 ~/.claude/skills/google-analytics/query_script.py –report <report_type> [options]
The credentials file is resolved automatically from the same directory as the script.
## Available Reports
overview — High-level summary: users, sessions, page views, bounce rate, engagement rate
pages — Top pages by views, with users and avg engagement time
sources — Traffic by source and medium, sessions, conversions
countries — Geographic breakdown: country, sessions, users, engagement rate
devices — Desktop / mobile / tablet split
daily — Day-by-day trend: date, users, sessions, page views
realtime — Active users on the site right now
custom — Any GA4 metric and dimension combination
## Common Options
–days N How many days to look back (default: 30)
–limit N Maximum number of rows to return (default: 10)
–start DATE Exact start date in format YYYY-MM-DD
–end DATE Exact end date in format YYYY-MM-DD
–output Output format: table, json, or csv
## Example Commands
python3 query_script.py –report overview –days 7
python3 query_script.py –report pages –days 30 –limit 20
python3 query_script.py –report sources –days 30
python3 query_script.py –report daily –days 14
python3 query_script.py –report realtime
“`

 

How to Connect Google Analytics to Claude

File 2 — Copy this into a file named: query_script.py

Before copying, find the two lines near the top marked CHANGE THIS and update them:

Replace your-credentials.json with the actual filename of your key file (if you renamed it differently)

Replace 123456789 with your own Property ID from Step 2

```python
#!/usr/bin/env python3
“””
Google Analytics 4 Data API query tool.
Queries GA4 property data using a service account.
“””
import argparse
import json
import sys
import os
from datetime import datetime, timedelta
# ============================================================
# CHANGE THIS — update the two values below to match your setup
# ============================================================
CREDENTIALS_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), “your-credentials.json”)
PROPERTY_ID = “123456789”
# ============================================================
def get_client():
“””Create and return a GA4 BetaAnalyticsDataClient.”””
os.environ[“GOOGLE_APPLICATION_CREDENTIALS”] = CREDENTIALS_PATH
from google.analytics.data_v1beta import BetaAnalyticsDataClient
return BetaAnalyticsDataClient()
def build_request(metrics, dimensions, days=30, start=None, end=None, limit=10, order_by_metric=None, desc=True):
“””Build a RunReportRequest.”””
from google.analytics.data_v1beta.types import (
RunReportRequest, Metric, Dimension, DateRange, OrderBy
)
end_date = end or datetime.now().strftime(“%Y-%m-%d”)
if start:
start_date = start
else:
start_date = (datetime.now() – timedelta(days=days)).strftime(“%Y-%m-%d”)
request = RunReportRequest(
property=f”properties/{PROPERTY_ID}”,
metrics=[Metric(name=m.strip()) for m in metrics],
dimensions=[Dimension(name=d.strip()) for d in dimensions] if dimensions else [],
date_ranges=[DateRange(start_date=start_date, end_date=end_date)],
limit=limit,
)
if order_by_metric:
request.order_bys = [
OrderBy(
metric=OrderBy.MetricOrderBy(metric_name=order_by_metric),
desc=desc,
)
]
return request
def format_response(response, output=”table”):
“””Format the API response into the desired output format.”””
headers = [h.name for h in response.dimension_headers] + [h.name for h in response.metric_headers]
rows = []
for row in response.rows:
values = [dv.value for dv in row.dimension_values] + [mv.value for mv in row.metric_values]
rows.append(values)
if output == “json”:
result = []
for row in rows:
result.append(dict(zip(headers, row)))
return json.dumps(result, indent=2)
elif output == “csv”:
lines = [“,”.join(headers)]
for row in rows:
lines.append(“,”.join(row))
return “\n”.join(lines)
else: # table
col_widths = [len(h) for h in headers]
for row in rows:
for i, val in enumerate(row):
col_widths[i] = max(col_widths[i], len(str(val)))
separator = “+” + “+”.join(“-” * (w + 2) for w in col_widths) + “+”
header_row = “|” + “|”.join(f” {h:<{col_widths[i]}} ” for i, h in enumerate(headers)) + “|”
lines = [separator, header_row, separator]
for row in rows:
line = “|” + “|”.join(f” {str(v):<{col_widths[i]}} ” for i, v in enumerate(row)) + “|”
lines.append(line)
lines.append(separator)
if response.row_count:
lines.append(f”\nTotal rows: {response.row_count}”)
return “\n”.join(lines)
def report_overview(client, args):
“””High-level site overview.”””
request = build_request(
metrics=[“totalUsers”, “newUsers”, “sessions”, “screenPageViews”,
“averageSessionDuration”, “engagementRate”, “bounceRate”],
dimensions=[],
days=args.days, start=args.start, end=args.end, limit=1,
)
response = client.run_report(request)
return format_response(response, args.output)
def report_pages(client, args):
“””Top pages by views.”””
request = build_request(
metrics=[“screenPageViews”, “totalUsers”, “averageSessionDuration”],
dimensions=[“pagePath”, “pageTitle”],
days=args.days, start=args.start, end=args.end, limit=args.limit,
order_by_metric=”screenPageViews”,
)
response = client.run_report(request)
return format_response(response, args.output)
def report_sources(client, args):
“””Traffic sources.”””
request = build_request(
metrics=[“sessions”, “totalUsers”, “engagementRate”, “conversions”],
dimensions=[“sessionSource”, “sessionMedium”],
days=args.days, start=args.start, end=args.end, limit=args.limit,
order_by_metric=”sessions”,
)
response = client.run_report(request)
return format_response(response, args.output)
def report_countries(client, args):
“””Geographic breakdown.”””
request = build_request(
metrics=[“sessions”, “totalUsers”, “engagementRate”],
dimensions=[“country”],
days=args.days, start=args.start, end=args.end, limit=args.limit,
order_by_metric=”sessions”,
)
response = client.run_report(request)
return format_response(response, args.output)
def report_devices(client, args):
“””Device category breakdown.”””
request = build_request(
metrics=[“sessions”, “totalUsers”, “engagementRate”],
dimensions=[“deviceCategory”],
days=args.days, start=args.start, end=args.end, limit=args.limit,
order_by_metric=”sessions”,
)
response = client.run_report(request)
return format_response(response, args.output)
def report_daily(client, args):
“””Day-by-day trend.”””
request = build_request(
metrics=[“totalUsers”, “sessions”, “screenPageViews”],
dimensions=[“date”],
days=args.days, start=args.start, end=args.end, limit=args.days or 30,
)
from google.analytics.data_v1beta.types import OrderBy
request.order_bys = [
OrderBy(dimension=OrderBy.DimensionOrderBy(dimension_name=”date”), desc=False)
]
response = client.run_report(request)
return format_response(response, args.output)
def report_realtime(client, args):
“””Realtime active users.”””
from google.analytics.data_v1beta.types import (
RunRealtimeReportRequest, Metric, Dimension
)
request = RunRealtimeReportRequest(
property=f”properties/{PROPERTY_ID}”,
metrics=[Metric(name=”activeUsers”)],
dimensions=[Dimension(name=”unifiedScreenName”)],
limit=args.limit,
)
response = client.run_realtime_report(request)
headers = [h.name for h in response.dimension_headers] + [h.name for h in response.metric_headers]
rows = []
for row in response.rows:
values = [dv.value for dv in row.dimension_values] + [mv.value for mv in row.metric_values]
rows.append(values)
if not rows:
return “No active users right now.”
if args.output == “json”:
result = [dict(zip(headers, row)) for row in rows]
return json.dumps(result, indent=2)
elif args.output == “csv”:
lines = [“,”.join(headers)]
for row in rows:
lines.append(“,”.join(row))
return “\n”.join(lines)
else:
col_widths = [len(h) for h in headers]
for row in rows:
for i, val in enumerate(row):
col_widths[i] = max(col_widths[i], len(str(val)))
separator = “+” + “+”.join(“-” * (w + 2) for w in col_widths) + “+”
header_row = “|” + “|”.join(f” {h:<{col_widths[i]}} ” for i, h in enumerate(headers)) + “|”
lines = [separator, header_row, separator]
for row in rows:
line = “|” + “|”.join(f” {str(v):<{col_widths[i]}} ” for i, v in enumerate(row)) + “|”
lines.append(line)
lines.append(separator)
return “\n”.join(lines)
def report_custom(client, args):
“””Custom query with user-specified metrics and dimensions.”””
if not args.metrics:
return “Error: –metrics required for custom report (comma-separated)”
metrics = [m.strip() for m in args.metrics.split(“,”)]
dimensions = [d.strip() for d in args.dimensions.split(“,”)] if args.dimensions else []
request = build_request(
metrics=metrics,
dimensions=dimensions,
days=args.days, start=args.start, end=args.end, limit=args.limit,
order_by_metric=metrics[0],
)
response = client.run_report(request)
return format_response(response, args.output)
REPORTS = {
“overview”: report_overview,
“pages”: report_pages,
“sources”: report_sources,
“countries”: report_countries,
“devices”: report_devices,
“daily”: report_daily,
“realtime”: report_realtime,
“custom”: report_custom,
}
def main():
parser = argparse.ArgumentParser(description=”Query Google Analytics 4 data”)
parser.add_argument(“–report”, required=True, choices=REPORTS.keys(), help=”Report type”)
parser.add_argument(“–days”, type=int, default=30, help=”Lookback period in days (default: 30)”)
parser.add_argument(“–start”, help=”Start date (YYYY-MM-DD), overrides –days”)
parser.add_argument(“–end”, help=”End date (YYYY-MM-DD), defaults to today”)
parser.add_argument(“–limit”, type=int, default=10, help=”Max rows (default: 10)”)
parser.add_argument(“–output”, choices=[“table”, “json”, “csv”], default=”table”, help=”Output format”)
parser.add_argument(“–metrics”, help=”Comma-separated metrics (for custom report)”)
parser.add_argument(“–dimensions”, help=”Comma-separated dimensions (for custom report)”)
args = parser.parse_args()
try:
client = get_client()
result = REPORTS[args.report](client, args)
print(result)
except Exception as e:
print(f”Error: {e}”, file=sys.stderr)
sys.exit(1)
if __name__ == “__main__”:
main()
“`

Step 5 — Test that it works

Open your Terminal again. Type the following and press Enter:

python3 ~/.claude/skills/google-analytics/query_script.py --report overview --days 7

If you see a table with numbers, you are done. Those are your real analytics numbers. If you see an error, check the common fixes at the bottom of this article.

Step 6 — Ask Claude

Open Claude Cowork. Type any of these questions naturally:

  • “How much traffic did my site get this week?”
  • “What are my top pages in the last 30 days?”
  • “Where is my traffic coming from?”
  • “Show me a daily breakdown of visitors this month”
  • “How many people are on my site right now?”

Claude will run the script automatically, pull your real data, and answer you. Available report types you can ask about:

Overview (total users, sessions, bounce rate)

Top pages

Traffic sources

Countries

Devices (desktop vs mobile)

Daily trends

Realtime (who is on your site right now)

If something goes wrong

“Permission denied” or “403 error”

You skipped or made a mistake in Step 2. Go back and make sure the service account email is added as a Viewer in your Analytics settings.

“No module named google”

The package from Step 3 didn’t install properly. Run the pip3 install command again.

“Property not found”

Your Property ID in query_script.py has a typo. It should be just the number (e.g. 123456789), nothing else.

“Claude doesn’t understand my question”

Try being specific: “Use the google-analytics skill to show me traffic for the last 7 days.”

 

nerdzlab - nerdzlab image Alt
Summarize with AI