You're shipping a new feature and need to know immediately if something breaks — or if it drives unexpected event volume. GA4's alert system gives you multiple ways to monitor event counts, from simple UI-based rules to programmatic thresholds in BigQuery. Let's walk through your options.
Using GA4's Built-in Alerts
The simplest path: set up alerts directly in GA4 that fire email notifications when event counts cross a threshold.
Navigate to the Alerts section
Open your GA4 property and go to Admin > Alerts. This is where all custom alerts live for your property.
Create a new alert
Click the Create alert button. You'll be prompted to name it (e.g., 'High Purchase Event Volume') and select the alert type.
Configure the event count condition
Under Condition, select Event count. Then choose whether you want to alert when counts go above a threshold, below a threshold, or change by a percentage. For example, if your baseline is 100 purchase events per hour, set it to alert when counts drop below 80 or spike above 200.
// GA4 alerts don't have a direct API, but you can query event counts
// using the Google Analytics Data API to validate thresholds:
const analyticsdata = require('@google-analytics/data');
const client = new analyticsdata.BetaAnalyticsDataClient();
const request = {
property: 'properties/YOUR_PROPERTY_ID',
dateRanges: [{ startDate: '1daysAgo', endDate: 'today' }],
metrics: [{ name: 'eventCount' }],
dimensions: [{ name: 'eventName' }],
dimensionFilter: {
filter: {
fieldName: 'eventName',
stringFilter: { matchType: 'EXACT', value: 'purchase' }
}
}
};
const [response] = await client.runReport(request);
console.log(`Total purchase events: ${response.rows[0].metricValues[0].value}`);Add notification email addresses
Under Notification, enter the email addresses that should receive the alert. You can add multiple team members. GA4 will send the alert when the condition is triggered.
Programmatic Monitoring with the Reporting API
If you need finer control — like alerting based on custom logic, running checks on intervals, or integrating with Slack — query event counts programmatically and build your own alert logic.
Set up Google Analytics Data API access
Create a service account in Google Cloud Console, grant it Viewer role on your GA4 property, and download the JSON key. Install the client library: npm install @google-analytics/data.
Query event counts for a specific time range
Use the runReport method to fetch event counts. This example pulls today's purchase events broken down by hour so you can spot drops or spikes.
const { BetaAnalyticsDataClient } = require('@google-analytics/data');
const client = new BetaAnalyticsDataClient({
projectId: 'your-gcp-project',
credentials: require('./service-account-key.json')
});
const request = {
property: 'properties/YOUR_PROPERTY_ID',
dateRanges: [{ startDate: '1daysAgo', endDate: 'today' }],
metrics: [{ name: 'eventCount' }],
dimensions: [{ name: 'dateHour' }],
dimensionFilter: {
filter: {
fieldName: 'eventName',
stringFilter: { matchType: 'EXACT', value: 'purchase' }
}
},
orderBys: [{ dimension: { orderType: 'ALPHANUMERIC', dimensionName: 'dateHour' } }]
};
const [response] = await client.runReport(request);
response.rows.forEach(row => {
const hour = row.dimensions[0];
const count = row.metricValues[0].value;
console.log(`Hour ${hour}: ${count} events`);
});Implement threshold logic and notifications
Compare the returned counts against your baseline or threshold. If a condition is met, send a notification via email, Slack, or your monitoring system.
// Simple threshold check
const BASELINE = 100; // expected events per hour
const ALERT_THRESHOLD = 0.5; // alert if below 50% of baseline
let isAlert = false;
response.rows.forEach(row => {
const count = parseInt(row.metricValues[0].value);
if (count < BASELINE * ALERT_THRESHOLD) {
console.error(`⚠️ Low event count: ${count} (expected ~${BASELINE})`);
isAlert = true;
}
});
if (isAlert) {
// Send to Slack, PagerDuty, email, etc.
await fetch('https://hooks.slack.com/services/YOUR/WEBHOOK', {
method: 'POST',
body: JSON.stringify({
text: `🚨 GA4 Purchase Event Alert: Event count below threshold`
})
});
}Real-time Alerts via BigQuery Export
For the lowest latency and most control, stream your GA4 events to BigQuery and set up alerts based on the raw event stream.
Enable BigQuery streaming export
In GA4, go to Admin > BigQuery Linking and link your GA4 property to a BigQuery project. GA4 will stream events to a daily table (e.g., events_YYYYMMDD) and an intraday table (e.g., events_intraday_YYYYMMDD) that updates every few seconds.
Query the intraday table for near-real-time counts
The intraday table is fresher than the daily table. Query it to get event counts within seconds of the event firing.
const { BigQuery } = require('@google-cloud/bigquery');
const bigquery = new BigQuery({
projectId: 'your-gcp-project',
keyFilename: './service-account-key.json'
});
const query = `
SELECT
event_name,
COUNT(*) as event_count,
MAX(TIMESTAMP_MILLIS(event_timestamp)) as last_event_time
FROM
\`your-project.analytics_YOUR_GA4_ID.events_intraday_YYYYMMDD\`
WHERE
event_name = 'purchase'
AND TIMESTAMP_MILLIS(event_timestamp) > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 5 MINUTE)
GROUP BY event_name
`;
const [rows] = await bigquery.query({
query: query,
location: 'US',
useQueryCache: false
});
console.log(`Purchase events in last 5 minutes: ${rows[0]?.event_count || 0}`);Set up Cloud Monitoring or a scheduled check
Wrap your query in a Cloud Function or scheduled script. If event counts drop below a threshold or show an anomaly, trigger an alert via email, Slack, or PagerDuty.
// Example: Cloud Function triggered every minute
const functions = require('@google-cloud/functions-framework');
const { BigQuery } = require('@google-cloud/bigquery');
const bigquery = new BigQuery();
functions.http('checkEventCounts', async (req, res) => {
const [rows] = await bigquery.query({
query: `SELECT COUNT(*) as cnt FROM \`your-project.analytics_YOUR_GA4_ID.events_intraday_YYYYMMDD\` WHERE event_name = 'purchase' AND TIMESTAMP_MILLIS(event_timestamp) > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 5 MINUTE)`
});
const count = rows[0]?.cnt || 0;
const threshold = 50;
if (count < threshold) {
await fetch('https://hooks.slack.com/services/YOUR/WEBHOOK', {
method: 'POST',
body: JSON.stringify({ text: `🚨 Purchase events dropped to ${count}` })
});
}
res.status(200).send(`Check complete: ${count} events`);
});Common Pitfalls
- Forgetting that GA4's built-in alerts are property-scoped, not view-scoped. If you have multiple views, you may miss alerts on the wrong property.
- Setting alert thresholds too tight. GA4 data has natural variance; a 5% drop doesn't always mean something broke. Use moving averages or baseline comparisons instead.
- Using the daily table in BigQuery when you want near-real-time alerts. Always query the
events_intraday_*table for fresher data. - Not accounting for time zones. GA4 reports in your property's time zone, but BigQuery is always UTC. Make sure your queries and thresholds align.
Wrapping Up
You now have three ways to monitor event counts in GA4: quick email alerts through the UI, programmatic checks via the Reporting API, or near-real-time streaming from BigQuery. Start with GA4's built-in alerts for simple cases, then scale to BigQuery when you need custom logic or tighter latency. If you want to track this automatically across tools, Product Analyst can help.