Skip to main content

Crate google_analytics_api_ga4

Crate google_analytics_api_ga4 

Source
Expand description

§google-analytics-api-ga4 — Google Analytics 4 (GA4) Data API client for Rust

crates.io docs.rs downloads license

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 methodRust functionDescription
runReportAnalyticsDataApi::run_reportCore report of dimensions and metrics (sessions, pageviews, events, …)
batchRunReportsAnalyticsDataApi::batch_run_reportsUp to 5 reports in a single HTTP request
runPivotReportAnalyticsDataApi::run_pivot_reportPivot-table style reports
batchRunPivotReportsAnalyticsDataApi::batch_run_pivot_reportsMultiple pivot reports in one request
runRealtimeReportAnalyticsDataApi::run_realtime_reportRealtime active users for the last 30 minutes
checkCompatibilityAnalyticsDataApi::check_compatibilityCheck which dimensions/metrics can be combined
getMetadataAnalyticsDataApi::get_metadataList 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 handlingGoogleApiError implements std::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 with yup-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>:

VariantMeaning
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

§Breaking changes in 0.3.0

  • Upgraded reqwest from 0.12 to 0.13. The default TLS backend is now rustls (with aws-lc-rs) instead of native-tls / OpenSSL, so OpenSSL development headers are no longer required to build. If you depend on reqwest yourself with default-features = false, make sure you enable a TLS backend (rustls or native-tls).
  • Minimum supported Rust version is now 1.85 (required by reqwest 0.13).

§Breaking changes in 0.2.0

  • AnalyticsDataApi::run_pivot_report now takes RunPivotReportRequest and returns RunPivotReportResponse (previously it mistakenly used the checkCompatibility types).
  • AnalyticsDataApi::batch_run_reports now returns BatchRunReportsResponse (with a reports field).
  • AnalyticsDataApi::batch_run_pivot_reports now takes Vec<RunPivotReportRequest> and returns BatchRunPivotReportsResponse.
  • RunReportRequest::order_bys / RunRealtimeReportRequest::order_bys are now Option<Vec<OrderBy>> (matching the API schema; previously DimensionOrderBy was serialized without the OrderBy wrapper).
  • MinuteRange::start_minutes_ago / end_minutes_ago are now Option<i32>.
  • FilterExpression::not_expression is now Option<Box<FilterExpression>>.
  • NumericValue::double_value is now Option<f64>; int64_value was renamed from int_64_value.
  • MetricMetadata fields are now all Option (robust deserialization).
  • All struct fields are now public, and None fields are no longer serialized as null.
  • GoogleApiError gained a Response(u16, String) variant for non-2xx responses.

§License

MIT

Modules§

types

Structs§

AnalyticsDataApi
Entry point for the Google Analytics 4 (GA4) Data API v1beta.
BatchRunPivotReportsResponse
https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/properties/batchRunPivotReports
BatchRunReportsResponse
https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/properties/batchRunReports
CheckCompatibilityRequest
https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/properties/checkCompatibility
CheckCompatibilityResponse
DimensionCompatibility
GetMetadataResponse
https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/properties/getMetadata
MetricCompatibility
MinuteRange
https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/MinuteRange
RunPivotReportRequest
https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/properties/runPivotReport
RunRealtimeReportRequest
Realtime Dimensions & Metrics https://developers.google.com/analytics/devguides/reporting/data/v1/realtime-api-schema
RunReportRequest
https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/properties/runReport

Enums§

Compatibility
https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/Compatibility
GoogleApiError