Install
$ agentstack add skill-bin-huang-google-analytics-cli-google-analytics-cli ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Google Analytics CLI Skill
You have access to google-analytics-cli, a read-only CLI for the GA4 API. Use it to run reports, monitor realtime activity, and explore account/property structure.
Quick start
# Check if the CLI is available
google-analytics-cli --help
# List accounts and properties
google-analytics-cli accounts
If the CLI is not installed, install it:
npm install -g google-analytics-cli
Authentication
The CLI uses Google service account credentials. Credentials are resolved in this order:
--credentialsflag (per-command)--profileflag orGA_PROFILEenv var →~/.config/google-analytics-cli/profiles/.jsonGOOGLE_APPLICATION_CREDENTIALSenv var~/.config/google-analytics-cli/credentials.json(auto-detected)- gcloud Application Default Credentials
Before running any command, verify credentials by running google-analytics-cli accounts. If it fails, ask the user to set up a service account and grant it Viewer access in Google Analytics.
If the user manages multiple GA accounts (e.g. several clients or organizations), run google-analytics-cli profiles to list available profiles, then pass --profile (e.g. accounts --profile account-a) to target a specific one. --credentials and --profile cannot be used together.
Property ID
Most commands require a GA4 property ID. It can be provided as:
- A positional argument:
google-analytics-cli report 123456789 ... - The
--propertyflag:google-analytics-cli report --property 123456789 ... - The
GA_PROPERTY_IDenv var:export GA_PROPERTY_ID=123456789
Both raw numbers (123456789) and prefixed format (properties/123456789) are accepted.
Output format
All commands output pretty-printed JSON by default. Use --format compact for single-line JSON.
Admin commands
# List all accounts and their properties
google-analytics-cli accounts
# Get details about a specific property
google-analytics-cli property 123456789
# List properties for an account
google-analytics-cli properties 987654321
google-analytics-cli properties 987654321 --show-deleted
# List data streams for a property
google-analytics-cli data-streams 123456789
# List key events (conversions) for a property
google-analytics-cli key-events 123456789
# List custom dimensions for a property (Admin API)
google-analytics-cli admin-custom-dimensions 123456789
# List custom metrics for a property (Admin API)
google-analytics-cli admin-custom-metrics 123456789
# Get data retention settings for a property
google-analytics-cli data-retention 123456789
# List Google Ads links for a property
google-analytics-cli ads-links 123456789
# List annotations for a property (alpha API)
google-analytics-cli annotations 123456789
# Get custom dimensions and metrics for a property (Data API, filters by customDefinition)
google-analytics-cli custom-dims 123456789
# List configured credentials profiles (for users with multiple GA accounts)
google-analytics-cli profiles
Change history
Search change history events for an account:
google-analytics-cli change-history 987654321
google-analytics-cli change-history 987654321 --filter-property 123456789
google-analytics-cli change-history 987654321 --earliest-change-time 2026-01-01T00:00:00Z
google-analytics-cli change-history 987654321 --earliest-change-time 2026-01-01T00:00:00Z --latest-change-time 2026-03-01T00:00:00Z
google-analytics-cli change-history 987654321 --actor-email user@example.com
google-analytics-cli change-history 987654321 --resource-type '["PROPERTY","DATA_STREAM"]'
google-analytics-cli change-history 987654321 --action '["CREATED","UPDATED"]'
Access report
Run an access report to see who accessed the property:
google-analytics-cli access-report 123456789 \
--dimensions "accessorEmail,accessMechanism" \
--metrics "accessCount" \
--date-ranges '[{"startDate": "30daysAgo", "endDate": "yesterday"}]'
Options: --dimension-filter, --metric-filter, --order-by, --limit, --offset, --time-zone, --return-entity-quota, --include-all-users, --expand-groups.
Note: Access report uses dimensionName/metricName (not name) internally and entity (not property).
Running reports
The report command runs a GA4 Data API report.
google-analytics-cli report \
--dimensions "" \
--metrics "" \
--date-ranges '' \
[--dimension-filter ''] \
[--metric-filter ''] \
[--order-by ''] \
[--limit ] \
[--offset ] \
[--currency-code ] \
[--keep-empty-rows] \
[--return-property-quota]
Required options: --dimensions, --metrics, --date-ranges.
Date ranges
The --date-ranges option takes a JSON array of date range objects:
# Relative dates
--date-ranges '[{"startDate": "30daysAgo", "endDate": "yesterday"}]'
# Absolute dates
--date-ranges '[{"startDate": "2026-01-01", "endDate": "2026-01-31"}]'
# Compare two periods
--date-ranges '[{"startDate": "30daysAgo", "endDate": "yesterday", "name": "current"}, {"startDate": "60daysAgo", "endDate": "31daysAgo", "name": "previous"}]'
Valid date values:
- Absolute:
YYYY-MM-DD(e.g.2026-01-01) - Relative:
NdaysAgo(e.g.30daysAgo,7daysAgo) - Special:
yesterday,today - Up to 4 date ranges per request
Dimension filters
The --dimension-filter option takes a JSON FilterExpression:
# Exact match
--dimension-filter '{"filter": {"fieldName": "country", "stringFilter": {"matchType": "EXACT", "value": "United States"}}}'
# Contains
--dimension-filter '{"filter": {"fieldName": "pagePath", "stringFilter": {"matchType": "CONTAINS", "value": "/blog"}}}'
# Regex
--dimension-filter '{"filter": {"fieldName": "pagePath", "stringFilter": {"matchType": "PARTIAL_REGEXP", "value": "^/products/[0-9]+"}}}'
# In list
--dimension-filter '{"filter": {"fieldName": "eventName", "inListFilter": {"values": ["page_view", "scroll", "click"]}}}'
# AND group
--dimension-filter '{"andGroup": {"expressions": [{"filter": {"fieldName": "country", "stringFilter": {"matchType": "EXACT", "value": "United States"}}}, {"filter": {"fieldName": "deviceCategory", "stringFilter": {"matchType": "EXACT", "value": "mobile"}}}]}}'
# OR group
--dimension-filter '{"orGroup": {"expressions": [{"filter": {"fieldName": "country", "stringFilter": {"matchType": "EXACT", "value": "United States"}}}, {"filter": {"fieldName": "country", "stringFilter": {"matchType": "EXACT", "value": "Canada"}}}]}}'
# NOT
--dimension-filter '{"notExpression": {"filter": {"fieldName": "pagePath", "stringFilter": {"matchType": "EXACT", "value": "/"}}}}'
StringFilter matchType values: EXACT, BEGINS_WITH, ENDS_WITH, CONTAINS, FULL_REGEXP, PARTIAL_REGEXP.
Metric filters
The --metric-filter option takes the same FilterExpression structure but with numeric filters:
# Greater than
--metric-filter '{"filter": {"fieldName": "sessions", "numericFilter": {"operation": "GREATER_THAN", "value": {"int64Value": "100"}}}}'
# Between
--metric-filter '{"filter": {"fieldName": "bounceRate", "betweenFilter": {"fromValue": {"doubleValue": 0.5}, "toValue": {"doubleValue": 0.9}}}}'
NumericFilter operations: EQUAL, LESS_THAN, LESS_THAN_OR_EQUAL, GREATER_THAN, GREATER_THAN_OR_EQUAL.
NumericValue: use {"int64Value": "string"} for integers or {"doubleValue": number} for decimals.
Ordering
The --order-by option takes a JSON array:
# By metric descending
--order-by '[{"metric": {"metricName": "sessions"}, "desc": true}]'
# By dimension alphabetically
--order-by '[{"dimension": {"dimensionName": "date", "orderType": "ALPHANUMERIC"}}]'
# Multiple sort keys
--order-by '[{"metric": {"metricName": "sessions"}, "desc": true}, {"dimension": {"dimensionName": "country"}}]'
DimensionOrderBy orderType values: ALPHANUMERIC, CASE_INSENSITIVE_ALPHANUMERIC, NUMERIC.
Pivot reports
Run a pivot report for cross-tabulation analysis:
google-analytics-cli pivot-report 123456789 \
--dimensions "country,browser" \
--metrics "sessions,activeUsers" \
--date-ranges '[{"startDate": "30daysAgo", "endDate": "yesterday"}]' \
--pivots '[{"fieldNames": ["browser"], "limit": 5, "orderBys": [{"metric": {"metricName": "sessions"}, "desc": true}]}]'
Options: --dimension-filter, --metric-filter, --currency-code, --keep-empty-rows, --return-property-quota.
Batch reports
Run up to 5 reports in a single request:
google-analytics-cli batch-report 123456789 \
--requests '[{"dimensions": [{"name": "date"}], "metrics": [{"name": "activeUsers"}], "dateRanges": [{"startDate": "7daysAgo", "endDate": "yesterday"}]}, {"dimensions": [{"name": "country"}], "metrics": [{"name": "sessions"}], "dateRanges": [{"startDate": "7daysAgo", "endDate": "yesterday"}]}]'
Metadata and compatibility
# Get full metadata (all available dimensions and metrics)
google-analytics-cli metadata 123456789
# Check if dimensions and metrics are compatible
google-analytics-cli check-compatibility 123456789 \
--dimensions "date,country" \
--metrics "sessions,activeUsers"
Options: --dimension-filter, --metric-filter (same FilterExpression format as report).
Audience exports
# Create an audience export
google-analytics-cli audience-export-create 123456789 \
--audience "properties/123456789/audiences/456" \
--dimensions "deviceId,userId"
# Get status of an audience export
google-analytics-cli audience-export 123456789 properties/123456789/audienceExports/789
# List all audience exports
google-analytics-cli audience-exports 123456789
# Query rows from a completed audience export
google-analytics-cli audience-export-query 123456789 properties/123456789/audienceExports/789 \
--limit 1000 --offset 0
Realtime reports
The realtime command monitors current activity. No date ranges or currency code.
google-analytics-cli realtime \
--dimensions "" \
--metrics "" \
[--dimension-filter ''] \
[--metric-filter ''] \
[--order-by ''] \
[--limit ] \
[--return-property-quota]
Realtime reports cover the last 30 minutes of activity.
Realtime dimensions (limited set)
appVersion, audienceId, audienceName, audienceResourceName, city, cityId, country, countryId, deviceCategory, eventName, minutesAgo, platform, streamId, streamName, unifiedScreenName
Note: minutesAgo is "00" for the current minute, "01" for the previous, up to "29".
Realtime metrics (4 only)
activeUsers, eventCount, keyEvents, screenPageViews
Common dimensions reference
Traffic source (session-scoped): sessionSource, sessionMedium, sessionSourceMedium, sessionDefaultChannelGroup, sessionCampaignName, sessionCampaignId
Traffic source (first-user acquisition): firstUserSource, firstUserMedium, firstUserSourceMedium, firstUserDefaultChannelGroup, firstUserCampaignName
Page/Screen: pagePath, pageTitle, pagePathPlusQueryString, landingPage, landingPagePlusQueryString, hostName, fullPageUrl, contentGroup
Event: eventName, isKeyEvent
User: newVsReturning, userAgeBracket, userGender, firstSessionDate
Geography: country, countryId, city, cityId, region, continent, language
Device: deviceCategory, browser, operatingSystem, operatingSystemVersion, screenResolution, mobileDeviceBranding, platform
Time: date, dateHour, day, dayOfWeek, dayOfWeekName, hour, month, week, year, yearMonth, nthDay
Ecommerce: transactionId, itemName, itemId, itemCategory, itemBrand, itemVariant, orderCoupon
Google Ads: sessionGoogleAdsCampaignName, sessionGoogleAdsAdGroupName, sessionGoogleAdsKeyword, sessionGoogleAdsAdNetworkType, googleAdsAccountName
Audience: audienceId, audienceName
Custom dimensions: customEvent:parameter_name (event-scoped), customUser:parameter_name (user-scoped), customItem:parameter_name (item-scoped)
Common metrics reference
User: activeUsers, newUsers, totalUsers
Session: sessions, sessionsPerUser, averageSessionDuration, bounceRate
Engagement: engagedSessions, engagementRate, screenPageViews, screenPageViewsPerSession, screenPageViewsPerUser, userEngagementDuration
Event: eventCount, eventCountPerUser, eventValue, eventsPerSession
Key events (conversions): keyEvents, sessionKeyEventRate, userKeyEventRate
Ecommerce/Revenue: ecommercePurchases, purchaseRevenue, totalRevenue, transactions, averagePurchaseRevenue, averageRevenuePerUser, itemRevenue, addToCarts, checkouts, cartToViewRate
Advertising: advertiserAdClicks, advertiserAdCost, advertiserAdCostPerClick, advertiserAdImpressions, returnOnAdSpend
Custom metrics: customEvent:parameter_name (sum), averageCustomEvent:parameter_name (average), countCustomEvent:parameter_name (count)
Report examples
Traffic overview (last 30 days):
google-analytics-cli report 123456789 \
--dimensions "sessionDefaultChannelGroup" \
--metrics "sessions,activeUsers,engagementRate,keyEvents,totalRevenue" \
--date-ranges '[{"startDate": "30daysAgo", "endDate": "yesterday"}]' \
--order-by '[{"metric": {"metricName": "sessions"}, "desc": true}]'
Top pages by views:
google-analytics-cli report 123456789 \
--dimensions "pagePath" \
--metrics "screenPageViews,activeUsers,averageSessionDuration,bounceRate" \
--date-ranges '[{"startDate": "30daysAgo", "endDate": "yesterday"}]' \
--order-by '[{"metric": {"metricName": "screenPageViews"}, "desc": true}]' \
--limit 20
Daily trend:
google-analytics-cli report 123456789 \
--dimensions "date" \
--metrics "activeUsers,sessions,screenPageViews,keyEvents" \
--date-ranges '[{"startDate": "30daysAgo", "endDate": "yesterday"}]' \
--order-by '[{"dimension": {"dimensionName": "date"}}]'
Traffic source breakdown:
google-analytics-cli report 123456789 \
--dimensions "sessionSource,sessionMedium" \
--metrics "sessions,activeUsers,engagementRate,bounceRate,keyEvents" \
--date-ranges '[{"startDate": "7daysAgo", "endDate": "yesterday"}]' \
--order-by '[{"metric": {"metricName": "sessions"}, "desc": true}]' \
--limit 20
Landing page performance:
google-analytics-cli report 123456789 \
--dimensions "landingPage" \
--metrics "sessions,activeUsers,bounceRate,keyEvents,averageSessionDuration" \
--date-ranges '[{"startDate": "30daysAgo", "endDate": "yesterday"}]' \
--order-by '[{"metric": {"metricName": "sessions"}, "desc": true}]' \
--limit 20
Device breakdown:
google-analytics-cli report 123456789 \
--dimensions "deviceCategory" \
--metrics "activeUsers,sessions,engagementRate,bounceRate,screenPageViews" \
--date-ranges '[{"startDate": "30daysAgo", "endDate": "yesterday"}]'
Geography:
google-analytics-cli report 123456789 \
--dimensions "country" \
--metrics "activeUsers,sessions,engagementRate,keyEvents" \
--date-ranges '[{"startDate": "30daysAgo", "endDate": "yesterday"}]' \
--order-by '[{"metric": {"metricName": "activeUsers"}, "desc": true}]' \
--limit 20
Event analysis:
google-analytics-cli report 123456789 \
--dimensions "eventName" \
--metrics "eventCount,eventCountPerUser,eventValue" \
--date-ranges '[{"startDate": "7daysAgo", "endDate": "yesterday"}]' \
--order-by '[{"metric": {"metricName": "eventCount"}, "desc": true}]' \
--limit 20
Period comparison:
google-analytics-cli report 123456789 \
--dimensions "sessionDefaultChannelGroup" \
--metrics "sessions,activeUsers,keyEvents" \
--date-ranges '[{"startDate": "30daysAgo", "endDate": "yesterday", "name": "current"}, {"startDate": "60daysAgo", "endDate": "31daysAgo
…
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [Bin-Huang](https://github.com/Bin-Huang)
- **Source:** [Bin-Huang/google-analytics-cli](https://github.com/Bin-Huang/google-analytics-cli)
- **License:** Apache-2.0
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.