Shopify Hydrogen
Add OnyxMetric analytics to your Shopify Hydrogen storefront
Hydrogen renders the HTML document from app/root.tsx. Put the tag in the <head> of that file's Layout component, and add the tracker's host to the Content Security Policy built in app/entry.server.tsx.
Copy your tracking snippet
In OnyxMetric, open your site's Site Settings and copy the tracking script. It looks like this:
<script src="https://app.onyxmetric.com/api/script.js?siteId=YOUR_SITE_ID" async></script>YOUR_SITE_ID is the numeric ID of your site.
Add the snippet to Shopify Hydrogen
Hydrogen ships with a nonce-based CSP, so a plain <script> tag without the nonce is blocked. Use Hydrogen's Script component, which adds the nonce for you.
- Open
app/root.tsxand add the tag inside<head>of theLayoutcomponent:
import {Script, useNonce} from '@shopify/hydrogen';
export function Layout({children}: {children?: React.ReactNode}) {
const nonce = useNonce();
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<Meta />
<Links />
<Script src="https://app.onyxmetric.com/api/script.js?siteId=YOUR_SITE_ID" async />
</head>
<body>
{children}
<ScrollRestoration nonce={nonce} />
<Scripts nonce={nonce} />
</body>
</html>
);
}- Open
app/entry.server.tsxand allow the tracker's host in the CSP. Values forconnectSrcmerge with Hydrogen's defaults.scriptSrchas no default to merge with (it falls back todefault-src), so list Shopify's CDN too:
const {nonce, header, NonceProvider} = createContentSecurityPolicy({
shop: {
checkoutDomain: context.env.PUBLIC_CHECKOUT_DOMAIN,
storeDomain: context.env.PUBLIC_STORE_DOMAIN,
},
scriptSrc: ["'self'", "https://cdn.shopify.com", "https://app.onyxmetric.com"],
connectSrc: ["https://app.onyxmetric.com"],
});connect-src lets the tracker post events. script-src is needed because features such as session replay load a second script from the same host at runtime.
Restart the dev server for the CSP change to apply. Navigation between routes is tracked automatically.
Check that it works
Load your live site and click through a few pages. Pageviews show up in the OnyxMetric dashboard within seconds.
If nothing arrives:
- View the page source and search for
script.js?siteId=to confirm the tag is present. - In the browser's Network tab, check that
script.jsreturns200and that requests go to/api/track. - Turn off ad blockers, or proxy the script through your own domain.
- Read script troubleshooting for other causes.
Track custom events
Hydrogen's Analytics.Provider already publishes storefront events (product_viewed, product_added_to_cart, cart_updated, and others). Subscribe to them once in a small component instead of instrumenting each route.
import {useEffect} from 'react';
import {useAnalytics} from '@shopify/hydrogen';
export function OnyxAnalytics() {
const {subscribe, register} = useAnalytics();
const {ready} = register('OnyxMetric');
useEffect(() => {
subscribe('product_viewed', (data) => {
const product = data.products[0];
if (!product) return;
window.onyx?.event('view_item', {
item_id: product.sku || product.variantId,
item_name: product.title,
item_variant: product.variantTitle,
price: Number(product.price),
});
});
subscribe('product_added_to_cart', (data) => {
const line = data.currentLine;
if (!line) return;
window.onyx?.event('add_to_cart', {
item_id: line.merchandise.sku || line.merchandise.id,
item_name: line.merchandise.product.title,
price: Number(line.cost.totalAmount.amount),
currency: line.cost.totalAmount.currencyCode,
quantity: line.quantity,
});
});
ready();
}, []);
return null;
}Render <OnyxAnalytics /> inside <Analytics.Provider> in the App component of app/root.tsx. Declare window.onyx with the type from Track events so TypeScript accepts the calls.
Checkout does not run in Hydrogen. Track purchases with the custom web pixel from the Shopify guide, which works for Hydrogen and Online Store checkouts alike.
Troubleshooting
Refused to load the scriptin the console: the CSP change inentry.server.tsxis missing, or the dev server was not restarted.POST /api/trackblocked:connectSrcdoes not includehttps://app.onyxmetric.com.- Early events dropped: on a cold load, a subscription can fire before the script runs. The optional chaining above skips those. Wrap calls in
window.onyx.onReady()if you need every one.
Next steps
- Track custom events such as signups, purchases, and clicks.
- Identify users to tie sessions to accounts.
- Proxy the script through your own domain to get past ad blockers.
- Script attributes let you skip or mask URLs and tag events.