Google analytics skill

Pull GA4 reports, traffic data, and insights from the Google Analytics Data API.

by OpenClaudia·MIT license·★ 705 Stars on the repo·GitHub ↗

Use now

Files of Google analytics

OpenClaudia/main1 file shown
SKILL.md
Show the full text404 lines

Google Analytics (GA4)

Pull reports and insights from GA4 using the Google Analytics Data API.

Prerequisites

Requires Google OAuth credentials:

  • GOOGLE_CLIENT_ID
  • GOOGLE_CLIENT_SECRET
  • A valid OAuth access token (refreshed as needed)

Set credentials in .env, .env.local, or ~/.claude/.env.global.

Getting an Access Token
# Step 1: Get authorization code (user must visit this URL in browser)
echo "https://accounts.google.com/o/oauth2/v2/auth?client_id=${GOOGLE_CLIENT_ID}&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=https://www.googleapis.com/auth/analytics.readonly&response_type=code&access_type=offline"

# Step 2: Exchange code for tokens
curl -s -X POST "https://oauth2.googleapis.com/token" \
  -d "code={AUTH_CODE}" \
  -d "client_id=${GOOGLE_CLIENT_ID}" \
  -d "client_secret=${GOOGLE_CLIENT_SECRET}" \
  -d "redirect_uri=urn:ietf:wg:oauth:2.0:oob" \
  -d "grant_type=authorization_code"

# Step 3: Refresh an expired token
curl -s -X POST "https://oauth2.googleapis.com/token" \
  -d "refresh_token={REFRESH_TOKEN}" \
  -d "client_id=${GOOGLE_CLIENT_ID}" \
  -d "client_secret=${GOOGLE_CLIENT_SECRET}" \
  -d "grant_type=refresh_token"

Store the refresh token securely. The access token expires after 1 hour.

Finding Your GA4 Property ID
curl -s -H "Authorization: Bearer ${GA_ACCESS_TOKEN}" \
  "https://analyticsadmin.googleapis.com/v1beta/accountSummaries" \
  | python3 -c "
import json, sys
data = json.load(sys.stdin)
for acct in data.get('accountSummaries', []):
    for prop in acct.get('propertySummaries', []):
        print(f\"{prop['property']}  |  {prop.get('displayName','')}  |  Account: {acct.get('displayName','')}\")
"

The property ID format is properties/XXXXXXXXX.


API Base

POST https://analyticsdata.googleapis.com/v1beta/{property_id}:runReport

All report requests use POST with a JSON body. Always include Authorization: Bearer {ACCESS_TOKEN}.


1. Traffic Overview Report

Get sessions, users, page views, and engagement rate over a date range.

Example curl
curl -s -X POST \
  "https://analyticsdata.googleapis.com/v1beta/properties/{PROPERTY_ID}:runReport" \
  -H "Authorization: Bearer ${GA_ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "dateRanges": [{"startDate": "30daysAgo", "endDate": "today"}],
    "metrics": [
      {"name": "sessions"},
      {"name": "totalUsers"},
      {"name": "newUsers"},
      {"name": "screenPageViews"},
      {"name": "engagementRate"},
      {"name": "averageSessionDuration"},
      {"name": "bounceRate"}
    ]
  }'
Date Range Shortcuts
  • today, yesterday
  • 7daysAgo, 14daysAgo, 28daysAgo, 30daysAgo, 90daysAgo
  • Specific dates: 2024-01-01
  • Compare periods by passing two dateRanges

2. User Acquisition Report

See where users come from (channels, sources, campaigns).

curl -s -X POST \
  "https://analyticsdata.googleapis.com/v1beta/properties/{PROPERTY_ID}:runReport" \
  -H "Authorization: Bearer ${GA_ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "dateRanges": [{"startDate": "30daysAgo", "endDate": "today"}],
    "dimensions": [
      {"name": "sessionDefaultChannelGroup"}
    ],
    "metrics": [
      {"name": "sessions"},
      {"name": "totalUsers"},
      {"name": "engagementRate"},
      {"name": "conversions"}
    ],
    "orderBys": [{"metric": {"metricName": "sessions"}, "desc": true}],
    "limit": 20
  }'
Useful Acquisition Dimensions
Dimension Description
sessionDefaultChannelGroup Channel grouping (Organic, Paid, Social, etc.)
sessionSource Traffic source (google, facebook, etc.)
sessionMedium Medium (organic, cpc, referral, etc.)
sessionCampaignName UTM campaign name
firstUserSource First-touch attribution source

3. Top Pages Report

Find the highest-traffic pages on the site.

curl -s -X POST \
  "https://analyticsdata.googleapis.com/v1beta/properties/{PROPERTY_ID}:runReport" \
  -H "Authorization: Bearer ${GA_ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "dateRanges": [{"startDate": "30daysAgo", "endDate": "today"}],
    "dimensions": [
      {"name": "pagePath"}
    ],
    "metrics": [
      {"name": "screenPageViews"},
      {"name": "totalUsers"},
      {"name": "engagementRate"},
      {"name": "averageSessionDuration"}
    ],
    "orderBys": [{"metric": {"metricName": "screenPageViews"}, "desc": true}],
    "limit": 25
  }'

4. Engagement Metrics

Understand how users interact with your content.

curl -s -X POST \
  "https://analyticsdata.googleapis.com/v1beta/properties/{PROPERTY_ID}:runReport" \
  -H "Authorization: Bearer ${GA_ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "dateRanges": [{"startDate": "30daysAgo", "endDate": "today"}],
    "dimensions": [
      {"name": "pagePath"}
    ],
    "metrics": [
      {"name": "engagedSessions"},
      {"name": "engagementRate"},
      {"name": "averageSessionDuration"},
      {"name": "screenPageViewsPerSession"},
      {"name": "eventCount"}
    ],
    "orderBys": [{"metric": {"metricName": "engagedSessions"}, "desc": true}],
    "limit": 20
  }'
Key Engagement Metrics
Metric What It Measures
engagementRate % of sessions that were engaged (>10s, 2+ pages, or conversion)
averageSessionDuration Mean session length in seconds
screenPageViewsPerSession Pages per session
bounceRate % of sessions with no engagement
eventCount Total events fired

5. Conversion Tracking

Report on conversion events (purchases, signups, etc.).

curl -s -X POST \
  "https://analyticsdata.googleapis.com/v1beta/properties/{PROPERTY_ID}:runReport" \
  -H "Authorization: Bearer ${GA_ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "dateRanges": [{"startDate": "30daysAgo", "endDate": "today"}],
    "dimensions": [
      {"name": "eventName"}
    ],
    "metrics": [
      {"name": "eventCount"},
      {"name": "totalUsers"},
      {"name": "eventValue"}
    ],
    "dimensionFilter": {
      "filter": {
        "fieldName": "eventName",
        "inListFilter": {
          "values": ["purchase", "sign_up", "generate_lead", "begin_checkout"]
        }
      }
    }
  }'
Conversion by Channel
curl -s -X POST \
  "https://analyticsdata.googleapis.com/v1beta/properties/{PROPERTY_ID}:runReport" \
  -H "Authorization: Bearer ${GA_ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "dateRanges": [{"startDate": "30daysAgo", "endDate": "today"}],
    "dimensions": [
      {"name": "sessionDefaultChannelGroup"}
    ],
    "metrics": [
      {"name": "sessions"},
      {"name": "conversions"},
      {"name": "totalRevenue"}
    ],
    "orderBys": [{"metric": {"metricName": "conversions"}, "desc": true}]
  }'

6. Audience Segments

Break down traffic by device, geography, and demographics.

By Device Category
curl -s -X POST \
  "https://analyticsdata.googleapis.com/v1beta/properties/{PROPERTY_ID}:runReport" \
  -H "Authorization: Bearer ${GA_ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "dateRanges": [{"startDate": "30daysAgo", "endDate": "today"}],
    "dimensions": [{"name": "deviceCategory"}],
    "metrics": [
      {"name": "sessions"},
      {"name": "totalUsers"},
      {"name": "engagementRate"},
      {"name": "conversions"}
    ]
  }'
By Country

Replace deviceCategory with country in the dimensions.

By Landing Page + Source
curl -s -X POST \
  "https://analyticsdata.googleapis.com/v1beta/properties/{PROPERTY_ID}:runReport" \
  -H "Authorization: Bearer ${GA_ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "dateRanges": [{"startDate": "30daysAgo", "endDate": "today"}],
    "dimensions": [
      {"name": "landingPage"},
      {"name": "sessionSource"}
    ],
    "metrics": [
      {"name": "sessions"},
      {"name": "engagementRate"},
      {"name": "conversions"}
    ],
    "orderBys": [{"metric": {"metricName": "sessions"}, "desc": true}],
    "limit": 30
  }'

7. Period Comparison

Compare two time periods to identify trends.

curl -s -X POST \
  "https://analyticsdata.googleapis.com/v1beta/properties/{PROPERTY_ID}:runReport" \
  -H "Authorization: Bearer ${GA_ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "dateRanges": [
      {"startDate": "30daysAgo", "endDate": "today", "name": "current"},
      {"startDate": "60daysAgo", "endDate": "31daysAgo", "name": "previous"}
    ],
    "metrics": [
      {"name": "sessions"},
      {"name": "totalUsers"},
      {"name": "conversions"},
      {"name": "engagementRate"}
    ]
  }'

Response Parsing

GA4 API returns JSON. Parse with python3 or jq:

# Parse report into a table
curl -s -X POST "..." | python3 -c "
import json, sys
data = json.load(sys.stdin)
headers = [h['name'] for h in data.get('dimensionHeaders',[])] + [m['name'] for m in data.get('metricHeaders',[])]
print(' | '.join(headers))
print('-' * (len(headers) * 20))
for row in data.get('rows', []):
    dims = [d['value'] for d in row.get('dimensionValues',[])]
    mets = [m['value'] for m in row.get('metricValues',[])]
    print(' | '.join(dims + mets))
"

Workflow: Monthly Analytics Report

When asked for a monthly report:

  1. Pull traffic overview (sessions, users, page views) with period comparison
  2. Pull acquisition breakdown by channel
  3. Pull top 20 pages by page views
  4. Pull conversion summary by channel
  5. Pull device and country breakdown

Present as a structured report with tables, trends (up/down arrows), and recommendations:

## Monthly Analytics Report: {Property Name}
### Period: {date range} vs {previous period}

### Traffic Summary
| Metric | Current | Previous | Change |
|--------|---------|----------|--------|
| Sessions | X | Y | +Z% |
| ...

### Top Channels
...

### Top Pages
...

### Conversion Summary
...

### Recommendations
- [Based on data patterns]

Common Issues

  • 403 Forbidden: User lacks access to the GA4 property
  • Empty rows: No data for the requested date range or filters
  • Quota exceeded: GA4 API has daily quotas; reduce date ranges or batch requests
  • Property not found: Verify the property ID format (properties/XXXXXXXXX)
1---
2name: google-analytics
3description: >
4 Pull GA4 reports, traffic data, and insights from the Google Analytics Data API.
5 Use when asked about website traffic, user behavior, acquisition channels,
6 conversions, or audience segments. Trigger phrases: "google analytics", "GA4",
7 "traffic report", "analytics data", "user acquisition", "engagement metrics",
8 "conversion tracking", "audience segments", "page views", "sessions".
9---
10 
11# Google Analytics (GA4)
12 
13Pull reports and insights from GA4 using the Google Analytics Data API.
14 
15## Prerequisites
16 
17Requires Google OAuth credentials:
18- `GOOGLE_CLIENT_ID`
19- `GOOGLE_CLIENT_SECRET`
20- A valid OAuth access token (refreshed as needed)
21 
22Set credentials in `.env`, `.env.local`, or `~/.claude/.env.global`.
23 
24### Getting an Access Token
25 
26```bash
27# Step 1: Get authorization code (user must visit this URL in browser)
28echo "https://accounts.google.com/o/oauth2/v2/auth?client_id=${GOOGLE_CLIENT_ID}&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=https://www.googleapis.com/auth/analytics.readonly&response_type=code&access_type=offline"
29 
30# Step 2: Exchange code for tokens
31curl -s -X POST "https://oauth2.googleapis.com/token" \
32 -d "code={AUTH_CODE}" \
33 -d "client_id=${GOOGLE_CLIENT_ID}" \
34 -d "client_secret=${GOOGLE_CLIENT_SECRET}" \
35 -d "redirect_uri=urn:ietf:wg:oauth:2.0:oob" \
36 -d "grant_type=authorization_code"
37 
38# Step 3: Refresh an expired token
39curl -s -X POST "https://oauth2.googleapis.com/token" \
40 -d "refresh_token={REFRESH_TOKEN}" \
41 -d "client_id=${GOOGLE_CLIENT_ID}" \
42 -d "client_secret=${GOOGLE_CLIENT_SECRET}" \
43 -d "grant_type=refresh_token"
44```
45 
46Store the refresh token securely. The access token expires after 1 hour.
47 
48### Finding Your GA4 Property ID
49 
50```bash
51curl -s -H "Authorization: Bearer ${GA_ACCESS_TOKEN}" \
52 "https://analyticsadmin.googleapis.com/v1beta/accountSummaries" \
53 | python3 -c "
54import json, sys
55data = json.load(sys.stdin)
56for acct in data.get('accountSummaries', []):
57 for prop in acct.get('propertySummaries', []):
58 print(f\"{prop['property']} | {prop.get('displayName','')} | Account: {acct.get('displayName','')}\")
59"
60```
61 
62The property ID format is `properties/XXXXXXXXX`.
63 
64---
65 
66## API Base
67 
68```
69POST https://analyticsdata.googleapis.com/v1beta/{property_id}:runReport
70```
71 
72All report requests use POST with a JSON body. Always include `Authorization: Bearer {ACCESS_TOKEN}`.
73 
74---
75 
76## 1. Traffic Overview Report
77 
78Get sessions, users, page views, and engagement rate over a date range.
79 
80### Example curl
81 
82```bash
83curl -s -X POST \
84 "https://analyticsdata.googleapis.com/v1beta/properties/{PROPERTY_ID}:runReport" \
85 -H "Authorization: Bearer ${GA_ACCESS_TOKEN}" \
86 -H "Content-Type: application/json" \
87 -d '{
88 "dateRanges": [{"startDate": "30daysAgo", "endDate": "today"}],
89 "metrics": [
90 {"name": "sessions"},
91 {"name": "totalUsers"},
92 {"name": "newUsers"},
93 {"name": "screenPageViews"},
94 {"name": "engagementRate"},
95 {"name": "averageSessionDuration"},
96 {"name": "bounceRate"}
97 ]
98 }'
99```
100 
101### Date Range Shortcuts
102 
103- `today`, `yesterday`
104- `7daysAgo`, `14daysAgo`, `28daysAgo`, `30daysAgo`, `90daysAgo`
105- Specific dates: `2024-01-01`
106- Compare periods by passing two dateRanges
107 
108---
109 
110## 2. User Acquisition Report
111 
112See where users come from (channels, sources, campaigns).
113 
114```bash
115curl -s -X POST \
116 "https://analyticsdata.googleapis.com/v1beta/properties/{PROPERTY_ID}:runReport" \
117 -H "Authorization: Bearer ${GA_ACCESS_TOKEN}" \
118 -H "Content-Type: application/json" \
119 -d '{
120 "dateRanges": [{"startDate": "30daysAgo", "endDate": "today"}],
121 "dimensions": [
122 {"name": "sessionDefaultChannelGroup"}
123 ],
124 "metrics": [
125 {"name": "sessions"},
126 {"name": "totalUsers"},
127 {"name": "engagementRate"},
128 {"name": "conversions"}
129 ],
130 "orderBys": [{"metric": {"metricName": "sessions"}, "desc": true}],
131 "limit": 20
132 }'
133```
134 
135### Useful Acquisition Dimensions
136 
137| Dimension | Description |
138|-----------|-------------|
139| `sessionDefaultChannelGroup` | Channel grouping (Organic, Paid, Social, etc.) |
140| `sessionSource` | Traffic source (google, facebook, etc.) |
141| `sessionMedium` | Medium (organic, cpc, referral, etc.) |
142| `sessionCampaignName` | UTM campaign name |
143| `firstUserSource` | First-touch attribution source |
144 
145---
146 
147## 3. Top Pages Report
148 
149Find the highest-traffic pages on the site.
150 
151```bash
152curl -s -X POST \
153 "https://analyticsdata.googleapis.com/v1beta/properties/{PROPERTY_ID}:runReport" \
154 -H "Authorization: Bearer ${GA_ACCESS_TOKEN}" \
155 -H "Content-Type: application/json" \
156 -d '{
157 "dateRanges": [{"startDate": "30daysAgo", "endDate": "today"}],
158 "dimensions": [
159 {"name": "pagePath"}
160 ],
161 "metrics": [
162 {"name": "screenPageViews"},
163 {"name": "totalUsers"},
164 {"name": "engagementRate"},
165 {"name": "averageSessionDuration"}
166 ],
167 "orderBys": [{"metric": {"metricName": "screenPageViews"}, "desc": true}],
168 "limit": 25
169 }'
170```
171 
172---
173 
174## 4. Engagement Metrics
175 
176Understand how users interact with your content.
177 
178```bash
179curl -s -X POST \
180 "https://analyticsdata.googleapis.com/v1beta/properties/{PROPERTY_ID}:runReport" \
181 -H "Authorization: Bearer ${GA_ACCESS_TOKEN}" \
182 -H "Content-Type: application/json" \
183 -d '{
184 "dateRanges": [{"startDate": "30daysAgo", "endDate": "today"}],
185 "dimensions": [
186 {"name": "pagePath"}
187 ],
188 "metrics": [
189 {"name": "engagedSessions"},
190 {"name": "engagementRate"},
191 {"name": "averageSessionDuration"},
192 {"name": "screenPageViewsPerSession"},
193 {"name": "eventCount"}
194 ],
195 "orderBys": [{"metric": {"metricName": "engagedSessions"}, "desc": true}],
196 "limit": 20
197 }'
198```
199 
200### Key Engagement Metrics
201 
202| Metric | What It Measures |
203|--------|-----------------|
204| `engagementRate` | % of sessions that were engaged (>10s, 2+ pages, or conversion) |
205| `averageSessionDuration` | Mean session length in seconds |
206| `screenPageViewsPerSession` | Pages per session |
207| `bounceRate` | % of sessions with no engagement |
208| `eventCount` | Total events fired |
209 
210---
211 
212## 5. Conversion Tracking
213 
214Report on conversion events (purchases, signups, etc.).
215 
216```bash
217curl -s -X POST \
218 "https://analyticsdata.googleapis.com/v1beta/properties/{PROPERTY_ID}:runReport" \
219 -H "Authorization: Bearer ${GA_ACCESS_TOKEN}" \
220 -H "Content-Type: application/json" \
221 -d '{
222 "dateRanges": [{"startDate": "30daysAgo", "endDate": "today"}],
223 "dimensions": [
224 {"name": "eventName"}
225 ],
226 "metrics": [
227 {"name": "eventCount"},
228 {"name": "totalUsers"},
229 {"name": "eventValue"}
230 ],
231 "dimensionFilter": {
232 "filter": {
233 "fieldName": "eventName",
234 "inListFilter": {
235 "values": ["purchase", "sign_up", "generate_lead", "begin_checkout"]
236 }
237 }
238 }
239 }'
240```
241 
242### Conversion by Channel
243 
244```bash
245curl -s -X POST \
246 "https://analyticsdata.googleapis.com/v1beta/properties/{PROPERTY_ID}:runReport" \
247 -H "Authorization: Bearer ${GA_ACCESS_TOKEN}" \
248 -H "Content-Type: application/json" \
249 -d '{
250 "dateRanges": [{"startDate": "30daysAgo", "endDate": "today"}],
251 "dimensions": [
252 {"name": "sessionDefaultChannelGroup"}
253 ],
254 "metrics": [
255 {"name": "sessions"},
256 {"name": "conversions"},
257 {"name": "totalRevenue"}
258 ],
259 "orderBys": [{"metric": {"metricName": "conversions"}, "desc": true}]
260 }'
261```
262 
263---
264 
265## 6. Audience Segments
266 
267Break down traffic by device, geography, and demographics.
268 
269### By Device Category
270 
271```bash
272curl -s -X POST \
273 "https://analyticsdata.googleapis.com/v1beta/properties/{PROPERTY_ID}:runReport" \
274 -H "Authorization: Bearer ${GA_ACCESS_TOKEN}" \
275 -H "Content-Type: application/json" \
276 -d '{
277 "dateRanges": [{"startDate": "30daysAgo", "endDate": "today"}],
278 "dimensions": [{"name": "deviceCategory"}],
279 "metrics": [
280 {"name": "sessions"},
281 {"name": "totalUsers"},
282 {"name": "engagementRate"},
283 {"name": "conversions"}
284 ]
285 }'
286```
287 
288### By Country
289 
290Replace `deviceCategory` with `country` in the dimensions.
291 
292### By Landing Page + Source
293 
294```bash
295curl -s -X POST \
296 "https://analyticsdata.googleapis.com/v1beta/properties/{PROPERTY_ID}:runReport" \
297 -H "Authorization: Bearer ${GA_ACCESS_TOKEN}" \
298 -H "Content-Type: application/json" \
299 -d '{
300 "dateRanges": [{"startDate": "30daysAgo", "endDate": "today"}],
301 "dimensions": [
302 {"name": "landingPage"},
303 {"name": "sessionSource"}
304 ],
305 "metrics": [
306 {"name": "sessions"},
307 {"name": "engagementRate"},
308 {"name": "conversions"}
309 ],
310 "orderBys": [{"metric": {"metricName": "sessions"}, "desc": true}],
311 "limit": 30
312 }'
313```
314 
315---
316 
317## 7. Period Comparison
318 
319Compare two time periods to identify trends.
320 
321```bash
322curl -s -X POST \
323 "https://analyticsdata.googleapis.com/v1beta/properties/{PROPERTY_ID}:runReport" \
324 -H "Authorization: Bearer ${GA_ACCESS_TOKEN}" \
325 -H "Content-Type: application/json" \
326 -d '{
327 "dateRanges": [
328 {"startDate": "30daysAgo", "endDate": "today", "name": "current"},
329 {"startDate": "60daysAgo", "endDate": "31daysAgo", "name": "previous"}
330 ],
331 "metrics": [
332 {"name": "sessions"},
333 {"name": "totalUsers"},
334 {"name": "conversions"},
335 {"name": "engagementRate"}
336 ]
337 }'
338```
339 
340---
341 
342## Response Parsing
343 
344GA4 API returns JSON. Parse with python3 or jq:
345 
346```bash
347# Parse report into a table
348curl -s -X POST "..." | python3 -c "
349import json, sys
350data = json.load(sys.stdin)
351headers = [h['name'] for h in data.get('dimensionHeaders',[])] + [m['name'] for m in data.get('metricHeaders',[])]
352print(' | '.join(headers))
353print('-' * (len(headers) * 20))
354for row in data.get('rows', []):
355 dims = [d['value'] for d in row.get('dimensionValues',[])]
356 mets = [m['value'] for m in row.get('metricValues',[])]
357 print(' | '.join(dims + mets))
358"
359```
360 
361---
362 
363## Workflow: Monthly Analytics Report
364 
365When asked for a monthly report:
366 
3671. Pull traffic overview (sessions, users, page views) with period comparison
3682. Pull acquisition breakdown by channel
3693. Pull top 20 pages by page views
3704. Pull conversion summary by channel
3715. Pull device and country breakdown
372 
373Present as a structured report with tables, trends (up/down arrows), and recommendations:
374 
375```
376## Monthly Analytics Report: {Property Name}
377### Period: {date range} vs {previous period}
378 
379### Traffic Summary
380| Metric | Current | Previous | Change |
381|--------|---------|----------|--------|
382| Sessions | X | Y | +Z% |
383| ...
384 
385### Top Channels
386...
387 
388### Top Pages
389...
390 
391### Conversion Summary
392...
393 
394### Recommendations
395- [Based on data patterns]
396```
397 
398## Common Issues
399 
400- **403 Forbidden**: User lacks access to the GA4 property
401- **Empty rows**: No data for the requested date range or filters
402- **Quota exceeded**: GA4 API has daily quotas; reduce date ranges or batch requests
403- **Property not found**: Verify the property ID format (`properties/XXXXXXXXX`)
404 

Discussion

Alternatives

Attribution AuditPaste the sales and spend numbers each ad platform claims, and get back a plain explanation of why they disagree and which figure to trust.Data & AI · MITAnalytics trackingWhen the user wants to set up, audit, or optimize analytics tracking (GA4, events, conversions). Also use when the user mentions "Google Analytics," "GA4," "event tracking," "conversions," "attribution model," "gtag," "data layer," "GA4 setup," "conversion tracking," "event setup," "User ID tracking," or "CTA attribution." For traffic insights, use traffic-analysis.Marketing · MITAnalytics TrackingWhen the user wants to set up, improve, or audit analytics tracking and measurement. Also use when the user mentions "set up tracking," "GA4," "Google Analytics," "conversion tracking," "event tracking," "UTM parameters," "tag manager," "GTM," "analytics implementation," "tracking plan," "how do I measure this," "track conversions," "Mixpanel," "Segment," "are my events firing," or "analytics isn't working." Use this whenever someone asks how to know if something is working or wants to measure marketing results. For choosing attribution models, comparing multi-touch/MMM/incrementality, or reconciling conflicting numbers across tools, see attribution. For A/B test measurement, see ab-testing.Marketing · MITFind Out Which Marketing Actually Made The SalePaste the conflicting numbers from your ad accounts, website stats and sales records; get back one honest read on which channels really drove sales and where to put your budget.Data & AI · MIT