Active Users is GA4's headline metric for user health, but it counts something different than your daily login numbers. It measures unique users who fired at least one engagement event in the past 28 days — and what qualifies as 'engagement' matters more than you think. Most teams misread it because they confuse it with sessions or overlook which events actually trigger it.
What Active Users Actually Measures
GA4's Active Users is a 28-day rolling count of distinct users who generated engagement.
Understand the 28-Day Rolling Window
Active Users counts unique users with at least one engagement event in the past 28 days. This is a rolling window — each day, GA4 includes the last 28 days and excludes everything older. The metric changes daily, but it's not tied to calendar months. This is different from counting monthly active users as a fixed time period.
// GA4 engagement events include:
// - page_view (fired automatically on page load)
// - scroll (fired when user scrolls 90% down a page)
// - view_item (e-commerce)
// - purchase (transaction)
// - custom events marked as engagement
// To enable engagement tracking for a custom event:
// Navigate to Admin > Events > select your_event
// Toggle the 'Mark as engagement event' switch
gtag('event', 'demo_requested', {
'product_name': 'Analytics Pro',
'user_segment': 'enterprise'
});
// This fires as an engagement event if configured in AdminKnow Which Events Count as Engagement
Page views, scrolls, outbound link clicks, and site searches count as engagement by default. Custom events do not count unless you explicitly mark them. This is the most common source of confusion — your event count rises while Active Users stays flat because those events aren't marked as engagement.
// Using Google Analytics SDK via gtag.js
// Default engagement events (automatic):
gtag('event', 'page_view');
gtag('event', 'scroll', { 'percent_scrolled': 90 });
gtag('event', 'click', { 'link_url': 'https://example.com' });
// Custom event — NOT engagement by default
gtag('event', 'form_submission', {
'form_name': 'contact_form'
});
// To make form_submission count: go to GA4 Admin > Events
// Find 'form_submission', toggle 'Mark as engagement event'Distinguish Active Users from Sessions and Other Metrics
Active Users is user-level, not session-level. One user with 5 sessions counts as 1 active user, not 5. Sessions count visits (resets every 30 minutes), while Engaged Sessions count visits that included at least 10 seconds on-page or a conversion. Active Users is the broadest user metric.
How to Find Active Users in GA4
Active Users appears in reports and dashboards across GA4. Know where to look and what the numbers mean.
Check the Home Dashboard for Quick Snapshots
Open your GA4 property and go to Home. The overview section displays Active Users as a large metric card showing the 28-day count. Click the card to see trends over time. GA4 surfaces this by default because it's a key business metric.
// To fetch Active Users via Google Analytics Data API v1beta
const request = {
property: 'properties/YOUR_PROPERTY_ID',
dateRanges: [
{
startDate: '28daysAgo',
endDate: 'today'
}
],
metrics: [
{
name: 'activeUsers'
}
]
};
// Use @google-analytics/data client:
// const response = await client.runReport(request);
// response.rows[0].metricValues[0].value returns the active user countBuild Dimension-Based Reports in Explore
Go to Reports > Explore > Free Form. Drag Active Users into the Metric column. Add dimensions like User Source, Device Category, Country, or Operating System. Set your date range to 28 days for a true rolling count. This breaks down which user segments are most engaged.
// Example: Active Users by traffic source
const request = {
property: 'properties/YOUR_PROPERTY_ID',
dateRanges: [
{
startDate: '28daysAgo',
endDate: 'today'
}
],
metrics: [
{ name: 'activeUsers' },
{ name: 'sessions' }
],
dimensions: [
{ name: 'sessionSource' }
]
};
// Response shows active users grouped by source:
// direct, organic, paid_search, referral, etc.Create Multi-Metric Trend Reports
Go to Reports > All Reports > Create new report. Add Active Users, Sessions, and Engaged Sessions as metrics. Group by Date to see daily trends. When Sessions grow but Active Users stay flat, your repeat visitor rate is declining. This signals retention issues.
Access Active Users Programmatically
Pull Active Users data into dashboards and reports using the Data API or Firebase Admin SDK.
Query via Google Analytics Data API
The Data API is the official method for programmatic access. You'll need a service account with Viewer role on your GA4 property. Use the metric name activeUsers. The API respects your date range but always calculates a rolling 28-day count if that's your range.
// Node.js example using @google-analytics/data
const { BetaAnalyticsDataClient } = require('@google-analytics/data');
const client = new BetaAnalyticsDataClient();
async function getActiveUsers(propertyId) {
const response = await client.runReport({
property: `properties/${propertyId}`,
dateRanges: [
{
startDate: '28daysAgo',
endDate: 'today'
}
],
metrics: [
{ name: 'activeUsers' }
]
});
const activeUserCount = response[0].rows[0].metricValues[0].value;
console.log(`Active Users (28d): ${activeUserCount}`);
return activeUserCount;
}
getActiveUsers('YOUR_PROPERTY_ID');Query Daily Active Users for Trends
Break down Active Users by date to see daily variation. Add the date dimension to your request. Each row is a separate day with its own active user count. These are not cumulative — they reflect the rolling 28-day count on that specific date.
// Query daily active users for the past 7 days
const response = await client.runReport({
property: `properties/${propertyId}`,
dateRanges: [
{
startDate: '7daysAgo',
endDate: 'today'
}
],
metrics: [
{ name: 'activeUsers' },
{ name: 'sessions' }
],
dimensions: [
{ name: 'date' }
]
});
// Each row represents one day:
// 2026-03-20: 1,243 active users, 3,891 sessions
// 2026-03-21: 1,256 active users, 3,945 sessions
// ...Cache Results for Performance
GA4 API queries can be slow if run on every page load. Cache results in memory or Redis for 6-12 hours. Active Users changes gradually, so stale data is acceptable. This keeps your dashboards responsive without hammering the API.
// Example: cache Active Users in memory
let cachedActiveUsers = null;
let cacheTime = null;
const CACHE_DURATION = 6 * 60 * 60 * 1000; // 6 hours
async function getActiveUsersWithCache(propertyId) {
const now = Date.now();
if (cachedActiveUsers && cacheTime && (now - cacheTime < CACHE_DURATION)) {
console.log('Returning cached value');
return cachedActiveUsers;
}
const response = await client.runReport({
property: `properties/${propertyId}`,
dateRanges: [{ startDate: '28daysAgo', endDate: 'today' }],
metrics: [{ name: 'activeUsers' }]
});
cachedActiveUsers = response[0].rows[0].metricValues[0].value;
cacheTime = now;
return cachedActiveUsers;
}Common Pitfalls
- Confusing Active Users with Sessions: one user with 10 visits in 28 days is still 1 active user, not 10.
- Forgetting custom events need configuration: events you send don't count toward Active Users unless marked as engagement in Admin > Events.
- Comparing GA4 Active Users to other platforms directly: Stripe, Mixpanel, and Amplitude use different definitions (often calendar-based, not rolling). GA4's 28-day rolling window is unique.
- Assuming the 28-day window is fixed: Active Users on Monday is not the same as last Monday. It's always the past 28 days from today, rolling daily.
Wrapping Up
Active Users in GA4 is a rolling 28-day count of unique users with at least one engagement event. The critical detail is understanding which events count as engagement — page views and scrolls do by default, but custom events need configuration in the Admin panel. Find it in the Home dashboard for quick snapshots, use Explore for breakdowns by user cohort, and pull it via the Data API for your own dashboards. If you want to track this automatically across tools, Product Analyst can help.