Integrating Google Analytics with Hydrogen 2.0

Topic summary

Goal: Add Google Analytics (GA) to a Shopify Hydrogen 2.0 storefront (Remix-based) and track pageviews across the custom domain, not just checkout.

Proposed implementation:

  • Based on Remix’s GA example, a gtags.client.ts defines window.gtag.
  • In the root loader (defer), GA config is added to data: analytics.gaTrackingId alongside shopId and ShopifySalesChannel.
  • In App, a useEffect with useLocation and a ref sends gtag.pageview on route changes when gaTrackingId is present.

Open questions and issues:

  • Whether storing the GA tracking ID as analytics.gaTrackingId is appropriate vs. reusing shopId (no consensus provided).
  • A user reports an error: “ReferenceError: useLocation is not defined” in root.jsx during server rendering; no fix or cause confirmed in the thread.
  • Another user’s attempt via Shopify “Online Store” GA setup only tracks checkout.mydomain.com, not the Hydrogen storefront, prompting interest in manual integration without disrupting existing analytics. A screenshot of their Shopify GA setup is referenced.

Status: No confirmed solution or guidance yet. The thread remains open with unresolved integration steps and error handling details.

Summarized with AI on December 21. AI used: gpt-5.

Hello fellow developers!

I’ve been attempting to add Google Analytics to my Hydrogen 2.0 project and wanted to get feedback on my approach.

I started off by referencing the Remix example for Google Analytics found here.

Using this as my foundation, I created a file named gtags.client.ts and structured my code similarly. Here’s a brief overview:

declare global {
  interface Window {
    gtag: (
      option: string,
      gaTrackingId: string,
      options: Record<string, unknown>,
    ) => void;
  }
}

Then, I imported the above file in root:

import * as gtag from "~/lib/gtags.client";

In the defer function, I’ve added my tracking ID:

return defer({
    isLoggedIn: Boolean(customerAccessToken),
    layout,
    selectedLocale: context.storefront.i18n,
    cart: cartId ? getCart(context, cartId) : undefined,
    analytics: {
      shopifySalesChannel: ShopifySalesChannel.hydrogen,
      shopId: layout.shop.id,
      gaTrackingId: 'NUMBERS',
    },
    seo,
  });
}

Lastly, I’ve added the following logic inside my export default function App():

const location = useLocation();
const lastLocationKey = useRef<string>('');

useEffect(() => {
  if (lastLocationKey.current === location.key) return;
  lastLocationKey.current = location.key;

  if (data.analytics.gaTrackingId) {
    gtag.pageview(location.pathname, data.analytics.gaTrackingId);
  }
}, [location, data.analytics.gaTrackingId]);

Have I approached this correctly? Should I have perhaps added the tracking ID to shopId instead of creating gaTrackingId? I would greatly appreciate any feedback or suggestions!

Thank you in advance!

1 Like

I’m trying to implement this, but it’s giving me an error

ReferenceError: useLocation is not defined
at Component (C:\Repos\remix-hydrogen-store\app\root.jsx:77:20)
at renderWithHooks (C:\Repos\remix-hydrogen-store\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5658:16)
at renderIndeterminateComponent (C:\Repos\remix-hydrogen-store\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5731:15)
at renderElement (C:\Repos\remix-hydrogen-store\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5946:7)
at renderNodeDestructiveImpl (C:\Repos\remix-hydrogen-store\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6104:11)
at renderNodeDestructive (C:\Repos\remix-hydrogen-store\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6076:14)
at renderIndeterminateComponent (C:\Repos\remix-hydrogen-store\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5785:7)
at renderElement (C:\Repos\remix-hydrogen-store\node_modules\react-dom\cjs\react-dom-server.browser.development.js:5946:7)
at renderNodeDestructiveImpl (C:\Repos\remix-hydrogen-store\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6104:11)
at renderNodeDestructive (C:\Repos\remix-hydrogen-store\node_modules\react-dom\cjs\react-dom-server.browser.development.js:6076:14)

Hey, did you get it working?

I don’t need a detailed solution just curious if you were on the right track here. I’m trying to integrate Google Analytics with my Hydrogen shop as well.

At first I just hooked up my Google Analytics using tutorials for the “Online Shop” like so:

Interestingly this worked BUT only for the checkout related areas of my site. So my Google Analytics is receiving data centered around my checkout.mydomain.com url. I didn’t expect this approach to work but tried it anyway.

I’m about to start researching how to integrate this manually, but I really don’t want to mess up my analytics for obvious reasons.

Any guidance from anyone who stumbles across this is SUPER APPRECIATED!!!

Thanks so much!

-Kevin