Your users aren't exploring your site as much as you thought. Pages per session tells you how many pages users view before leaving — and it's calculated differently in GA4 than it was in Universal Analytics. If this metric is dropping, it signals engagement problems. If it's rising, you've got a solid content strategy. Either way, you need to monitor it accurately.
Access Pages Per Session Data in GA4 Reports
GA4 doesn't use the old "Pages per Session" metric anymore. Instead, it uses engagement metrics like average engagement time and screen page views. Here's how to find the data you need.
Step 1: Navigate to the Engagement Report
Open GA4 and go to Reports > Engagement > Pages and screens. This shows individual pages ranked by user engagement, with data broken down by traffic source, device, and audience. You'll see screen page views and sessions here, which you can use to calculate pages per session manually.
Step 2: Create a Custom Report with Key Metrics
The default report doesn't show pages per session in one column. Click Customize this report in the top right. Add dimensions like Default Channel Grouping or Device Category, then add metrics Screenpage Views and Sessions. You can manually divide these columns to get pages per session by segment.
Step 3: Query Pages Per Session Programmatically with the Data API
For real-time dashboards or automated monitoring, use the Google Analytics Data API. This JavaScript example queries pages per session by device category over the last 30 days.
const {BetaAnalyticsDataClient} = require('@google-analytics/data');
const client = new BetaAnalyticsDataClient();
async function getPagesPerSession() {
const request = {
property: 'properties/YOUR_PROPERTY_ID',
dateRanges: [{startDate: '30daysAgo', endDate: 'today'}],
dimensions: [{name: 'deviceCategory'}],
metrics: [{name: 'screenPageViews'}, {name: 'sessions'}],
};
const response = await client.runReport(request);
response.rows.forEach(row => {
const device = row.dimensions[0];
const pageViews = parseInt(row.metricValues[0].value);
const sessions = parseInt(row.metricValues[1].value);
const pagesPerSession = (pageViews / sessions).toFixed(2);
console.log(`${device}: ${pagesPerSession} pages/session`);
});
}
getPagesPerSession();screenPageViews metric counts each unique page in a session only once. If a user visits the same page twice, it still counts as one page view. Use pageviewCount in events if you need to count repeated pages.Ensure Accurate Page Tracking with gtag.js
GA4 automatically tracks pageviews, but if your site is a single-page app (SPA), you need to manually fire page_view events. Otherwise, GA4 won't register navigation between sections and your pages per session will be artificially low.
Step 1: Verify GA4 Tracking Is Active
Check that your GA4 tracking code is installed in the head of your HTML or via Google Tag Manager. GA4 fires an automatic page_view event on initial page load. Open DevTools, go to the Network tab, and look for requests to google-analytics.com with your property ID (starting with G-).
<!-- GA4 tracking code -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX');
</script>Step 2: Manually Fire Page View Events for SPAs
If you're using React, Vue, or Next.js, the page_view event doesn't fire on route changes. You need to manually trigger it when the user navigates. Use the gtag page_view event with the page_path parameter to track navigation.
// Track page views in a single-page app
function trackPageView(path) {
gtag('event', 'page_view', {
'page_path': path,
'page_title': document.title,
'page_location': window.location.href
});
}
// Example: React Router
import {useEffect} from 'react';
import {useLocation} from 'react-router-dom';
export default function App() {
const location = useLocation();
useEffect(() => {
trackPageView(location.pathname);
}, [location.pathname]);
return <div>Your app</div>;
}Step 3: Verify Page View Events in Real Time
In GA4, go to Reports > Realtime and filter by the page_view event. Navigate your site and confirm that each page view appears in the real-time report. If pages per session is low but you're seeing navigation in realtime, check that your tracking code is actually firing.
// Add debug logging to confirm events are firing
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'event': 'page_view',
'page_path': window.location.pathname,
'timestamp': new Date().toISOString(),
'debug': true
});
console.log('Page view event pushed:', window.location.pathname);Monitor Pages Per Session with Alerts and Dashboards
Pages per session fluctuates with traffic quality and seasonality. Set up automated alerts so you catch drops before they impact your business.
Step 1: Create an Alert for Engagement Drops
Go to Admin > Alerts and click Create alert. Set the metric to Screenpage Views, define a threshold (e.g., alert if it drops 25% below the baseline), and choose who gets notified. GA4 sends alerts via email when the threshold is breached.
Step 2: Build a Trend Chart in Looker Studio
Connect GA4 to Looker Studio to track pages per session over time. Create a data source from GA4, then add a line chart with Date as the dimension and Screenpage Views and Sessions as metrics. Create a calculated field to divide pageviews by sessions for a continuous trend.
// Fetch 90-day trend data for export to Looker Studio
const request = {
property: 'properties/YOUR_PROPERTY_ID',
dateRanges: [{startDate: '90daysAgo', endDate: 'today'}],
dimensions: [{name: 'date'}, {name: 'source'}],
metrics: [{name: 'screenPageViews'}, {name: 'sessions'}],
orderBys: [{dimension: {name: 'date'}}]
};
const response = await client.runReport(request);
const trends = response.rows.map(row => ({
date: row.dimensions[0],
source: row.dimensions[1],
pagesPerSession: parseFloat(
(parseInt(row.metricValues[0].value) / parseInt(row.metricValues[1].value)).toFixed(2)
)
}));
console.table(trends);Step 3: Segment by Traffic Source to Spot Problem Areas
Pages per session varies by traffic source. Organic search users often view more pages than paid ad clicks. In your custom report, add Default Channel Grouping as a dimension to see which channels have low engagement. If organic drops while paid stays flat, you have a content or SEO issue.
Common Pitfalls
- Forgetting that GA4's screenPageViews metric counts unique pages in a session, not total clicks — repeat visits to the same page don't increase the count
- Not manually tracking page_view events in single-page apps, resulting in missing navigation and severely undercounted pages per session
- Confusing screenPageViews with events — screenPageViews is the metric for pages per session; eventCount includes all custom events and gives you inflated numbers
- Setting up alerts on pages per session without segmenting by source or device, leading to noisy alerts that don't indicate real problems
Wrapping Up
Pages per session is a reliable signal of engagement depth. By querying GA4's Data API, ensuring SPAs track page views correctly, and monitoring trends with Looker Studio alerts, you'll catch engagement issues early and know exactly where users are dropping off. If you want to track this automatically across tools, Product Analyst can help.