How to Configure GA4 OAuth for Google Analytics Reporting: Step-by-Step Setup for awesome-gpt-image-2
To configure GA4 OAuth for Google Analytics reporting in the freestylefly/awesome-gpt-image-2 repository, you must populate four environment variables—GA4_PROPERTY_ID, GOOGLE_ANALYTICS_CLIENT_ID, GOOGLE_ANALYTICS_CLIENT_SECRET, and GOOGLE_ANALYTICS_REFRESH_TOKEN—and run the helper script to generate the long-lived refresh token.
The freestylefly/awesome-gpt-image-2 project implements a dual-authentication system for Google Analytics 4 (GA4) that supports both OAuth 2.0 user-account flows and service-account authentication. This guide walks through configuring GA4 OAuth for Google Analytics reporting using the detection logic and token management utilities built into the codebase.
GA4 Configuration Architecture
The repository determines which authentication method to use through automatic configuration detection in api/_lib/ga4.js.
OAuth Detection Logic
The hasOAuthConfig() function (lines 11-17) checks for the presence of all four required OAuth environment variables before activating the user-account flow:
// api/_lib/ga4.js – hasOAuthConfig()
function hasOAuthConfig() {
return Boolean(
process.env.GA4_PROPERTY_ID &&
process.env.GOOGLE_ANALYTICS_CLIENT_ID &&
process.env.GOOGLE_ANALYTICS_CLIENT_SECRET &&
process.env.GOOGLE_ANALYTICS_REFRESH_TOKEN
);
}
If these variables are missing, the system automatically falls back to service-account authentication. When OAuth is detected, the getOAuthClient() function (lines 45-55) initializes a GoogleAuth OAuth2Client with the stored credentials.
Step-by-Step GA4 OAuth Setup
Follow these steps to enable OAuth-based GA4 reporting in your deployment.
1. Create a GA4 Property and Collect IDs
In the Google Analytics UI, create a new GA4 property for your application. Record two critical identifiers:
- Measurement ID: The string starting with
G-(e.g.,G-XXXXXXXXXX) used for client-side tracking - Numeric Property ID: The integer identifier (e.g.,
123456789) used for server-side API calls
You will also need the property URL (e.g., https://gpt-image2.canghe.ai) for the OAuth consent screen configuration.
2. Generate OAuth 2.0 Credentials
Navigate to Google Cloud Console → APIs & Services → Credentials and create an OAuth 2.0 Client ID for a Web application. Copy the Client ID and Client Secret displayed in the console.
Add your application's URL to the Authorized redirect URIs list. The specific URI does not affect the refresh-token flow used by this repository, but it must be registered for the OAuth client to function.
3. Obtain a Long-Lived Refresh Token
Run the provided helper script to execute the OAuth consent flow:
node scripts/google-analytics-oauth.mjs
This script opens a browser URL where you authenticate with the Google account that has access to your GA4 property. After granting permissions for the Analytics Data API scopes, paste the authorization code back into the terminal. The script outputs the refresh token, which you must copy for the next step.
4. Configure Environment Variables
Copy .env.example to .env (or set these in your deployment platform) and populate the following variables:
# Required for server-side OAuth
GA4_PROPERTY_ID=123456789
GOOGLE_ANALYTICS_CLIENT_ID=your-client-id.apps.googleusercontent.com
GOOGLE_ANALYTICS_CLIENT_SECRET=your-client-secret
GOOGLE_ANALYTICS_REFRESH_TOKEN=your-refresh-token-from-step-3
# Optional: For client-side page tracking (unrelated to OAuth)
VITE_GA_MEASUREMENT_ID=G-XXXXXXXXXX
5. Deploy and Restart
After setting the environment variables, restart your server or redeploy to Vercel. The application detects the OAuth configuration on startup via hasOAuthConfig() and routes all GA4 data requests through the authenticated user account instead of the service account.
6. Verify the Integration
Navigate to the application dashboard. The UI will no longer display the "GA4 is not configured yet" message (as defined in src/main.jsx lines 206-207). The /api/admin/metrics endpoint will now return live traffic data instead of empty placeholders.
Core OAuth Implementation Details
Understanding the internal mechanics helps troubleshoot configuration issues.
Building the OAuth Client
When getOAuthClient() is called, it constructs an OAuth2Client instance from the google-auth-library and injects the refresh token:
// api/_lib/ga4.js – getOAuthClient()
function getOAuthClient() {
if (!hasOAuthConfig()) return null;
if (!oauthClient) {
oauthClient = new OAuth2Client(
process.env.GOOGLE_ANALYTICS_CLIENT_ID,
process.env.GOOGLE_ANALYTICS_CLIENT_SECRET
);
oauthClient.setCredentials({
refresh_token: process.env.GOOGLE_ANALYTICS_REFRESH_TOKEN
});
}
return oauthClient;
}
Executing Reports
The runReport() function uses the OAuth client to fetch a temporary access token, then calls the GA4 Data API endpoint https://analyticsdata.googleapis.com/v1beta/properties/{propertyId}:runReport. If the OAuth client is unavailable, it seamlessly falls back to service-account credentials.
Fetching Traffic Data
To retrieve metrics programmatically, import the utility functions:
// Example: fetch daily active users
import { getGa4Traffic } from './api/_lib/ga4.js';
async function showDaily() {
const data = await getGa4Traffic({ startDate: '7daysAgo', endDate: 'today' });
console.log(data.daily); // array of {date, uv, pv, visits, newUsers}
}
showDaily();
Summary
- OAuth 2.0 enables access to GA4 data using individual user permissions rather than service accounts.
- The repository auto-detects OAuth configuration when four specific environment variables are present in
api/_lib/ga4.js. - Use
scripts/google-analytics-oauth.mjsto generate the required refresh token through the standard Google consent flow. - Client-side tracking requires
VITE_GA_MEASUREMENT_ID, which operates independently from the server-side OAuth implementation. - The system gracefully falls back to service-account authentication if OAuth variables are missing.
Frequently Asked Questions
What is the difference between OAuth and service account authentication in this repository?
OAuth 2.0 uses the four environment variables (GOOGLE_ANALYTICS_CLIENT_ID, etc.) to authenticate as a specific Google user with GA4 access, which is ideal for accessing properties tied to personal accounts. Service account authentication uses a JSON key file for machine-to-machine access, which the repository uses as a fallback when OAuth is not configured. According to the source code in api/_lib/ga4.js, OAuth takes precedence when hasOAuthConfig() returns true.
How do I obtain the numeric GA4_PROPERTY_ID?
Sign in to Google Analytics and navigate to Admin → Property Settings. The numeric property ID appears in the Property details section. This differs from the Measurement ID (which starts with G-); the numeric ID is required for the Data API, while the Measurement ID is used only for the VITE_GA_MEASUREMENT_ID client-side tracking snippet.
Can I use the same OAuth credentials for multiple environments?
Yes, you can reuse the same GOOGLE_ANALYTICS_CLIENT_ID and GOOGLE_ANALYTICS_CLIENT_SECRET across staging and production environments. However, you must generate separate refresh tokens for each environment if you want to track which system is querying the API, or you can share the same GOOGLE_ANALYTICS_REFRESH_TOKEN if the account permissions are identical.
What happens if the refresh token expires or is revoked?
If the refresh token becomes invalid, the getOAuthClient() function will fail to obtain an access token when runReport() executes, causing the GA4 API requests to return authentication errors. The repository currently falls back to service-account authentication only when OAuth is completely unconfigured, not when tokens are invalid. To resolve this, re-run node scripts/google-analytics-oauth.mjs to generate a new refresh token and update your environment variables.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →