Skip to main content
RapidDev - Software Development Agency
bolt-ai-integrationsBolt Chat + API Route

How to Integrate Bolt.new with Google Analytics 4

To add Google Analytics 4 to your Bolt.new app, get a GA4 Measurement ID (starts with G-) from Google Analytics, then add the gtag.js script tag to your HTML head or install the GA4 npm integration. The script runs in the user's browser and works in both the Bolt WebContainer preview and production. Page view tracking is automatic once installed. Custom events require a single FullStory.gtag() function call.

What you'll learn

  • How to create a Google Analytics 4 property and get your Measurement ID
  • How to add the GA4 gtag.js tag to a Vite or Next.js Bolt app for automatic page view tracking
  • How to send custom events (signups, purchases, feature usage) to GA4 from React components
  • How to use the GA4 Data API via a Next.js API route to build a custom analytics dashboard
  • Why GA4's client-side tag works in Bolt's WebContainer while server-side analytics integrations require deployment
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate18 min read15 minutesAnalyticsApril 2026RapidDev Engineering Team
TL;DR

To add Google Analytics 4 to your Bolt.new app, get a GA4 Measurement ID (starts with G-) from Google Analytics, then add the gtag.js script tag to your HTML head or install the GA4 npm integration. The script runs in the user's browser and works in both the Bolt WebContainer preview and production. Page view tracking is automatic once installed. Custom events require a single FullStory.gtag() function call.

Google Analytics 4 in Bolt.new: Free Traffic and Conversion Analytics for Every App

Google Analytics 4 is the most widely used web analytics platform in the world, and it is completely free for standard use with no session or pageview limits. For any Bolt.new app you ship to real users, GA4 should be one of the first integrations you add — it tells you how users find your app (organic search, social, direct), what pages they visit, how long they stay, where they drop off, and whether they complete your key goals (signups, purchases, feature activations).

The integration is simpler than most analytics tools. GA4's core tracking mechanism is a client-side JavaScript snippet (gtag.js) that loads in the user's browser and automatically tracks page views and scroll depth. Because this script runs in the browser — not in Bolt's WebContainer server runtime — it works identically in the Bolt preview and in production. You do not need to deploy your app to start collecting analytics data. A Bolt app with the GA4 tag installed starts sending data to Google Analytics the moment someone visits it, whether they arrived via the preview URL or your production domain.

GA4 uses an event-based data model where every user interaction is an event. Google automatically collects a standard set of events (page_view, scroll, click, session_start) without any configuration. You can extend this with custom events for business-specific actions: signup_completed, checkout_started, subscription_upgraded. GA4's free tier includes unlimited data collection, 14 months of data retention for standard properties (2 months for default user and event data), and BigQuery export on a 360 property for enterprise usage.

Integration method

Bolt Chat + API Route

Google Analytics 4 works through a client-side JavaScript tag (gtag.js) that fires directly from the user's browser to Google's servers — no server-side code required for standard tracking. This means the GA4 tag works in Bolt's WebContainer preview and after deployment. For programmatic reporting and building custom dashboards, the GA4 Data API is called through a server-side Next.js API route to protect your Google Cloud credentials.

Prerequisites

  • A Google account and a Google Analytics 4 property created at analytics.google.com (free)
  • Your GA4 Measurement ID (format: G-XXXXXXXXXX) from Admin → Data Streams → Web Stream Details
  • A Bolt.new project — Vite (React) or Next.js both work for the client-side tag
  • For the GA4 Data API dashboard: a Next.js Bolt project, a Google Cloud project with Analytics Data API enabled, and a service account with Viewer access to your GA4 property

Step-by-step guide

1

Create a GA4 Property and Get Your Measurement ID

Before adding the tag to your Bolt app, you need a Google Analytics 4 property. If you already have GA4 set up, skip to getting your Measurement ID. If starting fresh: go to analytics.google.com, click Admin (gear icon bottom-left), click 'Create Property', enter your app name, select your timezone and currency, choose your business size and objectives, and click 'Create'. After creating the property, you need to create a Web data stream. In the Property column, click 'Data Streams', then 'Add stream', then 'Web'. Enter your app's URL (use your Bolt Cloud or Netlify domain — or put a placeholder if you haven't deployed yet) and a stream name. Click 'Create stream'. You will see your Measurement ID at the top of the stream details page — it starts with 'G-' followed by letters and numbers (example: G-A1B2C3D4E5). Copy this ID. This is the only credential you need for client-side tracking. It is safe to expose in client-side code because it only identifies your analytics property — it cannot be used to write fake data at any significant scale, and it is visible in your website's HTML source code by design. Note: GA4 data takes 24-48 hours to fully populate standard reports. The 'Realtime' report under Reports → Realtime shows immediate data from the last 30 minutes — use this to verify your tag is working right after installation.

Bolt.new Prompt

Set up Google Analytics 4 in my Bolt.new project. Add the GA4 measurement script to my app. For a Vite project, add the gtag.js script to index.html. For a Next.js project, add it to the root layout's head. Use VITE_GA_MEASUREMENT_ID (Vite) or NEXT_PUBLIC_GA_MEASUREMENT_ID (Next.js) environment variable for the measurement ID. Also create a lib/analytics.ts helper file that exports a trackEvent function wrapping window.gtag. Add a .env entry with a placeholder measurement ID.

Paste this in Bolt.new chat

index.html
1<!-- index.html (Vite) add to <head> -->
2<!-- Replace G-XXXXXXXXXX with your Measurement ID -->
3<script async src="https://www.googletagmanager.com/gtag/js?id=%VITE_GA_MEASUREMENT_ID%"></script>
4<script>
5 window.dataLayer = window.dataLayer || [];
6 function gtag(){dataLayer.push(arguments);}
7 gtag('js', new Date());
8 gtag('config', '%VITE_GA_MEASUREMENT_ID%');
9</script>
10
11// For Vite: inject env variable into HTML via vite.config.ts
12// vite.config.ts
13import { defineConfig } from 'vite';
14import react from '@vitejs/plugin-react';
15
16export default defineConfig({
17 plugins: [react()],
18 // Vite automatically replaces %VITE_*% in index.html
19});

Pro tip: The GA4 Measurement ID (G-XXXXXXXXXX) is safe to use as a VITE_ variable or NEXT_PUBLIC_ variable — it is meant to be public. Never confuse this with a GA4 API secret key or service account credentials, which must remain server-side.

Expected result: The gtag.js script loads in your app's browser console without errors. Open the GA4 Realtime report and visit your Bolt preview URL — you should see yourself appear as an active user within 1-2 minutes.

2

Add GA4 to a Next.js Bolt App with Proper Script Loading

For Next.js Bolt projects, the integration approach differs slightly from plain HTML. Next.js manages the document head and provides the next/script component for optimized third-party script loading. Using next/script with strategy='afterInteractive' (or 'lazyOnload') ensures the GA4 script loads after the page becomes interactive, not blocking the first render. In Next.js App Router (which Bolt uses by default), add the GA4 scripts to your root layout.tsx file. The root layout wraps all pages, so GA4 will initialize on every page load automatically. Use the Script component from next/script instead of plain script tags for better performance. For page view tracking in a Next.js single-page app, you need to handle client-side navigation manually. The GA4 tag automatically tracks the first page load, but when users navigate between pages in a React app without a full browser reload, GA4 doesn't receive a new page_view event. You need to listen to route changes and fire a page_view event manually. In Next.js App Router, use the usePathname hook inside a client component to detect navigation and trigger GA4 page view events on each route change. Create a separate GoogleAnalytics client component that handles both initialization and navigation tracking. Add this component to your root layout. This keeps the analytics logic isolated from your page components and makes it easy to disable or replace later.

Bolt.new Prompt

Add Google Analytics 4 to my Next.js Bolt app with proper App Router support. Create a components/GoogleAnalytics.tsx client component that uses next/script to load gtag.js and uses the usePathname hook to fire page_view events on each route change. Read the measurement ID from process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID. Add GoogleAnalytics to my root app/layout.tsx inside the body tag. Create a lib/gtag.ts helper that exports pageview and event functions with proper TypeScript types.

Paste this in Bolt.new chat

lib/gtag.ts
1// lib/gtag.ts
2export const GA_MEASUREMENT_ID = process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID || '';
3
4export function pageview(url: string) {
5 if (!GA_MEASUREMENT_ID || typeof window === 'undefined') return;
6 window.gtag('config', GA_MEASUREMENT_ID, { page_path: url });
7}
8
9export function event(
10 action: string,
11 params: Record<string, string | number | boolean> = {}
12) {
13 if (!GA_MEASUREMENT_ID || typeof window === 'undefined') return;
14 window.gtag('event', action, params);
15}
16
17// Add to global TypeScript types
18declare global {
19 interface Window {
20 gtag: (
21 command: 'config' | 'event' | 'js' | 'set',
22 targetId: string | Date,
23 params?: Record<string, unknown>
24 ) => void;
25 dataLayer: unknown[];
26 }
27}
28
29// components/GoogleAnalytics.tsx
30'use client';
31
32import Script from 'next/script';
33import { usePathname } from 'next/navigation';
34import { useEffect } from 'react';
35import { GA_MEASUREMENT_ID, pageview } from '@/lib/gtag';
36
37export function GoogleAnalytics() {
38 const pathname = usePathname();
39
40 useEffect(() => {
41 if (pathname) pageview(pathname);
42 }, [pathname]);
43
44 if (!GA_MEASUREMENT_ID) return null;
45
46 return (
47 <>
48 <Script
49 strategy="afterInteractive"
50 src={`https://www.googletagmanager.com/gtag/js?id=${GA_MEASUREMENT_ID}`}
51 />
52 <Script
53 id="google-analytics"
54 strategy="afterInteractive"
55 dangerouslySetInnerHTML={{
56 __html: `
57 window.dataLayer = window.dataLayer || [];
58 function gtag(){dataLayer.push(arguments);}
59 gtag('js', new Date());
60 gtag('config', '${GA_MEASUREMENT_ID}', { page_path: window.location.pathname });
61 `,
62 }}
63 />
64 </>
65 );
66}

Pro tip: Use strategy='afterInteractive' for Google Analytics — it loads after the page is interactive, reducing impact on First Input Delay (FID) and Core Web Vitals. Never use strategy='beforeInteractive' for third-party analytics scripts.

Expected result: The GA4 script loads after page interaction. Navigating between pages in your Next.js app fires page_view events for each route. Check GA4 Realtime → Pages to see each page view appear as you navigate.

3

Track Custom Events for Business Metrics

GA4's automatically collected events (page_view, scroll, click, first_visit, session_start) give you basic traffic analytics. To measure whether your app achieves its business goals, you need custom events that represent meaningful user actions. GA4's free custom event tracking has no limits — you can define up to 500 distinct event names per property. GA4's event model uses a flat structure: each event has a name and optional parameters. Event names should be snake_case strings describing the action (sign_up, purchase, level_up, feature_enable). Parameters add context to events — for example, a purchase event includes currency, value, and items. GA4 has a set of recommended event names for common actions (sign_up, login, search, select_item, begin_checkout, purchase) that unlock pre-built reports in the GA4 dashboard. Use these recommended names when they match your action. For conversion tracking, mark your most important events as 'Key Events' (formerly called Conversions) in GA4 Admin → Events → Key Events. This tells GA4 to track these events in conversion reports, goal completions, and the Conversions summary. Typical key events for a SaaS app: sign_up, purchase, trial_start. Call window.gtag('event', eventName, params) directly, or use the event() helper from lib/gtag.ts to add TypeScript safety. Always call events from event handlers or useEffect hooks — never from the render function directly, as this would fire on every render.

Bolt.new Prompt

Add custom GA4 event tracking to my app's key conversion moments using the gtag event function from lib/gtag.ts. Track: (1) sign_up with { method: 'email' | 'google' } when a user completes registration, (2) begin_checkout with { currency: 'USD', value: price } when they click a pricing plan, (3) purchase with { transaction_id: id, value: amount, currency: 'USD', items: [{ item_name: planName }] } when payment succeeds, (4) search with { search_term: query } when they use any search feature. Add these calls to the existing handlers in my components.

Paste this in Bolt.new chat

lib/gtag.ts
1// Usage examples throughout your app:
2import { event } from '@/lib/gtag';
3
4// After successful signup:
5event('sign_up', { method: 'email' });
6
7// When user clicks a pricing plan:
8event('begin_checkout', {
9 currency: 'USD',
10 value: 29.00,
11 coupon: '',
12});
13
14// After successful payment:
15event('purchase', {
16 transaction_id: invoiceId,
17 value: 29.00,
18 currency: 'USD',
19 tax: 0,
20 items: JSON.stringify([{ item_name: 'Pro Plan', item_id: 'plan_pro', price: 29.00 }]),
21});
22
23// When user searches:
24event('search', { search_term: userQuery });
25
26// When user enables a feature:
27event('select_content', {
28 content_type: 'feature',
29 item_id: featureName,
30});

Pro tip: Go to GA4 Admin → Events → Key Events after creating your custom events to mark sign_up and purchase as key events. This enables them in GA4's Acquisition and Monetization reports automatically.

Expected result: Custom events appear in GA4 Reports → Engagement → Events within a few hours. The Realtime report shows events as they fire during testing. Marked key events appear in Conversions reports.

4

Deploy and Verify GA4 in Production

GA4 works in the Bolt WebContainer preview for basic testing, but there are important differences between the preview environment and production that affect analytics accuracy. The Bolt preview URL (a browser-based WebContainer URL) may be sampled or filtered differently by GA4. More importantly, you want GA4 capturing data from your real deployed domain — the URL your actual users will visit. Deploy your Bolt app to Netlify or Bolt Cloud to get a production URL. After deploying, add your production domain to the GA4 property's Web data stream: go to GA4 Admin → Data Streams → click your web stream → scroll to 'Enhance measurement' → verify the stream URL matches your deployed domain. Set environment variables on your hosting platform before deploying. In Netlify: Site Settings → Environment Variables → add NEXT_PUBLIC_GA_MEASUREMENT_ID (for Next.js) or VITE_GA_MEASUREMENT_ID (for Vite) with your G- measurement ID. Trigger a redeploy after adding variables. Vite bakes environment variables into the bundle at build time — the variable must be set before the build runs. Verify the integration using the GA4 DebugView. In GA4 Reports → Configure → DebugView, enable debug mode by adding ?debug_mode=1 to your app URL or by installing the Google Analytics Debugger Chrome extension. DebugView shows events in real-time with full parameter details, making it easy to confirm every event fires correctly before relying on the standard 24-hour reporting delay. Note: Bolt's WebContainer has no mechanism to receive incoming requests from external services, so GA4 Measurement Protocol (server-to-server event sending) cannot be used in the WebContainer preview. It works fine after deploying to a standard Node.js environment where you can send server-side events via API routes.

Bolt.new Prompt

Prepare my Bolt app for production deployment with GA4. Create a netlify.toml with the correct build settings for my framework (Vite or Next.js). Add a check in my GA4 initialization code that logs a warning if the Measurement ID environment variable is missing. Create a simple /debug route or console utility that fires a test_event to GA4 when clicked, so I can verify the integration works in production without waiting for real user events.

Paste this in Bolt.new chat

netlify.toml
1// netlify.toml (for Next.js Bolt app)
2[build]
3 command = "npm run build"
4 publish = ".next"
5
6[build.environment]
7 NODE_VERSION = "20"
8
9[[plugins]]
10 package = "@netlify/plugin-nextjs"
11
12# Set these in Netlify Dashboard Environment Variables:
13# NEXT_PUBLIC_GA_MEASUREMENT_ID = G-XXXXXXXXXX
14
15// netlify.toml (for Vite Bolt app)
16[build]
17 command = "npm run build"
18 publish = "dist"
19
20[build.environment]
21 NODE_VERSION = "20"
22
23[[redirects]]
24 from = "/*"
25 to = "/index.html"
26 status = 200

Pro tip: Use GA4 DebugView (Reports → Configure → DebugView) to verify events during testing. Enable debug mode by visiting your deployed app at yourapp.netlify.app?debug_mode=1 — GA4 shows every event with full parameters in real-time, bypassing the standard 24-hour processing delay.

Expected result: Your deployed app reports page views to GA4 on every navigation. GA4 Realtime shows users from your deployed domain. The DebugView shows custom events with correct parameters. Google Analytics begins populating standard reports within 24 hours.

5

Build a Custom Analytics Dashboard with the GA4 Data API

GA4's Data API (part of Google Analytics Data API v1) lets you run analytics queries programmatically and display the results in your own UI. This is useful for building internal analytics dashboards that show aggregated data without requiring team members to log into GA4, or for creating public 'transparency pages' showing your app's growth metrics. The GA4 Data API uses Google Cloud service account authentication. You need a Google Cloud project with the Analytics Data API enabled, and a service account with at least Viewer access to your GA4 property. This authentication involves a JSON key file that must never reach the browser — call this API exclusively from a Next.js server-side API route. The API accepts a request body specifying dimensions (what to group by: pagePath, deviceCategory, country, date) and metrics (what to measure: sessions, totalUsers, screenPageViews, conversions). The API returns rows of data matching your query. This data is suitable for rendering charts, tables, or summary cards in your admin dashboard. An important architectural note: the GA4 Data API works fine after deploying to Netlify or Bolt Cloud because the API route runs server-side in a real Node.js environment. During Bolt WebContainer development, API routes that use the Google Cloud client SDK may encounter WebContainer's lack of TCP support — the googleapis npm package uses gRPC under the hood for some calls. If you encounter connection issues in the preview, use the HTTP-based REST approach (direct fetch to https://analyticsdata.googleapis.com) instead of the googleapis npm package, or test via a quick deploy to Netlify.

Bolt.new Prompt

Create a Next.js API route at app/api/analytics/overview/route.ts that fetches GA4 analytics data. Use the googleapis npm package with a service account. Read GOOGLE_SERVICE_ACCOUNT_JSON (the entire service account JSON as a string) and GA4_PROPERTY_ID from server-side environment variables. Query the last 30 days of data: total sessions, total users, bounce rate, and top 5 pages by sessions. Create an AnalyticsDashboard React component that fetches from this endpoint and displays the data in a clean table.

Paste this in Bolt.new chat

app/api/analytics/overview/route.ts
1// app/api/analytics/overview/route.ts
2import { NextResponse } from 'next/server';
3import { BetaAnalyticsDataClient } from '@google-analytics/data';
4
5export async function GET() {
6 try {
7 const credentials = JSON.parse(
8 process.env.GOOGLE_SERVICE_ACCOUNT_JSON || '{}'
9 );
10 const propertyId = process.env.GA4_PROPERTY_ID;
11
12 if (!propertyId || !credentials.client_email) {
13 return NextResponse.json(
14 { error: 'GA4 credentials not configured' },
15 { status: 500 }
16 );
17 }
18
19 const analyticsClient = new BetaAnalyticsDataClient({ credentials });
20
21 const [response] = await analyticsClient.runReport({
22 property: `properties/${propertyId}`,
23 dateRanges: [{ startDate: '30daysAgo', endDate: 'today' }],
24 dimensions: [{ name: 'pagePath' }],
25 metrics: [
26 { name: 'sessions' },
27 { name: 'totalUsers' },
28 { name: 'screenPageViews' },
29 ],
30 orderBys: [{ metric: { metricName: 'sessions' }, desc: true }],
31 limit: 10,
32 });
33
34 const rows = response.rows?.map((row) => ({
35 page: row.dimensionValues?.[0]?.value,
36 sessions: row.metricValues?.[0]?.value,
37 users: row.metricValues?.[1]?.value,
38 views: row.metricValues?.[2]?.value,
39 }));
40
41 return NextResponse.json({ rows });
42 } catch (error: unknown) {
43 const e = error as { message: string };
44 return NextResponse.json({ error: e.message }, { status: 500 });
45 }
46}

Pro tip: Store GOOGLE_SERVICE_ACCOUNT_JSON as a single-line JSON string (with escaped quotes) in your .env file. Run JSON.stringify(require('./service-account.json')) in Node.js locally to get the correctly formatted single-line string. Never commit the actual service account JSON file to your repository.

Expected result: After deploying to Netlify with GOOGLE_SERVICE_ACCOUNT_JSON and GA4_PROPERTY_ID set, GET /api/analytics/overview returns the last 30 days of top pages data. The analytics dashboard component displays session counts and user numbers from your real GA4 property.

Common use cases

Track Page Views and Traffic Sources for a New Bolt App

You just launched a Bolt app and want to understand how many people are visiting, where they come from (Google search, direct link, social media), and which pages they view most. Add the GA4 tag and start collecting traffic data immediately. GA4's Acquisition report shows traffic sources; the Pages report shows most-viewed content.

Bolt.new Prompt

Add Google Analytics 4 to my Bolt.new Vite React app. Create a lib/analytics.ts file that exports a pageview function and an event function using window.gtag. Add the GA4 script tags to my index.html head section using the Measurement ID from VITE_GA_MEASUREMENT_ID environment variable. The gtag.js script should load from https://www.googletagmanager.com/gtag/js?id= followed by the measurement ID. Add a .env entry with VITE_GA_MEASUREMENT_ID=G-XXXXXXXXXX as a placeholder.

Copy this prompt to try it in Bolt.new

Track Conversion Events for a SaaS App

You have a Bolt SaaS app with a signup flow, a pricing page, and a checkout step. Track custom events at each funnel stage to measure conversion rates: how many visitors sign up, how many reach the pricing page, how many start checkout. Use GA4's Funnel Exploration report to visualize drop-off and identify where to improve the UX.

Bolt.new Prompt

Add custom GA4 event tracking to my React app's key conversion moments. I already have GA4 initialized with gtag. When a user completes signup, call gtag('event', 'sign_up', { method: authMethod }). When they view the pricing page, call gtag('event', 'view_item_list', { item_list_name: 'Pricing Plans' }). When they click a plan to start checkout, call gtag('event', 'begin_checkout', { currency: 'USD', value: price, items: [{ item_name: planName }] }). Add these calls in the appropriate React components and event handlers.

Copy this prompt to try it in Bolt.new

Build a Custom Analytics Dashboard Using the GA4 Data API

Build an admin dashboard page inside your Bolt app that pulls live analytics data from GA4: total sessions this week, top pages by views, and new user count. This requires the GA4 Data API and a Google Cloud service account, called through a Next.js API route to keep credentials server-side.

Bolt.new Prompt

Create a Next.js API route at app/api/analytics/report/route.ts that fetches the last 7 days of data from the GA4 Data API. Use GOOGLE_APPLICATION_CREDENTIALS_JSON (a service account JSON as a string) and GA4_PROPERTY_ID environment variables. Return total sessions, total users, and top 5 pages by sessions. Create an AdminAnalytics React component that calls this endpoint and displays the data in a simple table.

Copy this prompt to try it in Bolt.new

Troubleshooting

GA4 Realtime shows no active users even after adding the script tag

Cause: The Measurement ID may be incorrect or missing from the script tag, the gtag.js script may have a loading error, or an ad blocker in the browser is blocking the Google Analytics request.

Solution: Open browser DevTools → Console and check for script errors. Check Network tab for requests to www.googletagmanager.com — if blocked (red), an extension is interfering. Temporarily disable browser extensions and reload. Verify the Measurement ID (G-XXXXXXXXXX) is exactly correct in your .env file. In GA4 Admin → Data Streams, confirm the stream is set to the correct website URL.

Vite app: window.gtag is not a function / TypeError at runtime

Cause: The gtag script tag uses %VITE_GA_MEASUREMENT_ID% template syntax in index.html, but the variable is not being replaced because the app is running outside of Vite's build context, or the VITE_ prefix is missing from the environment variable name.

Solution: Ensure the environment variable name starts with VITE_ exactly: VITE_GA_MEASUREMENT_ID. Variables without the VITE_ prefix are not exposed to client-side Vite code. Check index.html for the correct %VITE_GA_MEASUREMENT_ID% placeholder syntax (percent signs, not ${}). Restart the Bolt dev server after editing .env.

typescript
1# .env correct:
2VITE_GA_MEASUREMENT_ID=G-XXXXXXXXXX
3
4# index.html correct syntax for Vite HTML template:
5# <script async src="https://www.googletagmanager.com/gtag/js?id=%VITE_GA_MEASUREMENT_ID%"></script>

GA4 Data API returns 403 Forbidden from the API route after deployment

Cause: The service account does not have Viewer access to the GA4 property, or the Analytics Data API is not enabled in the Google Cloud project associated with the service account.

Solution: In GA4 Admin → Property Access Management, click + Add Users and add your service account's email address (from the service account JSON, the client_email field) with the Viewer role. In Google Cloud Console → APIs & Services → Enabled APIs, ensure 'Google Analytics Data API' is enabled for your project.

Page views in Next.js app only track the first page, not subsequent navigations

Cause: GA4's automatic page_view event fires on initial page load, but Next.js App Router uses client-side navigation (no full browser reload between pages), so GA4 doesn't detect subsequent page changes.

Solution: Add the usePathname-based navigation listener to your GoogleAnalytics component as shown in Step 2. This detects route changes and fires a pageview event manually. Verify the component is mounted at the root layout level so it persists across all pages.

typescript
1// In your GoogleAnalytics component:
2const pathname = usePathname();
3useEffect(() => {
4 if (pathname) {
5 window.gtag('config', GA_MEASUREMENT_ID, { page_path: pathname });
6 }
7}, [pathname]);

Best practices

  • Use NEXT_PUBLIC_GA_MEASUREMENT_ID or VITE_GA_MEASUREMENT_ID for your Measurement ID — it is safe to expose client-side since it is visible in your HTML source by design
  • Load the gtag.js script with strategy='afterInteractive' in Next.js to avoid blocking First Contentful Paint and Core Web Vitals scores
  • Track route changes manually in Next.js App Router using usePathname — GA4 only auto-tracks the initial page load in SPAs
  • Mark your key business events (sign_up, purchase, trial_start) as Key Events in GA4 Admin → Events to unlock conversion reports
  • Keep service account credentials (GOOGLE_SERVICE_ACCOUNT_JSON) server-side only — never use NEXT_PUBLIC_ prefix on sensitive Google Cloud credentials
  • Use GA4's DebugView (visit your app with ?debug_mode=1) to verify events fire correctly during testing before waiting for 24-hour standard reporting
  • Use GA4's recommended event names (sign_up, purchase, search, begin_checkout) rather than custom names when they fit — they unlock pre-built reports automatically

Alternatives

Frequently asked questions

Does Google Analytics 4 work in Bolt.new's WebContainer preview?

Yes. GA4's gtag.js script loads from Google's CDN and runs entirely in the user's browser — it does not depend on Bolt's WebContainer server runtime. The script fires analytics events over HTTPS directly to Google's servers. You can verify initialization works in the Bolt preview using the browser console and GA4 Realtime report.

Is GA4 free? Are there any limits?

Google Analytics 4 standard is completely free with no pageview or session limits. The free tier retains event data for 2 months by default and up to 14 months if configured in Admin → Data Settings → Data Retention. GA4 360 (enterprise tier starting at around $150,000/year) adds BigQuery exports, higher sampling thresholds, and SLAs — not relevant for most Bolt apps.

Does GA4 track events from the Bolt.new preview URL?

Yes, GA4 will receive events from the preview URL, but Bolt's WebContainer URLs are dynamic and change between sessions. For accurate production analytics, deploy to Bolt Cloud or Netlify and verify your production domain matches the Web data stream URL in GA4 Admin. Use GA4's DebugView to test events during development without polluting production data.

Can I use Google Tag Manager instead of adding gtag.js directly?

Yes. Google Tag Manager (GTM) is an alternative container tag that manages GA4 (and other scripts) through the GTM dashboard without code changes. Add the GTM container snippet to your Bolt app once, then manage all GA4 configuration in the GTM interface. GTM is recommended if you need multiple analytics and marketing tags — it centralizes tag management. For a simple GA4-only setup, direct gtag.js is simpler.

How long does it take for GA4 data to appear in reports?

The GA4 Realtime report (Reports → Realtime) shows data within a few seconds of events firing, making it useful for testing. Standard reports (Acquisition, Engagement, Retention) process data with a 24-48 hour delay. BigQuery exports (GA4 360 only) have near-real-time streaming. For testing your integration, always use Realtime or DebugView — don't wait 24 hours to confirm your events are working.

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.