Skip to content

Commit

Permalink
feat: add json-ld and individual og image for single product page (sa…
Browse files Browse the repository at this point in the history
…leor#1019)

- Change the OG image for the product page to the product image instead
of the default OG image.
- Add JSON-LD for product pages.
  • Loading branch information
grzegorzpokorski authored Nov 13, 2023
1 parent 51be2f0 commit 856e9fc
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 1 deletion.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"postcss": "8.4.31",
"prettier": "3.0.3",
"prettier-plugin-tailwindcss": "0.5.7",
"schema-dts": "1.1.2",
"tailwindcss": "3.3.5",
"typescript": "5.2.2",
"wonka": "6.3.4"
Expand Down
11 changes: 11 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 50 additions & 1 deletion src/app/(main)/products/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { notFound } from "next/navigation";
import { type ResolvingMetadata, type Metadata } from "next";
import xss from "xss";
import invariant from "ts-invariant";
import { type WithContext, type Product } from "schema-dts";
import { AddButton } from "./AddButton";
import { VariantSelector } from "@/ui/components/VariantSelector";
import { ProductImageWrapper } from "@/ui/atoms/ProductImageWrapper";
Expand Down Expand Up @@ -39,7 +40,6 @@ export async function generateMetadata(

const productName = product.seoTitle || product.name;
const variantName = product.variants?.find(({ id }) => id === searchParams.variant)?.name;

const productNameAndVariant = variantName ? `${productName} - ${variantName}` : productName;

return {
Expand All @@ -50,6 +50,16 @@ export async function generateMetadata(
? process.env.NEXT_PUBLIC_STOREFRONT_URL + `/products/${encodeURIComponent(params.slug)}`
: undefined,
},
openGraph: product.thumbnail
? {
images: [
{
url: product.thumbnail.url,
alt: product.name,
},
],
}
: null,
};
}

Expand Down Expand Up @@ -125,8 +135,47 @@ export default async function Page(props: { params: { slug: string }; searchPara
})
: "";

const productJsonLd: WithContext<Product> = {
"@context": "https://schema.org",
"@type": "Product",
image: product.thumbnail?.url,
...(selectedVariant
? {
name: `${product.name} - ${selectedVariant.name}`,
description: product.seoDescription || `${product.name} - ${selectedVariant.name}`,
offers: {
"@type": "Offer",
availability: selectedVariant.quantityAvailable
? "https://schema.org/InStock"
: "https://schema.org/OutOfStock",
priceCurrency: selectedVariant.pricing?.price?.gross.currency,
price: selectedVariant.pricing?.price?.gross.amount,
},
}
: {
name: product.name,

description: product.seoDescription || product.name,
offers: {
"@type": "AggregateOffer",
availability: product.variants?.some((variant) => variant.quantityAvailable)
? "https://schema.org/InStock"
: "https://schema.org/OutOfStock",
priceCurrency: product.pricing?.priceRange?.start?.gross.currency,
lowPrice: product.pricing?.priceRange?.start?.gross.amount,
highPrice: product.pricing?.priceRange?.stop?.gross.amount,
},
}),
};

return (
<section className="mx-auto grid max-w-7xl p-8">
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify(productJsonLd),
}}
/>
<form className="grid gap-2 sm:grid-cols-2" action={addItem}>
{firstImage && (
<ProductImageWrapper
Expand Down

0 comments on commit 856e9fc

Please sign in to comment.