Firebase Analytics tracks page views automatically for traditional websites, but single-page applications need manual screen_view logging because the page does not reload on navigation. Call logEvent(analytics, 'screen_view', { firebase_screen, firebase_screen_class }) on every route change. In React, use a useEffect hook that listens to location changes from React Router. Verify events in the Firebase Console DebugView.
Screen View Tracking for Single-Page Applications
Firebase Analytics automatically logs a page_view event when the page loads, but in SPAs, client-side routing changes the URL without triggering a full page load. This means Firebase only sees the initial page view, not subsequent navigation. This tutorial shows you how to log screen_view events on every route change so your analytics accurately reflect how users navigate your app.
Prerequisites
- A Firebase project with Analytics enabled in the Firebase Console
- Firebase JS SDK initialized with getAnalytics() in your web app
- A single-page application using client-side routing (React Router, Vue Router, etc.)
- The measurementId from your Firebase config (starts with G-)
Step-by-step guide
Understand automatic vs manual page view tracking
Understand automatic vs manual page view tracking
Firebase Analytics automatically tracks a page_view event on initial page load and when the browser history changes (popstate event). However, many SPA routers use pushState which does not always trigger the automatic event. Additionally, the automatic page_view only captures the URL path, not a meaningful screen name. Manual screen_view events give you full control over what is tracked and how it appears in reports.
1// Automatic tracking (limited for SPAs):2// Firebase logs page_view on initial load with:3// - page_location: full URL4// - page_referrer: previous URL5// - page_title: document.title67// Manual tracking (recommended for SPAs):8// You log screen_view with custom parameters:9// - firebase_screen: human-readable screen name10// - firebase_screen_class: component or route name1112// Disable automatic page_view if you want full manual control:13import { initializeAnalytics } from "firebase/analytics";1415const analytics = initializeAnalytics(app, {16 config: {17 send_page_view: false, // Disable automatic page_view18 },19});Expected result: You understand the difference between automatic page_view and manual screen_view, and can choose the approach that fits your app.
Create a screen tracking utility function
Create a screen tracking utility function
Build a reusable function that logs screen_view events with consistent parameters. Include firebase_screen (the human-readable screen name), firebase_screen_class (the component or route group), and optionally update the document title to match. This function will be called from your router integration.
1import { getAnalytics, logEvent } from "firebase/analytics";23const analytics = getAnalytics();45export function trackScreenView(6 screenName: string,7 screenClass: string = "Page"8) {9 logEvent(analytics, "screen_view", {10 firebase_screen: screenName,11 firebase_screen_class: screenClass,12 });1314 // Optionally update the document title for consistency15 document.title = `${screenName} | Your App Name`;16}1718// Usage examples:19// trackScreenView("Home", "LandingPage");20// trackScreenView("User Profile", "ProfilePage");21// trackScreenView("Settings", "SettingsPage");Expected result: A reusable trackScreenView function is ready to be called from your router on every navigation event.
Integrate with React Router v6
Integrate with React Router v6
In React, use the useLocation hook from React Router inside a useEffect to detect route changes and log screen_view events. Create a component that wraps your app's routes and calls the tracking function whenever the pathname changes. Map route paths to human-readable screen names using a lookup object.
1import { useEffect } from "react";2import { useLocation } from "react-router-dom";3import { trackScreenView } from "./analytics";45// Map routes to screen names6const SCREEN_NAMES: Record<string, string> = {7 "/": "Home",8 "/dashboard": "Dashboard",9 "/profile": "User Profile",10 "/settings": "Settings",11 "/pricing": "Pricing",12};1314function getScreenName(pathname: string): string {15 // Exact match16 if (SCREEN_NAMES[pathname]) return SCREEN_NAMES[pathname];1718 // Dynamic routes: /posts/123 -> "Post Detail"19 if (pathname.startsWith("/posts/")) return "Post Detail";20 if (pathname.startsWith("/users/")) return "User Profile";2122 return "Unknown Page";23}2425export function AnalyticsTracker() {26 const location = useLocation();2728 useEffect(() => {29 const screenName = getScreenName(location.pathname);30 trackScreenView(screenName, "WebApp");31 }, [location.pathname]);3233 return null; // This component renders nothing34}3536// In your App.tsx:37// <BrowserRouter>38// <AnalyticsTracker />39// <Routes>...</Routes>40// </BrowserRouter>Expected result: Every route change in your React app logs a screen_view event with a descriptive screen name.
Integrate with Vue Router
Integrate with Vue Router
For Vue apps, use the router's afterEach navigation guard to track screen views. This fires after every successful navigation, including programmatic navigations and back/forward button usage. Access the route meta or name to determine the screen name.
1// router/index.ts2import { createRouter, createWebHistory } from "vue-router";3import { trackScreenView } from "@/analytics";45const router = createRouter({6 history: createWebHistory(),7 routes: [8 {9 path: "/",10 name: "Home",11 component: () => import("@/views/Home.vue"),12 meta: { screenName: "Home" },13 },14 {15 path: "/dashboard",16 name: "Dashboard",17 component: () => import("@/views/Dashboard.vue"),18 meta: { screenName: "Dashboard" },19 },20 {21 path: "/settings",22 name: "Settings",23 component: () => import("@/views/Settings.vue"),24 meta: { screenName: "Settings" },25 },26 ],27});2829// Track screen views on every navigation30router.afterEach((to) => {31 const screenName = (to.meta.screenName as string) || to.name?.toString() || "Unknown";32 trackScreenView(screenName, "VueApp");33});3435export default router;Expected result: Every route change in your Vue app logs a screen_view event using the screen name defined in the route's meta field.
Enable debug mode and verify in DebugView
Enable debug mode and verify in DebugView
Firebase Analytics events are batched and sent periodically, which means they do not appear in reports immediately (24-48 hour delay). To see events in real time during development, enable debug mode. Open the Firebase Console, navigate to Analytics > DebugView, and verify that screen_view events appear with the correct parameters as you navigate your app.
1// Enable debug mode in the browser console:2// Open Chrome DevTools > Console and run:3// firebase.analytics().setAnalyticsCollectionEnabled(true);45// Or add the debug parameter to your URL:6// https://your-app.com/?debug_event=true78// Or install the GA Debugger Chrome extension9// and enable verbose mode1011// For programmatic debug mode in development:12import { getAnalytics, setAnalyticsCollectionEnabled } from "firebase/analytics";1314const analytics = getAnalytics();1516if (process.env.NODE_ENV === "development") {17 // Events still appear in DebugView even in dev mode18 // as long as analytics is initialized19 console.log("Firebase Analytics debug mode active");20}2122// Verify in Firebase Console:23// 1. Go to Analytics > DebugView24// 2. Select your debug device from the device list25// 3. Navigate through your app26// 4. screen_view events should appear in the timeline27// 5. Click each event to see firebase_screen parameterExpected result: screen_view events appear in DebugView with the correct firebase_screen and firebase_screen_class parameters as you navigate your app.
View screen view reports in the Firebase Console
View screen view reports in the Firebase Console
After events have been collected for 24-48 hours, view them in the Firebase Console. Navigate to Analytics > Events and find the screen_view event. Click it to see parameter breakdowns including which screens are viewed most. Use the Engagement > Pages and screens report for a dedicated screen-level view. Create custom audiences based on screen views to segment users by the features they use.
1// Firebase Console reports for screen views:2//3// 1. Events report: Analytics > Events > screen_view4// Shows total screen_view count over time5//6// 2. Pages and screens: Analytics > Engagement > Pages and screens7// Groups by firebase_screen parameter8// Shows: screen views, users, avg engagement time9//10// 3. Custom audience example:11// Create an audience of users who viewed "Pricing" screen12// Analytics > Audiences > New audience13// Condition: screen_view where firebase_screen = "Pricing"14//15// 4. BigQuery export for advanced analysis:16// Firebase Console > Project Settings > Integrations > BigQuery17// Enable daily export, then query events_* tables:18//19// SELECT20// event_params.value.string_value AS screen_name,21// COUNT(*) AS views22// FROM `project.analytics_123.events_*`,23// UNNEST(event_params) AS event_params24// WHERE event_name = 'screen_view'25// AND event_params.key = 'firebase_screen'26// GROUP BY screen_name27// ORDER BY views DESCExpected result: You can see which screens are viewed most, how long users spend on each screen, and create audiences based on screen view behavior.
Complete working example
1// Firebase Analytics — Screen View Tracking for SPAs2import { initializeApp } from "firebase/app";3import {4 initializeAnalytics,5 logEvent,6 getAnalytics,7} from "firebase/analytics";89const firebaseConfig = {10 apiKey: "your-api-key",11 authDomain: "your-project.firebaseapp.com",12 projectId: "your-project",13 storageBucket: "your-project.appspot.com",14 messagingSenderId: "123456789",15 appId: "1:123456789:web:abc123",16 measurementId: "G-XXXXXXXXXX",17};1819const app = initializeApp(firebaseConfig);2021// Initialize with automatic page_view disabled (manual tracking)22const analytics = initializeAnalytics(app, {23 config: {24 send_page_view: false,25 },26});2728// Track a screen view29export function trackScreenView(30 screenName: string,31 screenClass: string = "Page"32) {33 logEvent(analytics, "screen_view", {34 firebase_screen: screenName,35 firebase_screen_class: screenClass,36 });37 document.title = `${screenName} | YourApp`;38}3940// Track a custom event alongside screen view41export function trackEvent(42 eventName: string,43 params: Record<string, string | number> = {}44) {45 logEvent(analytics, eventName, params);46}4748// Route-to-screen-name mapping49const SCREEN_MAP: Record<string, string> = {50 "/": "Home",51 "/dashboard": "Dashboard",52 "/profile": "User Profile",53 "/settings": "Settings",54 "/pricing": "Pricing",55 "/login": "Login",56 "/signup": "Sign Up",57};5859// Dynamic route matching60function matchDynamicRoute(path: string): string | null {61 if (/^\/posts\/[\w-]+$/.test(path)) return "Post Detail";62 if (/^\/users\/[\w-]+$/.test(path)) return "User Profile";63 if (/^\/projects\/[\w-]+$/.test(path)) return "Project Detail";64 return null;65}6667// Get screen name from any path68export function getScreenName(pathname: string): string {69 return SCREEN_MAP[pathname]70 || matchDynamicRoute(pathname)71 || "Unknown Page";72}7374// React integration component (separate file recommended)75// import { useEffect } from "react";76// import { useLocation } from "react-router-dom";77//78// export function AnalyticsTracker() {79// const location = useLocation();80// useEffect(() => {81// const name = getScreenName(location.pathname);82// trackScreenView(name, "WebApp");83// }, [location.pathname]);84// return null;85// }Common mistakes when tracking Screen Views in Firebase Analytics for Web Apps
Why it's a problem: Relying on automatic page_view tracking for SPAs, which only captures the initial page load and misses client-side route changes
How to avoid: Manually log screen_view events on every route change using your router's navigation hooks or a useEffect that watches the location.
Why it's a problem: Using URL paths as screen names, resulting in thousands of unique screen names from dynamic routes like /posts/abc123
How to avoid: Map URL patterns to descriptive screen names: /posts/:id becomes 'Post Detail', not '/posts/abc123'. Use a lookup table and regex matching for dynamic routes.
Why it's a problem: Expecting screen_view events to appear in Firebase Console reports immediately after logging them
How to avoid: Firebase Analytics has a 24-48 hour reporting delay. Use DebugView for real-time verification during development.
Why it's a problem: Logging screen_view inside a component that renders multiple times, causing duplicate events for the same navigation
How to avoid: Track screen views in a single location — a dedicated tracker component or router guard — not inside individual page components.
Best practices
- Disable automatic page_view tracking (send_page_view: false) and use manual screen_view for full control in SPAs
- Use descriptive, human-readable screen names like 'User Profile' instead of raw URL paths
- Create a centralized route-to-screen-name mapping for consistency across your app
- Track screen views in one place (router hook or tracker component) to avoid duplicate events
- Use firebase_screen_class to group screens by type (e.g., 'Settings', 'Dashboard', 'Auth')
- Update document.title alongside screen_view events for consistent analytics and browser history
- Test with DebugView during development before relying on delayed reports
- Export to BigQuery for advanced screen flow analysis and custom funnel reports
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I have a React SPA with React Router v6 and Firebase Analytics. Automatic page_view tracking only captures the initial load, not route changes. Write a complete screen view tracking solution: a trackScreenView function, a route-to-screen-name mapping that handles both static and dynamic routes, and a React component that tracks on every route change. Show how to verify with DebugView.
Set up screen view tracking in my Firebase web app. Disable automatic page_view, create a trackScreenView function that logs screen_view with firebase_screen and firebase_screen_class parameters, and integrate it with React Router v6 using a useLocation-based tracker component. Include a mapping for routes: /, /dashboard, /settings, /posts/:id.
Frequently asked questions
Does Firebase Analytics track page views automatically in SPAs?
Firebase Analytics tracks a page_view event on initial page load and sometimes on history.pushState changes. However, this is unreliable for SPAs. Manual screen_view tracking on every route change is the recommended approach.
What is the difference between page_view and screen_view in Firebase Analytics?
page_view is automatically tracked and uses URL-based parameters (page_location, page_title). screen_view is manually tracked and uses firebase_screen and firebase_screen_class parameters that you define. For SPAs, screen_view gives you better control over naming.
Why do my screen_view events not appear in Firebase Console reports?
Firebase Analytics has a 24-48 hour reporting delay. Use DebugView (Analytics > DebugView) for real-time verification during development. Install the Google Analytics Debugger Chrome extension for immediate event visibility.
Can I track screen views without disabling automatic page_view?
Yes. Both can coexist. Automatic page_view events and manual screen_view events appear as separate events in your reports. Some teams keep both for redundancy.
How do I track screen views in a Next.js app?
In Next.js App Router, create a client component that uses the usePathname hook from next/navigation inside a useEffect. Log the screen_view event when the pathname changes. Place the component inside your root layout.
Is there a cost for logging screen_view events?
Firebase Analytics is free and has no per-event charges. You can log unlimited screen_view events. However, custom parameters are limited to 25 per event and 50 custom event-scoped dimensions per project.
Can RapidDev help set up analytics tracking for my SPA?
Yes. RapidDev can implement a complete screen view tracking solution for your SPA, including router integration, screen name mapping, custom event tracking, DebugView verification, and BigQuery export for advanced analytics.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation