Integration and verification
Who does what and in what order, the self-serve staging checklist, and a symptom-to-owner triage table.
The other pages here are the component's API. This one is the process: which work is yours, which is your Product Genius contact's, and how the two of you confirm it worked without a scheduled call.
Who owns what
| # | Step | Owner | Effort |
|---|---|---|---|
| 1 | Provision your organization with Product Genius, which provisions your catalog and recommendations. On Shopify, that starts with installing the app — see the Shopify section. | You + Product Genius (pipeline) | 15 min |
| 2 | Store configuration: recommendations and appearance (design tokens) on product pages | Product Genius contact | — |
| 3 | Store configuration: headless mode — cart events routed to your onAddToCart, Add-to-Cart buttons on multi-variant cards, storefront URL on record | Product Genius contact | — |
| 4 | Page patterns matched to your storefront's product URLs (e.g. ^/products/) | Product Genius contact | — |
| 5 | Install the package and render <ProductGeniusFeed> on your product page | Your engineers | ~half a day incl. QA |
| 6 | onAddToCart wired to your storefront's own cart mutation | Your engineers | part of 5 |
| 7 | Content-Security-Policy allows the Product Genius hosts | Your engineers | minutes |
| 8 | Joint verification on staging | Both | ~10 min, self-serve |
Steps 1–4 without 5–7: nothing renders, because no script ever loads on your pages. Steps
5–7 without 2–3: the component mounts an empty div and stays silent. Both halves are
required, and neither can break your storefront on its own — which is why the two sides
can proceed in either order. Landing your code before your store is configured is a
perfectly safe way to sequence the work.
Your side — steps 5 to 7
Four small changes:
Install the package
Tarball or git — see Install. Peer deps: React 18 or 19.
Render the feed on your product page
<ProductGeniusFeed> with the product context from your loader
(pageConfig), where you want the recommendations to appear.
On SPA storefronts, pass key={product.id} so a client-side product → product navigation
remounts the feed and refetches. On any Vite-based setup — including Hydrogen — add
optimizeDeps: {include: ['@productgenius/react']} to your Vite config so the first
npm run dev load doesn't re-optimize mid-hydration.
Wire your cart
onAddToCart calls your own cart mutation and updates your
own cart UI. On Shopify, map the feed's numeric variant id to a gid.
Allow the hosts in your CSP
script-src and connect-src. If your CSP is nonce-based — Hydrogen's
default — thread the request nonce through the nonce prop; omit it otherwise.
Optional — the search bar. If your store also uses Product Genius search, render
<ProductGeniusSearchBar> where the search UI belongs, usually
your header. It needs the feed component on the page (that is what loads the bundle) plus
the search keys in your store configuration, set by your Product Genius contact. Render one
instance per page, in UI that exists at page load.
Failure posture
If the Product Genius backend is unreachable, or your store isn't configured yet, your product page renders normally: an empty mount node, zero layout shift, and no console errors from the component. The search-bar skeleton, if you use it, keeps working as plain native search. The integration cannot take your page down.
Joint verification — step 8
Self-serve, about ten minutes, on a treated product page. Hard-reload first to bypass cache.
Network
Three requests, in order, all 200:
GET …/shopify/tag.jsPOST …/generate_visitor_configPOST …/feed/…
Console
window.GAMALONis defined.- A
.gamalon-appelement is in the DOM. typeof window.pgEventHandlers.onAddToCart === 'function'.
Cards and Add-to-Cart
Recommendation cards render. Click a card's Add-to-Cart button
(.pg-card-product-cart button.pg-app-btn): your cart mutation fires and your cart UI
updates with that card's variant.
SPA behaviour
Navigate product → collection → a different product, and confirm the feed re-rendered for the new product. Then switch a variant and add a card to the cart, and confirm the correct variant lands.
Triage: the feed isn't showing
| Symptom | Meaning | Whose court |
|---|---|---|
No tag.js request at all | The component isn't rendered on this route, or CSP blocked script-src — the console names the directive | Yours |
tag.js 200 but window.GAMALON undefined | The script was blocked after loading (missing nonce?), or the store isn't enabled yet | Yours (nonce) / Product Genius (enablement) |
| Feed request 200 but the mount stays empty | Backend or catalog state — that product has no recommendations built yet. Your wiring is fine. | Product Genius |
| Cards render but multi-variant cards have no Add-to-Cart button | Headless mode not fully applied to the store configuration | Product Genius |
| The button renders, but clicking it does nothing | Headless cart routing not applied, or onAddToCart not passed | Product Genius / Yours |
For search-bar-specific symptoms — a skeleton that shimmers forever — check the placement rules first: a second mount on the page, or a mount that wasn't in the DOM when the bundle initialized, both produce exactly that.
How is this guide?