Expand description
§google-analytics-api-ga4 — Google Analytics 4 (GA4) Data API client for Rust
google-analytics-api-ga4 is a lightweight, async Rust client library for the
Google Analytics Data API v1beta (GA4).
Fetch GA4 reports, realtime reports, pivot reports, and metadata from Rust with
strongly typed requests and responses — no code generation, no heavy dependencies
(just reqwest, serde, and serde_json).
Use it to build analytics dashboards, export GA4 data to your database or data warehouse, automate SEO / marketing reporting, or monitor realtime active users from a Rust backend.
§Features
| GA4 Data API method | Rust function | Description |
|---|---|---|
runReport | AnalyticsDataApi::run_report | Core report of dimensions and metrics (sessions, pageviews, events, …) |
batchRunReports | AnalyticsDataApi::batch_run_reports | Up to 5 reports in a single HTTP request |
runPivotReport | AnalyticsDataApi::run_pivot_report | Pivot-table style reports |
batchRunPivotReports | AnalyticsDataApi::batch_run_pivot_reports | Multiple pivot reports in one request |
runRealtimeReport | AnalyticsDataApi::run_realtime_report | Realtime active users for the last 30 minutes |
checkCompatibility | AnalyticsDataApi::check_compatibility | Check which dimensions/metrics can be combined |
getMetadata | AnalyticsDataApi::get_metadata | List all available dimensions and metrics, including custom ones |
- Async / await — built on
reqwest+tokio, with a shared connection pool - Strongly typed — request and response structs mirror the official GA4 REST schema (
FilterExpression,OrderBy,CohortSpec,Pivot, …) - Filter support — string / in-list / numeric / between filters with
andGroup,orGroup,notExpression - Proper error handling —
GoogleApiErrorimplementsstd::error::Error, distinguishing network errors, non-2xx API responses, and JSON parse failures - Auth-agnostic — pass any OAuth2 / service-account access token as
&str(works withyup-oauth2,gcp_auth, etc.)
§Installation
[dependencies]
google-analytics-api-ga4 = "0.3"§Quick start
§1. Get an access token (service account)
Any library that produces a Google OAuth2 access token works. Example with yup-oauth2:
async fn token() -> yup_oauth2::AccessToken {
let secret = yup_oauth2::read_service_account_key("./service_account.json")
.await
.expect("service_account.json");
let auth = yup_oauth2::ServiceAccountAuthenticator::builder(secret)
.build()
.await
.unwrap();
let scopes = &["https://www.googleapis.com/auth/analytics.readonly"];
auth.token(scopes).await.unwrap()
}Remember to add the service account’s email address as a viewer of your GA4 property (Admin → Property Access Management).
§2. Run a report (runReport)
use google_analytics_api_ga4::types::{
DateRange, Dimension, Filter, FilterExpression, FilterExpressionList, MatchType, Metric,
OrderBy, StringFilter,
};
use google_analytics_api_ga4::{AnalyticsDataApi, RunReportRequest};
async fn example(token: &str) {
let property_id = "123456789";
// WHERE fullPageUrl BEGINS_WITH "example.com"
let dimension_filter = FilterExpression {
and_group: Some(FilterExpressionList {
expressions: Some(vec![FilterExpression {
filter: Some(Filter {
field_name: Some("fullPageUrl".to_string()),
string_filter: Some(StringFilter {
match_type: Some(MatchType::BeginsWith),
value: Some("example.com".to_string()),
..StringFilter::default()
}),
..Filter::default()
}),
..FilterExpression::default()
}]),
}),
..FilterExpression::default()
};
let request = RunReportRequest {
property: format!("properties/{}", property_id),
dimensions: Dimension::from_string_vec(vec!["fullPageUrl", "eventName"]),
metrics: Metric::from_string_vec(vec!["sessions", "screenPageViews", "eventCount"]),
date_ranges: vec![DateRange::new("range", "2024-01-01", "2024-01-31")],
dimension_filter: Some(dimension_filter),
order_bys: Some(vec![OrderBy::metric("sessions", true)]), // ORDER BY sessions DESC
limit: Some("20".to_string()),
..RunReportRequest::default()
};
let response = AnalyticsDataApi::run_report(token, property_id, request)
.await
.unwrap();
for row in response.rows.unwrap_or_default() {
println!("{:?} {:?}", row.dimension_values, row.metric_values);
}
}§3. Realtime active users (runRealtimeReport)
use google_analytics_api_ga4::types::{Dimension, Metric};
use google_analytics_api_ga4::{AnalyticsDataApi, MinuteRange, RunRealtimeReportRequest};
async fn example(token: &str) {
let property_id = "123456789";
let request = RunRealtimeReportRequest {
dimensions: Dimension::from_string_vec(vec!["unifiedScreenName"]),
metrics: Metric::from_string_vec(vec!["activeUsers"]),
minute_ranges: Some(vec![MinuteRange::new("last 5 min", 5, 0)]),
..RunRealtimeReportRequest::default()
};
let response = AnalyticsDataApi::run_realtime_report(token, property_id, request)
.await
.unwrap();
println!("{:?}", response.rows);
}§4. Discover dimensions and metrics (getMetadata)
use google_analytics_api_ga4::AnalyticsDataApi;
async fn example(token: &str) {
let metadata = AnalyticsDataApi::get_metadata(token, "123456789")
.await
.unwrap();
for dimension in metadata.dimensions.unwrap_or_default() {
println!("{:?}: {:?}", dimension.api_name, dimension.ui_name);
}
}§Error handling
Every method returns Result<_, GoogleApiError>:
| Variant | Meaning |
|---|---|
GoogleApiError::Connection(message) | Network-level failure (DNS, TLS, timeout) |
GoogleApiError::Response(status, body) | The API returned a non-2xx status (quota exceeded, permission denied, invalid argument, …) |
GoogleApiError::JsonParse(body) | The response body could not be deserialized |
GoogleApiError implements std::error::Error and Display, so it composes
with ?, anyhow, and thiserror.
§FAQ
Q. Does this crate support Universal Analytics (UA / GA3)? No. It targets Google Analytics 4 (GA4) only, via the Data API v1beta. Universal Analytics was shut down by Google in 2023–2024.
Q. Which authentication methods are supported?
Any Google OAuth2 access token: service accounts (recommended for servers),
user OAuth flows, workload identity, etc. The token is passed as a plain &str,
so you can use yup-oauth2, gcp_auth, or your own token source.
Q. How is this different from google-analyticsdata1_beta (google-apis-rs)?
This crate is hand-written and minimal: a handful of files, three dependencies,
and idiomatic builder-free structs. The auto-generated alternative covers more
surface area but is heavier and harder to read.
Q. Which GA4 dimensions and metrics can I use?
Any from the official
API schema
(e.g. sessions, activeUsers, screenPageViews, eventCount, country,
fullPageUrl, eventName), plus your custom definitions. Use
AnalyticsDataApi::get_metadata to list everything available on your property,
and check_compatibility to verify combinations.
Q. Is the Data API quota handled?
Set return_property_quota: Some(true) on a request and read
response.property_quota to monitor consumed/remaining tokens per property.
§日本語での概要
google-analytics-api-ga4 は、Google アナリティクス 4(GA4)の Data API v1beta を
Rust から呼び出すための非同期クライアントライブラリです。runReport による
レポート取得、runRealtimeReport によるリアルタイムのアクティブユーザー数取得、
ピボットレポート、ディメンション・指標のメタデータ取得に対応しています。
サービスアカウントのアクセストークンを文字列で渡すだけで利用でき、GA4 データの
データベース連携・ダッシュボード構築・SEO レポート自動化などに使えます。
§Testing
# Offline serialization tests (no credentials needed)
cargo test
# Integration tests against the live API (requires ./test.json service account key)
cargo test -- --ignored§Links
- API reference on docs.rs
- crates.io page
- Google Analytics Data API v1beta reference
- GA4 dimensions & metrics schema
- Realtime API schema
§Breaking changes in 0.3.0
- Upgraded
reqwestfrom 0.12 to 0.13. The default TLS backend is nowrustls(withaws-lc-rs) instead ofnative-tls/ OpenSSL, so OpenSSL development headers are no longer required to build. If you depend onreqwestyourself withdefault-features = false, make sure you enable a TLS backend (rustlsornative-tls). - Minimum supported Rust version is now 1.85 (required by
reqwest0.13).
§Breaking changes in 0.2.0
AnalyticsDataApi::run_pivot_reportnow takesRunPivotReportRequestand returnsRunPivotReportResponse(previously it mistakenly used the checkCompatibility types).AnalyticsDataApi::batch_run_reportsnow returnsBatchRunReportsResponse(with areportsfield).AnalyticsDataApi::batch_run_pivot_reportsnow takesVec<RunPivotReportRequest>and returnsBatchRunPivotReportsResponse.RunReportRequest::order_bys/RunRealtimeReportRequest::order_bysare nowOption<Vec<OrderBy>>(matching the API schema; previouslyDimensionOrderBywas serialized without theOrderBywrapper).MinuteRange::start_minutes_ago/end_minutes_agoare nowOption<i32>.FilterExpression::not_expressionis nowOption<Box<FilterExpression>>.NumericValue::double_valueis nowOption<f64>;int64_valuewas renamed fromint_64_value.MetricMetadatafields are now allOption(robust deserialization).- All struct fields are now public, and
Nonefields are no longer serialized asnull. GoogleApiErrorgained aResponse(u16, String)variant for non-2xx responses.
§License
MIT
Modules§
Structs§
- Analytics
Data Api - Entry point for the Google Analytics 4 (GA4) Data API v1beta.
- Batch
RunPivot Reports Response - https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/properties/batchRunPivotReports
- Batch
RunReports Response - https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/properties/batchRunReports
- Check
Compatibility Request - https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/properties/checkCompatibility
- Check
Compatibility Response - Dimension
Compatibility - GetMetadata
Response - https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/properties/getMetadata
- Metric
Compatibility - Minute
Range - https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/MinuteRange
- RunPivot
Report Request - https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/properties/runPivotReport
- RunRealtime
Report Request - Realtime Dimensions & Metrics https://developers.google.com/analytics/devguides/reporting/data/v1/realtime-api-schema
- RunReport
Request - https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/properties/runReport