Here's what I did to integrate Google Analytics into Astro.
<GoogleAnalytics measurementId={'G-XXXXXXXXXX'} />
I added the @astrojs/partytown integration to integrate Partytown. The config needed to be updated to forward 'dataLayer.push'
calls (Google Analytics).
npx astro add partytown
import partytown from '@astrojs/partytown'
export default defineConfig({ · · · integrations: [ partytown({ config: { forward: ['dataLayer.push'] } }), ]})
I updated the layout’s <head>
to add the Google Analytics script as early in the <head>
as possible (in my case, after the meta charset tag).
---import GoogleAnalytics from './GoogleAnalytics.astro'---<html lang='en'> <head> <meta charset='utf-8' /> <GoogleAnalytics measurementId={'G-XXXXXXXXXX'} /> <title>My page</title> · ·
This is a reusable component that takes the Google Analytics measurement ID as a prop.
---type Props = { measurementId: string }const props = Astro.props as Propsconst measurementId = props.measurementId---<script type='text/partytown' src={`https://www.googletagmanager.com/gtag/js?id=${measurementId}`}></script><script13 collapsed lines
type='text/partytown' data-ga-measurement-id={measurementId} id='ga-init'> const measurementId = document .getElementById('ga-init') .getAttribute('data-ga-measurement-id') window.dataLayer = window.dataLayer || [] function gtag() { dataLayer.push(arguments) // eslint-disable-line } gtag('js', new Date()) gtag('config', measurementId)</script>
Partytown isn’t really needed for Google Analytics integration in Astro, but I figured it’s a good idea for a few reasons:
Prevent blocking of page rendering. Third-party scripts will be executed on a separate web worker thread, preventing any scripts from locking up.
Protect from negative impacts of third-party scripts. This includes expensive DOM selectors, CPU-intensive scripts, or blocking network requests, and other negative impacts.
Partytown doesn’t work well with Astro View Transitions.
Doesn’t track page views. (Workarounds are available.) Google Analytics tracking fires a page view event when the page loads. In a SPA (single page app) environment, there needs to be extra tracking code to fire the event manually after a new page is loaded in place.
Breaks in Firefox. No workaround as of Dec 2023. There’s an outstanding bug in Astro 4.0.4 where Partytown breaks View Transitions fallback which is needed for browsers that don’t support view transitions (eg, Firefox).
I am a web developer helping make the world a better place through JavaScript, Ruby, and UI design. I write articles like these often. If you'd like to stay in touch, subscribe to my list.