Install Personizely on Shopify Hydrogen
On a Shopify Hydrogen storefront, you install Personizely with the @personizely/shopify-hydrogen npm package. Its PersonizelyProvider component connects the snippet to Hydrogen's cart and loads it in the browser. Hooks let your product forms and checkout button fire Personizely's add-to-cart and checkout triggers. You also install the Personizely Shopify app on the store, so orders are tracked server-side.
Available on: Shopify Hydrogen v2 with React Router v7 and React 18.
Before you start
You need:
- The Personizely Shopify app installed on the store, so products sync and orders are recorded and attributed. Follow the first section of Install Personizely on Shopify. You don't need the theme app embed, because Hydrogen doesn't use your Online Store theme.
- Your website key. It's the part of the snippet URL after https://static.personizely.net/ and before .js. Find the snippet in Settings → Website.
- A Storefront API access token, which Hydrogen projects usually already have as PUBLIC_STOREFRONT_API_TOKEN.
Install the package
npm install @personizely/shopify-hydrogenSet up the provider
- Return the Storefront credentials from your root loader in app/root.tsx. The provider also reads cart from the root loader's data, which the standard Hydrogen template already returns.
export async function loader(args: Route.LoaderArgs) {
const { env } = args.context
return {
// ...your existing data, including cart
personizely: {
storefrontAccessToken: env.PUBLIC_STOREFRONT_API_TOKEN,
shopDomain: env.PUBLIC_STORE_DOMAIN,
},
}
}- Wrap your app in PersonizelyProvider:
import { PersonizelyProvider } from '@personizely/shopify-hydrogen'
export default function App() {
const data = useRouteLoaderData<RootLoader>('root')
if (!data) return <Outlet />
return (
<PersonizelyProvider
websiteApiKey="YOUR_WEBSITE_KEY"
storefrontAccessToken={data.personizely.storefrontAccessToken}
shopDomain={data.personizely.shopDomain}
locale="en-US"
>
<Outlet />
</PersonizelyProvider>
)
}- If your storefront has a Content Security Policy (Hydrogen's createContentSecurityPolicy), allow Personizely's hosts. See Content Security Policy (CSP).
Provider props
Prop | What it does | Values / default |
|---|---|---|
websiteApiKey | Your Personizely website key | Required |
storefrontAccessToken | Storefront API token, used to read and update the cart and products | Required |
shopDomain | Your shop domain, for example myshop.myshopify.com | Required |
locale | Shop locale, used for formatting | 'en-US' |
currency | { rate, active, base }: conversion rate from your base currency, the active currency and the base currency | Base currency only |
market | Market handle, for Targets | None |
apiVersion | Storefront API version | '2024-01' |
methods.formatMoney | (amountInCents, includeDecimals) => string, to format prices like your storefront | Built-in formatting |
methods.builtProductPath | ({ handle }) => string, to build product URLs if yours aren't /products/<handle> | /products/<handle> |
customer | The logged-in customer (id, email, phone, firstName, lastName, displayName, hasAccount, tags), for customer targeting | null |
Define currency and market outside your component, or memoize them, so they keep a stable reference between renders.
Fire add-to-cart and checkout triggers
Hydrogen handles add to cart and checkout in your own components, so you tell Personizely when they happen. Both hooks return true if a widget was shown, so you can hold the action while an upsell or offer is displayed.
import { useCartAdd, useCheckout } from '@personizely/shopify-hydrogen'
const triggerCartAdd = useCartAdd()
const widgetShown = await triggerCartAdd({
id: product.id,
variantId: selectedVariant.id,
price: parseFloat(selectedVariant.price.amount), // in major units, e.g. 19.99
quantity: 1,
handle: product.handle,
})
if (!widgetShown) {
// add to cart as usual
}
const triggerCheckout = useCheckout()
if (!(await triggerCheckout())) {
window.location.href = checkoutUrl
}Set the page context
Call usePageContext in route components so product, collection, home and cart page rules and filters work:
import { usePageContext } from '@personizely/shopify-hydrogen'
usePageContext({
pageType: 'product',
product: { id: 1234567890, handle: product.handle, tags: product.tags }, // numeric ID
})
usePageContext({ pageType: 'collection', collection: { id: 9876543210 } })
usePageContext({ pageType: 'home' })
usePageContext({ pageType: 'cart' })usePersonizely() returns { cart, adapter, websiteApiKey } if you need the cart or formatting helpers directly.
Verify it works
- Run your storefront and open it in a normal browser window.
- In the developer console, look for Personizely initialized. Startup time: <n>ms.
- Navigate to another route. With ?ply_debug=1 in the first URL, the console logs Page change detected on each route change.
- Create a test popup with the Add to cart trigger, start it, and add a product to the cart. The popup should appear and useCartAdd should return true.
- Place a test order and check that it appears in reports for the Purchase goal.
Behavior details and limitations
- The snippet loads in the browser after hydration. Server-rendered HTML is shown first, so Content A/B testing with the visual editor can change the page a moment after it appears. For flicker-free tests of server-rendered content, use Full-stack experiments and feature flags and render the variation in your own code.
- Theme and template tests don't apply. They rely on Online Store themes. Price tests are documented for the Shopify Online Store; for a Hydrogen storefront, contact support. Content, split URL and full-stack campaigns, and all widgets, work.
- Commerce elements work. The Products (cross-sell and upsell) element, Cart progress (free shipping bar), unique discount codes and Coupon and discount codes auto-apply work on Hydrogen.
- Route changes are detected automatically and count as new page views.
- Orders come from Shopify. Purchases are recorded server-side from Shopify order data through the Personizely app, so the app must stay installed.
- Consent. Consent follows your Shopify customer privacy settings. See Cookies and consent.
Troubleshooting
- Nothing in the console → check that PersonizelyProvider wraps your routes and that your CSP allows Personizely's hosts.
- Add-to-cart widgets never show → your product form isn't calling the function returned by useCartAdd.
- Product page rules don't match → usePageContext isn't called on that route, or the product ID is a GID instead of the numeric ID.
- Prices in widgets look wrong → pass currency and methods.formatMoney to match your storefront's formatting.