@ptengine/hydrogen-react
v0.1.0
Published
Ptengine analytics for @shopify/hydrogen-react storefronts (Next.js and other React frameworks)
Readme
@ptengine/hydrogen-react
Ptengine analytics for storefronts built with @shopify/hydrogen-react —
Next.js, Remix (non-Hydrogen), or any React framework using Shopify's
ShopifyProvider/CartProvider.
Which package do I need?
| Your stack | Install |
| --- | --- |
| @shopify/hydrogen (Hydrogen framework, React Router, Oxygen) | @ptengine/hydrogen |
| @shopify/hydrogen-react + your own framework (Next.js etc.) | this package |
Each package is self-contained — install exactly one.
Prerequisites
- Install the Ptengine Shopify App on your store (registers order webhooks + checkout web pixel — required for purchase attribution).
- Register your storefront domain in your Ptengine profile settings
(local dev: use
http://127.0.0.1:<port>, notlocalhost).
Setup
npm install @ptengine/hydrogen-reactMount inside your providers (must be within CartProvider):
'use client';
import {ShopifyProvider, CartProvider} from '@shopify/hydrogen-react';
import {PtAnalytics} from '@ptengine/hydrogen-react';
export function Providers({children}) {
return (
<ShopifyProvider
storeDomain="https://your-store.myshopify.com"
storefrontToken="..."
storefrontApiVersion="2025-07"
countryIsoCode="US"
languageIsoCode="EN"
>
<CartProvider>
<PtAnalytics ptengineId="your-ptengine-id" />
{children}
</CartProvider>
</ShopifyProvider>
);
}What it does automatically
- Loads the Ptengine SDK (idempotent;
scriptUrloverrides the default URL). product_added_to_cart/product_removed_from_cart: diffsuseCart()lines between stable (idle) states — fresh visitors' first add is captured; carts restored on page reload do not emit false events.- Writes the five
__pt_*identity keys to cart attributes (value-compared, so a rotatedsessionIdtriggers a rewrite; non-__pt_*attributes are preserved). Orders then carrynote_attributesfor backend attribution. - Pre-checkout guard: clicking a checkout link re-checks identity values and,
if stale, blocks navigation, rewrites via a direct Storefront API
cartAttributesUpdatemutation (keepalive, 1.5s cap), then continues. checkout_startedon checkout link clicks (disable viaemitCheckoutStarted={false}once the Ptengine Web Pixel version that emits it rolls out).
View events (manual — no route bus exists in hydrogen-react)
Data shapes mirror Hydrogen's Analytics.*View exactly:
import {PtProductView, PtCollectionView, PtSearchView, PtCartView} from '@ptengine/hydrogen-react';
// product page
<PtProductView data={{
products: [{id, title, price, sku, type: productType, imageUrl}],
shop: {currency: 'USD'},
url: window.location.href,
}} />
// collection page
<PtCollectionView data={{collection: {id, title}}} />
// search results
<PtSearchView data={{searchTerm, searchResults: {total}}} />
// cart page (reads useCart(); waits for idle, skips empty carts like the pixel)
<PtCartView />Props
| prop | default | description |
| --- | --- | --- |
| ptengineId | required | Ptengine profile ID (the id in your tag URL js.ptengine.com/{id}.js) |
| loadSdk | true | inject https://js.ptengine.com/{id}.js |
| scriptUrl | derived | override SDK URL |
| debug | false | log events; buffer to window.__ptEvents, expose window.__ptCart |
| emitCheckoutStarted | true | see above |
| waitForConsent | — | optional () => boolean; SDK loads only after it returns true (listens to visitorConsentCollected + 1s polling). Wire it to useCustomerPrivacy or your CMP |
CSP (if your app sets one)
import {ptengineCspDirectives} from '@ptengine/hydrogen-react';
// merge scriptSrc/connectSrc/styleSrc/frameSrc additions
// (*.ptengine.com + *.ptengine.jp) into your CSP header config.Next.js apps without a CSP need nothing.
Local file: install (development only)
Webpack must resolve the symlinked package's peer imports from your app:
// next.config.mjs
export default {
transpilePackages: ['@ptengine/hydrogen-react'],
webpack: (config) => {
config.resolve.symlinks = false;
return config;
},
};Registry installs need neither.
Scope & boundaries
- Checkout entry must be an
<a href>link (see the hydrogen package notes — same listener-based guard). - Non-.com regions need
scriptUrl(default isjs.ptengine.com/{id}.js). - If the page already loads a Ptengine tag by other means, pass
loadSdk={false}to avoid double loading.
Known limits
cart_viewedhas no automatic source — mount<PtCartView>on your cart page/aside.- Carts managed outside
CartProviderdon't emit events (use the exportedptTrack/writeCartAttributesDirectprimitives and manual instrumentation). - Quick-pay (
ShopPayButton) attribution is not yet covered (same limitation as the Hydrogen package). - Verified baseline: Next.js 15 App Router. Pages Router should work (components are pure client) but is unverified.
