Skip to content

Fixed SSR and SEO of Product Details - #80

Merged
damianlegawiec merged 1 commit into
mainfrom
fix/pdp-seo
Mar 24, 2026
Merged

Fixed SSR and SEO of Product Details#80
damianlegawiec merged 1 commit into
mainfrom
fix/pdp-seo

Conversation

@damianlegawiec

@damianlegawiec damianlegawiec commented Mar 24, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features

    • Product view events are now automatically tracked and recorded in analytics.
  • Bug Fixes

    • Improved error responses when products are unavailable or not found.
  • Refactor

    • Streamlined product page architecture and unified product data fetching logic.

@coderabbitai

coderabbitai Bot commented Mar 24, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

The PR refactors product page data fetching by removing the ProductDetailsWrapper component and consolidating data expansion configuration. Analytics tracking for product views is relocated from the wrapper to ProductDetails, and a new PRODUCT_PAGE_EXPAND constant centralizes the expand field list used across product metadata generation and page rendering.

Changes

Cohort / File(s) Summary
Analytics Tracking Relocation
src/app/[country]/[locale]/(storefront)/products/[slug]/ProductDetails.tsx
Added useEffect hook to call trackViewItem(product, currency) whenever product or currency changes, moving analytics tracking responsibility from the removed wrapper component.
Wrapper Removal
src/app/[country]/[locale]/(storefront)/products/[slug]/ProductDetailsWrapper.tsx
Removed entire component that previously handled product data fetching, loading state management, error handling, and view tracking. Responsibilities migrated to parent page component and child ProductDetails component.
Page Component Refactoring
src/app/[country]/[locale]/(storefront)/products/[slug]/page.tsx
Replaced ProductDetailsWrapper with direct ProductDetails usage. Added notFound() invocation on fetch failure, switched to PRODUCT_PAGE_EXPAND for consistent data expansion, and simplified JSON-LD rendering condition based on canonical URL.
Expand Configuration Centralization
src/lib/data/cached.ts, src/lib/metadata/product.ts
Added new exported constant PRODUCT_PAGE_EXPAND containing expand fields (variants, media, option_types, metafields). Updated both product metadata generation and product page to use this centralized configuration instead of hardcoded expand arrays.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

  • Bump SDK to 0.7.1 #49: Introduces changes to analytics tracking (src/lib/analytics/gtm.ts) and product type updates that directly affect the trackViewItem function signature and types now being called in ProductDetails.
  • Upgrade to Spree 5.4 media system #65: Modifies product data fetch expand field usage on the product details page, similarly refactoring which related product data is requested during rendering.
  • Use Categories #51: Updates the analytics pipeline (mapProductToGA4Item) to use product categories, affecting the same GTM analytics flow that this PR extends with view item tracking.

Poem

🐰 The wrapper hops away, its work now done,
Expand fields bundled—configuration won!
Product views tracked when components ignite,
Data flows cleaner from left to right. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: moving product fetching to the server layer (fixing SSR) and improving product analytics tracking for SEO purposes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/pdp-seo

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/app/[country]/[locale]/(storefront)/products/[slug]/ProductDetails.tsx (1)

47-50: Consider adding a guard to prevent duplicate view tracking.

The useEffect fires whenever product or currency changes. If the product object reference is recreated (e.g., during a client-side navigation or hydration mismatch), this could trigger duplicate view_item analytics events.

Consider tracking only on initial mount or using a ref to prevent duplicate fires:

♻️ Optional: Guard against duplicate tracking
+import { useEffect, useMemo, useRef, useState } from "react";

 // Track product view (analytics - client-only side effect)
+const trackedProductRef = useRef<string | null>(null);
 useEffect(() => {
+  if (trackedProductRef.current === product.id) return;
+  trackedProductRef.current = product.id;
   trackViewItem(product, currency);
-}, [product, currency]);
+}, [product, currency]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/`[country]/[locale]/(storefront)/products/[slug]/ProductDetails.tsx
around lines 47 - 50, The useEffect calling trackViewItem(product, currency) can
fire multiple times when product or currency references change; update the logic
in the ProductDetails component to only fire once per product view (e.g., on
initial mount or when product.id changes) by adding a guard using a ref (or a
Set) to remember tracked product IDs and skip subsequent calls; make the guard
check the unique product identifier before invoking trackViewItem so repeated
re-renders or recreated product objects won't emit duplicate view_item events.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/app/`[country]/[locale]/(storefront)/products/[slug]/ProductDetails.tsx:
- Around line 47-50: The useEffect calling trackViewItem(product, currency) can
fire multiple times when product or currency references change; update the logic
in the ProductDetails component to only fire once per product view (e.g., on
initial mount or when product.id changes) by adding a guard using a ref (or a
Set) to remember tracked product IDs and skip subsequent calls; make the guard
check the unique product identifier before invoking trackViewItem so repeated
re-renders or recreated product objects won't emit duplicate view_item events.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 31339cec-5d41-44c4-8dc7-7a5bcca2dbb2

📥 Commits

Reviewing files that changed from the base of the PR and between a40d405 and 46755da.

📒 Files selected for processing (5)
  • src/app/[country]/[locale]/(storefront)/products/[slug]/ProductDetails.tsx
  • src/app/[country]/[locale]/(storefront)/products/[slug]/ProductDetailsWrapper.tsx
  • src/app/[country]/[locale]/(storefront)/products/[slug]/page.tsx
  • src/lib/data/cached.ts
  • src/lib/metadata/product.ts
💤 Files with no reviewable changes (1)
  • src/app/[country]/[locale]/(storefront)/products/[slug]/ProductDetailsWrapper.tsx

@damianlegawiec
damianlegawiec merged commit bc6a069 into main Mar 24, 2026
4 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.

1 participant