Active Users is GA4's signal for engagement right now, but it's buried in the default dashboard. You need to see trends, catch drops, and isolate problem segments—and GA4 doesn't make that easy in the UI alone. The solution: combine the Reports interface with the Data API to build real monitoring.
View Active Users in GA4 Reports
Start in the GA4 interface to see active users across dimensions and time ranges.
Open Realtime to see active users in the last 30 seconds
Go to Reports > Realtime in the left sidebar. Watch active users tick up as users interact with your site. This is useful for quick validation (e.g., during a launch), but won't show you trends over days or weeks.
Create a custom report with dimensions
Click Reports > Explore to build a custom view. Drag Active Users into metrics, then add dimensions like Country, Device Category, or Traffic Source. GA4 breaks down active user counts by each dimension value.
Query the same report structure programmatically
After designing your report in Explore, automate it with the Data API. Specify the same metrics and dimensions you set up in the UI; the API returns structured data you can log or alert on.
const {BetaAnalyticsDataClient} = require('@google-analytics/data');
const client = new BetaAnalyticsDataClient({
projectId: 'YOUR_GOOGLE_CLOUD_PROJECT_ID',
keyFilename: '/path/to/service-account-key.json',
});
const response = await client.runReport({
property: 'properties/YOUR_GA4_PROPERTY_ID',
dateRanges: [{startDate: '2025-03-20', endDate: '2025-03-26'}],
metrics: [{name: 'activeUsers'}],
dimensions: [{name: 'country'}, {name: 'deviceCategory'}],
});
console.log(response[0].rows);Query Active Users via the Data API
To monitor beyond the UI and automate feeds into your own dashboards, use the Google Analytics Data API with proper authentication and filtering.
Authenticate with a service account
Create a service account in your Google Cloud project and download the JSON key. Install the @google-analytics/data npm package and initialize the client. Your GA4 property ID is available under Admin > Property Settings.
const {BetaAnalyticsDataClient} = require('@google-analytics/data');
const client = new BetaAnalyticsDataClient({
projectId: 'YOUR_GOOGLE_CLOUD_PROJECT_ID',
keyFilename: './service-account-key.json',
});
console.log('Data API client authenticated');Request active users for a date range
Call runReport() with your property ID, a date range (YYYY-MM-DD format), and the activeUsers metric. GA4 returns the count for that period.
const response = await client.runReport({
property: 'properties/YOUR_GA4_PROPERTY_ID',
dateRanges: [
{
startDate: '2025-03-19',
endDate: '2025-03-26',
},
],
metrics: [
{name: 'activeUsers'},
],
});
const activeUserCount = response[0].rows[0].metricValues[0].value;
console.log(`Active Users (7-day): ${activeUserCount}`);Break down by dimension to find problem areas
Add a dimensions array to segment active users. GA4 returns one row per dimension value (e.g., per country or device type). This pinpoints which segments are losing engagement.
const response = await client.runReport({
property: 'properties/YOUR_GA4_PROPERTY_ID',
dateRanges: [{startDate: '2025-03-20', endDate: '2025-03-26'}],
metrics: [{name: 'activeUsers'}],
dimensions: [{name: 'country'}, {name: 'deviceCategory'}, {name: 'trafficSource'}],
});
response[0].rows.forEach(row => {
const country = row.dimensionValues[0].value;
const device = row.dimensionValues[1].value;
const source = row.dimensionValues[2].value;
const count = row.metricValues[0].value;
console.log(`${country} / ${device} / ${source}: ${count} active users`);
});Set Up Alerts for Active User Drops
Monitoring only matters if you catch anomalies. Automate hourly checks to alert before a real problem blows up.
Query today vs. last week's baseline
Fetch active users for today and the same day last week. Compare the percentage drop. A 30%+ decline is worth investigating; smaller swings are noise.
const moment = require('moment');
async function checkActiveUserDrop() {
const today = moment().format('YYYY-MM-DD');
const weekAgo = moment().subtract(7, 'days').format('YYYY-MM-DD');
// Today
const todayRes = await client.runReport({
property: 'properties/YOUR_GA4_PROPERTY_ID',
dateRanges: [{startDate: today, endDate: today}],
metrics: [{name: 'activeUsers'}],
});
const todayCount = parseInt(todayRes[0].rows[0].metricValues[0].value);
// Last week, same day
const weekRes = await client.runReport({
property: 'properties/YOUR_GA4_PROPERTY_ID',
dateRanges: [{startDate: weekAgo, endDate: weekAgo}],
metrics: [{name: 'activeUsers'}],
});
const weekCount = parseInt(weekRes[0].rows[0].metricValues[0].value);
const dropPercent = ((weekCount - todayCount) / weekCount) * 100;
if (dropPercent > 30) {
console.error(`⚠️ ALERT: Active users down ${dropPercent.toFixed(1)}% vs. last week`);
// Send Slack, PagerDuty, email, etc.
}
}
checkActiveUserDrop();Log baseline metrics hourly for trend tracking
Run a lightweight query every hour (via cron or Cloud Scheduler) and log the active user count with a timestamp. Store results in a database or monitoring tool. This builds a baseline to detect slow declines.
async function logActiveUsersHourly() {
const today = new Date().toISOString().split('T')[0]; // YYYY-MM-DD
const response = await client.runReport({
property: 'properties/YOUR_GA4_PROPERTY_ID',
dateRanges: [{startDate: today, endDate: today}],
metrics: [{name: 'activeUsers'}],
});
const count = response[0].rows[0].metricValues[0].value;
const timestamp = new Date().toISOString();
// Log to database, CloudWatch, or file
console.log(JSON.stringify({
timestamp,
activeUsers: count,
property: 'YOUR_GA4_PROPERTY_ID',
}));
}
// Run every hour (e.g., via Google Cloud Scheduler)
setInterval(logActiveUsersHourly, 60 * 60 * 1000);Common Pitfalls
- Confusing "Active Users" (fired an event in the last 30 min) with "Users" (unique count). They're different metrics with different definitions.
- Forgetting that GA4 only counts events, not pageviews. If your site doesn't fire events (or fires them rarely), Active Users will be zero. Always check Realtime first.
- Querying Realtime active users then comparing to a 30-day report. Realtime and batched reports use different definitions. Always compare like with like.
- Setting your alert threshold too low. Daily noise is normal; 10–20% swings happen without a real incident. Threshold at 30%+ or use a 7-day rolling average.
Wrapping Up
Monitoring active users in GA4 means three things: check the Realtime report for quick validation, design custom reports in Explore, then automate via the Data API to catch drops before they become incidents. If you want to track active user trends across GA4, Amplitude, Mixpanel, and Stripe from one dashboard, Product Analyst can help.