Skip to main content
RapidDev - Software Development Agency
firebase-tutorial

How to Track Screen Views in Firebase Analytics for Web Apps

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.

What you'll learn

  • Why SPAs need manual screen_view tracking and how automatic page_view falls short
  • How to log screen_view events with custom screen names and classes
  • How to integrate screen tracking with React Router and other SPA routers
  • How to verify screen view events using Firebase DebugView
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner10 min read10-15 minFirebase Analytics (web), firebase/analytics v9+ modular SDK, React Router v6+, Vue Router, any SPA frameworkMarch 2026RapidDev Engineering Team
TL;DR

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

1

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.

typescript
1// Automatic tracking (limited for SPAs):
2// Firebase logs page_view on initial load with:
3// - page_location: full URL
4// - page_referrer: previous URL
5// - page_title: document.title
6
7// Manual tracking (recommended for SPAs):
8// You log screen_view with custom parameters:
9// - firebase_screen: human-readable screen name
10// - firebase_screen_class: component or route name
11
12// Disable automatic page_view if you want full manual control:
13import { initializeAnalytics } from "firebase/analytics";
14
15const analytics = initializeAnalytics(app, {
16 config: {
17 send_page_view: false, // Disable automatic page_view
18 },
19});

Expected result: You understand the difference between automatic page_view and manual screen_view, and can choose the approach that fits your app.

2

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.

typescript
1import { getAnalytics, logEvent } from "firebase/analytics";
2
3const analytics = getAnalytics();
4
5export 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 });
13
14 // Optionally update the document title for consistency
15 document.title = `${screenName} | Your App Name`;
16}
17
18// 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.

3

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.

typescript
1import { useEffect } from "react";
2import { useLocation } from "react-router-dom";
3import { trackScreenView } from "./analytics";
4
5// Map routes to screen names
6const SCREEN_NAMES: Record<string, string> = {
7 "/": "Home",
8 "/dashboard": "Dashboard",
9 "/profile": "User Profile",
10 "/settings": "Settings",
11 "/pricing": "Pricing",
12};
13
14function getScreenName(pathname: string): string {
15 // Exact match
16 if (SCREEN_NAMES[pathname]) return SCREEN_NAMES[pathname];
17
18 // Dynamic routes: /posts/123 -> "Post Detail"
19 if (pathname.startsWith("/posts/")) return "Post Detail";
20 if (pathname.startsWith("/users/")) return "User Profile";
21
22 return "Unknown Page";
23}
24
25export function AnalyticsTracker() {
26 const location = useLocation();
27
28 useEffect(() => {
29 const screenName = getScreenName(location.pathname);
30 trackScreenView(screenName, "WebApp");
31 }, [location.pathname]);
32
33 return null; // This component renders nothing
34}
35
36// 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.

4

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.

typescript
1// router/index.ts
2import { createRouter, createWebHistory } from "vue-router";
3import { trackScreenView } from "@/analytics";
4
5const 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});
28
29// Track screen views on every navigation
30router.afterEach((to) => {
31 const screenName = (to.meta.screenName as string) || to.name?.toString() || "Unknown";
32 trackScreenView(screenName, "VueApp");
33});
34
35export 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.

5

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.

typescript
1// Enable debug mode in the browser console:
2// Open Chrome DevTools > Console and run:
3// firebase.analytics().setAnalyticsCollectionEnabled(true);
4
5// Or add the debug parameter to your URL:
6// https://your-app.com/?debug_event=true
7
8// Or install the GA Debugger Chrome extension
9// and enable verbose mode
10
11// For programmatic debug mode in development:
12import { getAnalytics, setAnalyticsCollectionEnabled } from "firebase/analytics";
13
14const analytics = getAnalytics();
15
16if (process.env.NODE_ENV === "development") {
17 // Events still appear in DebugView even in dev mode
18 // as long as analytics is initialized
19 console.log("Firebase Analytics debug mode active");
20}
21
22// Verify in Firebase Console:
23// 1. Go to Analytics > DebugView
24// 2. Select your debug device from the device list
25// 3. Navigate through your app
26// 4. screen_view events should appear in the timeline
27// 5. Click each event to see firebase_screen parameter

Expected result: screen_view events appear in DebugView with the correct firebase_screen and firebase_screen_class parameters as you navigate your app.

6

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.

typescript
1// Firebase Console reports for screen views:
2//
3// 1. Events report: Analytics > Events > screen_view
4// Shows total screen_view count over time
5//
6// 2. Pages and screens: Analytics > Engagement > Pages and screens
7// Groups by firebase_screen parameter
8// Shows: screen views, users, avg engagement time
9//
10// 3. Custom audience example:
11// Create an audience of users who viewed "Pricing" screen
12// Analytics > Audiences > New audience
13// Condition: screen_view where firebase_screen = "Pricing"
14//
15// 4. BigQuery export for advanced analysis:
16// Firebase Console > Project Settings > Integrations > BigQuery
17// Enable daily export, then query events_* tables:
18//
19// SELECT
20// event_params.value.string_value AS screen_name,
21// COUNT(*) AS views
22// FROM `project.analytics_123.events_*`,
23// UNNEST(event_params) AS event_params
24// WHERE event_name = 'screen_view'
25// AND event_params.key = 'firebase_screen'
26// GROUP BY screen_name
27// ORDER BY views DESC

Expected 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

analytics.ts
1// Firebase Analytics — Screen View Tracking for SPAs
2import { initializeApp } from "firebase/app";
3import {
4 initializeAnalytics,
5 logEvent,
6 getAnalytics,
7} from "firebase/analytics";
8
9const 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};
18
19const app = initializeApp(firebaseConfig);
20
21// Initialize with automatic page_view disabled (manual tracking)
22const analytics = initializeAnalytics(app, {
23 config: {
24 send_page_view: false,
25 },
26});
27
28// Track a screen view
29export 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}
39
40// Track a custom event alongside screen view
41export function trackEvent(
42 eventName: string,
43 params: Record<string, string | number> = {}
44) {
45 logEvent(analytics, eventName, params);
46}
47
48// Route-to-screen-name mapping
49const 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};
58
59// Dynamic route matching
60function 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}
66
67// Get screen name from any path
68export function getScreenName(pathname: string): string {
69 return SCREEN_MAP[pathname]
70 || matchDynamicRoute(pathname)
71 || "Unknown Page";
72}
73
74// 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.

ChatGPT Prompt

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.

Firebase Prompt

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.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.