Where to Place Google Analytics Code in React JS?
Adding Google Analytics to a React application is one of the first steps to understanding how users interact with your site, but it's not as straightforward as with a traditional static website. Because React handles navigation without full page reloads, a simple copy-and-paste of the tracking script won't capture all the data you need. This guide will walk you through the best methods for correctly installing Google Analytics in your React JS project, from the most basic implementation to the recommended, scalable approaches.
Why Google Analytics is Different with React
With traditional websites, every time a user clicks a link to a new page, the browser loads a brand-new HTML document. The Google Analytics (GA) script runs again on this new page load, automatically logging a "pageview."
React, however, powers what’s known as a Single-Page Application (SPA). The initial page load brings in the entire application. When you navigate between pages (or "routes"), React just swaps out components on the fly without making a new request to the server for a full HTML page.
This creates a challenge: the GA script in your main HTML file only runs once when the app first loads. It has no idea that the user is navigating through different views like /about, /services, or /contact. To Google Analytics, it looks like the user arrived on your homepage and never left, which means you're missing out on most of your user behavior data.
To solve this, we need to manually tell Google Analytics whenever a "pageview" happens within our React app.
Method 1: The Simple (But Flawed) Way - index.html
The first and most basic method is to add the Google Analytics tracking script directly into your main HTML file. In a standard Create React App project, this file is located at public/index.html.
How to Do It
- Log in to your Google Analytics account and navigate to the Admin section.
- Go to
Data Streams, select your stream, and find the "View tag instructions" section. - You'll see a global site tag (gtag.js) script. Copy this entire script.
- Open
public/index.htmlin your React project and paste the script inside the<head>tag.
It will look something like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>My React App</title>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-YOUR_MEASUREMENT_ID"></script>
<script>
window.dataLayer = window.dataLayer || [],
function gtag(){dataLayer.push(arguments),}
gtag('js', new Date()),
gtag('config', 'G-YOUR_MEASUREMENT_ID'),
</script>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>Why This Is Flawed
As mentioned earlier, this method only tracks the very first page load. When a user navigates from your homepage to your pricing page, React simply changes the URL in the browser and updates the view. Since there's no new HTML document being loaded from the server, the GA script is not re-executed. All internal navigation goes completely untracked. This approach is only suitable if your app truly has only one page with no navigation.
Method 2: A Manual Fix Using React Router and Hooks
To accurately track pageviews, we need to detect when the route changes and manually send a pageview event to Google. If you’re using React Router for navigation, you can achieve this with the useLocation and useEffect hooks.
This method builds on Method 1. You still need the GA script in your index.html file so that the global gtag function is available throughout your application.
How to Do It
In your main App.js component (or wherever your router is defined), you can create logic to listen for location changes.
- Make sure you have
react-router-dominstalled:npm install react-router-dom - Import
useLocationanduseEffectinto your component. - Use the
useLocationhook to get the current location object, which contains details like thepathname. - Create a
useEffecthook that has thelocationobject in its dependency array. This ensures the effect will run every time the URL changes. - Inside the effect, call the
gtagfunction to send apage_viewevent.
Here’s an example of how you might structure your App.js file:
import React, { useEffect } from 'react',
import { BrowserRouter as Router, Routes, Route, useLocation } from 'react-router-dom',
import Home from './components/Home',
import About from './components/About',
import Contact from './components/Contact',
// This helper component will track route changes
function AnalyticsTracker() {
const location = useLocation(),
useEffect(() => {
if (window.gtag) {
window.gtag('config', 'G-YOUR_MEASUREMENT_ID', {
page_path: location.pathname + location.search,
}),
}
}, [location]),
return null, // This component does not render anything
}
function App() {
return (
<Router>
<AnalyticsTracker />
{/* Your navigation and routes here */}
<nav>...</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</Router>
),
}
export default App,This approach works well and gives you full control. However, you're interacting directly with a global window object, which isn't always ideal in a React environment. A more structured and maintainable way is to use a dedicated library.
Method 3: The Recommended Approach via the react-ga4 Library
Using a library dedicated to integrating React with Google Analytics is almost always the best choice. The react-ga4 package is a popular, up-to-date library that simplifies the entire process. It provides a clean React-friendly API for initializing GA and tracking events.
- Easier to Use: Simplifies initialization and event tracking into simple function calls.
- Better Maintenance: If Google changes its Analytics API, the library maintainers will update the package for you.
- Encapsulated Logic: Keeps your analytics code separate and organized, rather than scattered across components.
- No Need to Manually Add GA to HTML: The library handles loading the necessary scripts, keeping your
index.htmlclean.
Step-by-Step Implementation
1. Install the Package
Open your terminal and run:
npm install react-ga4or
yarn add react-ga42. Initialize Google Analytics
The best place to initialize GA is at the top level of your application, for example in index.js or App.js, so it runs once when the app starts.
Remember to use an environment variable for your measurement ID so you are not committing sensitive information to your code repository.
In your App.js:
import React from 'react',
import ReactGA from 'react-ga4',
const MEASUREMENT_ID = process.env.REACT_APP_GA_MEASUREMENT_ID,
// Initialize GA once at app start
ReactGA.initialize(MEASUREMENT_ID),
function App() {
// ... The rest of your app logic
}3. Track Pageviews on Route Change
We'll use the same hook-based approach as before, but calling the library's functions instead of the global gtag.
You can create a reusable component to handle this:
// components/RouteChangeTracker.jsx
import { useEffect, useState } from "react",
import { useLocation } from "react-router-dom",
import ReactGA from "react-ga4",
const RouteChangeTracker = () => {
const location = useLocation(),
const [initialized, setInitialized] = useState(false),
useEffect(() => {
if (!window.location.href.includes("localhost")) {
ReactGA.initialize(process.env.REACT_APP_GA_MEASUREMENT_ID),
setInitialized(true),
}
}, []),
useEffect(() => {
if (initialized) {
ReactGA.send({ hitType: "pageview", page: location.pathname + location.search }),
}
}, [initialized, location]),
return null, // This component does not render anything
},
export default RouteChangeTracker,Now, place this component inside your Router in App.js:
// App.js
import React from 'react',
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom',
import RouteChangeTracker from './components/RouteChangeTracker',
// ... import your other components
function App() {
return (
<Router>
<RouteChangeTracker />
{/* ... Your Routes here ... */}
</Router>
),
}
export default App,4. Tracking Custom Events
Tracking user interactions like button clicks or form submissions is key to understanding behavior. react-ga4 makes this incredibly easy.
For example, to track a "Sign Up" button click:
import ReactGA from 'react-ga4',
const trackSignUpClick = () => {
ReactGA.event({
category: 'User',
action: 'Clicked Sign Up',
label: 'Top Nav Sign Up CTA' // optional
}),
},
function SignUpButton() {
return <button onClick={trackSignUpClick}>Sign Up</button>,
}Best Practices for a Robust Setup
Use Environment Variables for Your ID
Never hard-code your Measurement ID directly into your application. Create a .env file in the root of your project and store your ID there. Create React App will automatically make any variable starting with REACT_APP_ accessible inside your code.
In your .env file:
REACT_APP_GA_MEASUREMENT_ID=G-ABC123XYZThis allows you to easily switch between different GA properties for development, staging, and production environments without changing your code.
Respect User Consent (GDPR/CCPA)
Privacy regulations require you to get user consent before running analytics scripts. You should wrap your GA initialization logic in a condition that checks if the user has consented to tracking. This state can be managed with React's Context API or a state management library.
Debug Your Implementation
The "Google Analytics Debugger" Chrome extension is an invaluable tool. Once enabled, it prints all the GA events being sent from your app into your browser's developer console. You can click around your app and watch as pageview and custom events are fired in real-time, confirming your setup works as expected.
Final Thoughts
While placing the Google Analytics script in index.html feels like the simplest solution, the nature of Single-Page Applications like React requires a more thoughtful approach to track user behavior correctly. By leveraging React Router hooks with a helper library like react-ga4, you can create a robust, accurate, and maintainable analytics setup that captures every pageview and user interaction.
Once you’ve successfully implemented tracking and data is flowing into Google Analytics, the challenge shifts to making sense of it all. Instead of spending hours pulling manual reports and trying to connect the dots, we built Graphed to simplify the entire process. At Graphed, you connect your Google Analytics account in seconds and use simple, natural language prompts like "show me my top traffic sources this month" to instantly generate real-time dashboards and get answers, turning your data into clear insights without the work.
Related Articles
How to Connect Facebook to Google Data Studio: The Complete Guide for 2026
Connecting Facebook Ads to Google Data Studio (now called Looker Studio) has become essential for digital marketers who want to create comprehensive, visually appealing reports that go beyond the basic analytics provided by Facebook's native Ads Manager. If you're struggling with fragmented reporting across multiple platforms or spending too much time manually exporting data, this guide will show you exactly how to streamline your Facebook advertising analytics.
Appsflyer vs Mixpanel: Complete 2026 Comparison Guide
The difference between AppsFlyer and Mixpanel isn't just about features—it's about understanding two fundamentally different approaches to data that can make or break your growth strategy. One tracks how users find you, the other reveals what they do once they arrive. Most companies need insights from both worlds, but knowing where to start can save you months of implementation headaches and thousands in wasted budget.
DashThis vs AgencyAnalytics: The Ultimate Comparison Guide for Marketing Agencies
When it comes to choosing the right marketing reporting platform, agencies often find themselves torn between two industry leaders: DashThis and AgencyAnalytics. Both platforms promise to streamline reporting, save time, and impress clients with stunning visualizations. But which one truly delivers on these promises?