Skip to content

fix(analytics): always render <Analytics.ProductView> on PDP#384

Merged
hta218 merged 1 commit into
mainfrom
fix/analytics-product-view-ungate
May 14, 2026
Merged

fix(analytics): always render <Analytics.ProductView> on PDP#384
hta218 merged 1 commit into
mainfrom
fix/analytics-product-view-ungate

Conversation

@paul-phan
Copy link
Copy Markdown
Member

What

Remove the {selectedVariant && ...} guard around <Analytics.ProductView> in app/routes/products/product.tsx. The component now mounts on every PDP render.

Why

For combined-listing products (where the variant is resolved after hydration via useOptimisticVariant), selectedVariant is null on the first render. The truthiness guard skips the mount entirely, so:

  • AnalyticsEvent.PRODUCT_VIEWED never dispatches
  • view_item never reaches window.dataLayer
  • GA4 e-comm tags wired to view_item never fire on combined-listing PDPs
  • Hydrogen's <ShopifyAnalytics> is missing the product context for downstream events on the same visit

The fallback values selectedVariant?.price.amount || "0", selectedVariant?.id || "", selectedVariant?.title || "" were already in place inside the JSX — they just weren't reachable behind the guard. Removing the guard activates them as intended.

Behaviour change

  • Before: view_item fires only after selectedVariant resolves (which is post-hydration for combined listings — often after the user has already interacted with the page).
  • After: view_item fires on first render for every product, with safe fallback values when variant data isn't loaded yet.

For products where selectedVariant IS available on first render (the majority — standard non-combined products), behaviour is unchanged.

Verification

  1. Open any PDP, especially a combined-listing product.
  2. Check the GA4 DebugView or GTM Preview — view_item should appear on initial page load.
  3. Confirm price/variant fields populate correctly once selectedVariant resolves (they're reactive bindings, so the analytics payload updates if needed for subsequent events).

Risk

Minimal. The change reverses a defensive guard that was over-restrictive; the fallback values handle the no-variant case gracefully. Tested locally on standard products, combined listings, and bundled products.

The component was gated on `{selectedVariant && ...}`, which skips
the mount entirely on the first render when `selectedVariant` is
`null`. For combined-listing products (which use
`useOptimisticVariant` to resolve the variant after hydration), this
means `PRODUCT_VIEWED` never dispatches and the `view_item` event
never reaches GTM / dataLayer / Hydrogen Shopify Analytics.

The fallback values (`selectedVariant?.price.amount || "0"`,
`selectedVariant?.id || ""`, `selectedVariant?.title || ""`) were
already in place — they just weren't reachable behind the truthiness
guard. Removing the guard activates them as intended.

After this change, `view_item` fires reliably on every PDP visit,
including products where the variant resolves post-hydration.
@hta218 hta218 self-requested a review May 14, 2026 02:31
@hta218 hta218 merged commit 969061f into main May 14, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants