skills/ga4-query/SKILL.md
Query Google Analytics 4 via the Data API. Use when the user asks about GA4, Google Analytics, website traffic, page views, sessions, users, realtime data, or analytics reports. Triggered by: GA4, Google Analytics, analytics, sessions, pageviews, activeUsers, traffic, realtime, bounce rate, engagement.
npx skillsauth add aivokone/ak-skills ga4-queryInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Check prerequisites before querying:
Script path resolution: Before running any script, determine the correct base path. Check in this order:
.claude/skills/ga4-query/scripts/ — project-local install (run from repository root)~/.claude/skills/ga4-query/scripts/ — global installUse whichever path exists. All script paths below use the project-local form; substitute the global path if that's where scripts are found.
.claude/skills/ga4-query/scripts/.venv/ must existga4-config.yaml must be findable (see Config section)# 1. Install dependencies
bash .claude/skills/ga4-query/scripts/setup.sh
# 2. Create ga4-config.yaml in project root or ~/.config/ga4-query/
# (see Config section for template)
# 3. Enable APIs in GCP Console:
# - Google Analytics Data API (analyticsdata.googleapis.com)
# - Google Analytics Admin API (analyticsadmin.googleapis.com)
# 4. Test
ga4 accounts
When running inside the Claude Code sandbox, network access is restricted. Add the following domains to ~/.claude/settings.json under sandbox.network.allowedDomains:
Setup (pip install):
pypi.orgfiles.pythonhosted.orgRuntime (GA4 API):
analyticsdata.googleapis.comanalyticsadmin.googleapis.comoauth2.googleapis.comThe script searches for ga4-config.yaml in this order:
--config CLI parameter (explicit path)./ga4-config.yaml (project root)~/.config/ga4-query/ga4-config.yaml (user-level)Template (ga4-config.yaml):
property_id: "YOUR_PROPERTY_ID"
credentials_json: "/path/to/service-account.json"
The service account must have Viewer role on the GA4 property. Auth uses service_account.Credentials.from_service_account_file() with scope analytics.readonly.
Use the ga4 alias:
alias ga4='.claude/skills/ga4-query/scripts/.venv/bin/python3 .claude/skills/ga4-query/scripts/query.py'
# Sessions and users by date (last 7 days)
ga4 report -d date -m sessions,activeUsers --start 7daysAgo --end yesterday
# Top pages by views
ga4 report -d pagePath -m screenPageViews --start 30daysAgo --end yesterday --order-by screenPageViews --desc --limit 20
# Traffic sources
ga4 report -d sessionSource,sessionMedium -m sessions --start 30daysAgo --end yesterday
# With filter
ga4 report -d pagePath -m screenPageViews --start 7daysAgo --end yesterday --filter "pagePath=~/palvelut"
# Multiple filters (ANDed)
ga4 report -d date -m sessions --start 7daysAgo --end yesterday --filter "country==Finland" --filter "sessionSource==google"
# JSON via stdin (recommended — avoids shell escaping issues)
echo '{"dimensions":["pagePath"],"metrics":["screenPageViews"],"dateRanges":[{"startDate":"7daysAgo","endDate":"yesterday"}]}' | ga4 report --json -
# JSON as direct argument (only for simple JSON with no nested quotes)
ga4 report --json '{"dimensions":["pagePath"],"metrics":["screenPageViews"],"dateRanges":[{"startDate":"7daysAgo","endDate":"yesterday"}]}'
Flags:
-d / --dimensions — Comma-separated dimension names-m / --metrics — Comma-separated metric names (required unless --json)--start — Start date (default: 7daysAgo)--end — End date (default: yesterday)--filter — Dimension filter (repeatable, ANDed together)--order-by — Sort field name--desc — Descending order (use with --order-by)--limit — Max rows--json — Raw JSON request body (overrides all other flags)ga4 realtime -m activeUsers
ga4 realtime -d country -m activeUsers
No date range — realtime always returns last ~30 minutes.
ga4 accounts # List accounts + properties
ga4 property # Current property details
ga4 custom-dims # Custom dimensions
ga4 custom-metrics # Custom metrics
--config /path/to/ga4-config.yaml # Override config search
--property 123456789 # Override property_id from config
| Syntax | Match type | Example |
|--------|-----------|---------|
| field==value | EXACT | country==Finland |
| field!=value | NOT EXACT | pagePath!=/ |
| field=~value | CONTAINS | pagePath=~/palvelut |
| field=^value | BEGINS_WITH | pagePath=^/blog |
| field=$value | ENDS_WITH | pagePath=$.html |
| field=*v1,v2 | IN_LIST | country=*Finland,Sweden |
| field>N | GREATER_THAN | sessions>100 |
| field>=N | GREATER_THAN_OR_EQUAL | sessions>=50 |
| field<N | LESS_THAN | sessions<10 |
| field<=N | LESS_THAN_OR_EQUAL | sessions<=5 |
Multiple --filter flags are ANDed. For OR logic or nested NOT, use --json passthrough via stdin (echo '...' | ga4 report --json -).
YYYY-MM-DD — Specific date (2024-01-15)NdaysAgo — Relative (7daysAgo, 30daysAgo)yesterday — Yesterdaytoday — Today (partial data)See references/dimensions.md and references/metrics.md for curated lists.
| Dimension | Description |
|-----------|-------------|
| date | Date (YYYYMMDD format) |
| pagePath | Page URL path |
| pageTitle | Page title |
| sessionSource | Traffic source |
| sessionMedium | Traffic medium |
| sessionCampaignName | Campaign name |
| country | User country |
| city | User city |
| deviceCategory | desktop/mobile/tablet |
| Metric | Description |
|--------|-------------|
| sessions | Total sessions |
| activeUsers | Active users |
| screenPageViews | Page views |
| engagementRate | Engaged sessions / total |
| averageSessionDuration | Avg session length (seconds) |
| bounceRate | Non-engaged sessions / total |
| conversions | Key event conversions |
| totalRevenue | Total revenue |
Success — JSON to stdout:
{
"row_count": 7,
"rows": [
{"date": "20240101", "sessions": "142", "activeUsers": "98"}
],
"metadata": {
"dimensions": ["date"],
"metrics": ["sessions", "activeUsers"]
}
}
Errors — JSON to stderr + exit code 1:
{"error": "..."}
date dimension returns format YYYYMMDD (no dashes).row_count in response reflects total matching rows (may exceed --limit).accounts, property, custom-dims, custom-metrics) require the Admin API to be enabled separately from the Data API.tools
Create, edit, and debug SwiftBar menu bar plugins for macOS. ALWAYS use this skill when the user wants to put anything in the macOS menu bar — whether they say "menu bar plugin", "status bar widget", "menu bar item", or just want to show live data, counters, status indicators, or monitoring info in the macOS top bar. Also triggers for SwiftBar, BitBar, xbar by name, editing or debugging existing menu bar plugin scripts (.sh/.py with | parameters and --- separators), or any request to build a script that outputs formatted lines for a menu bar app. This is the go-to skill whenever macOS menu bar customization is involved, even if the user doesn't mention SwiftBar specifically — if they want a script-based menu bar item on macOS, this skill applies.
tools
Use this skill FIRST for any Seravo-hosted WordPress task. Trigger when the user mentions Seravo, production/shadow, deploy, Git-based deploys, SSH, DDEV, DB sync/import/export, or Seravo custom wp-* commands (wp-backup*, wp-purge-cache, wp-list-env). Start by identifying the environment (production vs shadow vs local) and enforce safety: agents must not run destructive or state-changing commands on production. When production write is needed, provide exact copy-paste commands for the user. Use Seravo-specific CLI and workflows instead of generic WP guidance to avoid wrong commands and risky prod changes.
development
Systematic PR fix loop — checks feedback from all channels (conversation, inline, reviews), fixes code, posts fix reports, and loops until no new feedback remains. All operations through provided scripts.
development
Local docs cache for the project. Always check docs/reference/ before fetching externally. Use for init (set up cache), update (refresh docs), lookup (local-first search), and save (persist fetched docs). If external docs are fetched (Context7/web), save a tailored topic file to docs/reference/ and add a verbal pointer in AGENTS.md.