Skip to content

Commit dd63a83

Browse files
igoramfclaude
andcommitted
feat(commerce/seo): add descriptionSource option to SeoPDPV2
Adds a `descriptionSource` prop ("seo" | "product") that controls which field is used as the meta description when no manual override is set. - "seo" (default): uses jsonLD.seo.description — existing behavior, no breaking change - "product": strips HTML from jsonLD.product.description — useful when the SEO description is empty or when the richer product copy is preferred In VTEX, product.description is a rich-text HTML field meant for page display, while seo.description maps to metaTagDescription — a plain-text field designed for meta tags. The "product" source strips HTML before writing to <meta name="description"> and og:description. Falls back to the other source if the chosen one is empty. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent cc04882 commit dd63a83

1 file changed

Lines changed: 20 additions & 1 deletion

File tree

commerce/sections/Seo/SeoPDPV2.tsx

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ export interface Props {
1515
title?: string;
1616
/** @title Description Override */
1717
description?: string;
18+
/**
19+
* @title Description Source
20+
* @description Choose which field to use as the meta description when no Description Override is set.
21+
* "seo" uses the SEO description from the search index (default).
22+
* "product" uses the product's own description field, stripping HTML tags — useful when the SEO description is empty or you prefer the richer product copy.
23+
*/
24+
descriptionSource?: "seo" | "product";
1825
/**
1926
* @title Disable indexing
2027
* @description In testing, you can use this to prevent search engines from indexing your site
@@ -38,18 +45,30 @@ export function loader(_props: Props, _req: Request, ctx: AppContext) {
3845
const {
3946
title: titleProp,
4047
description: descriptionProp,
48+
descriptionSource = "seo",
4149
jsonLD,
4250
omitVariants,
4351
ignoreStructuredData,
4452
} = props;
4553

54+
const productDescription = jsonLD?.product.description
55+
?.replace(/<[^>]+>/g, " ")
56+
.replace(/\s+/g, " ")
57+
.trim();
58+
59+
const resolvedDescription = descriptionProp ||
60+
(descriptionSource === "product"
61+
? productDescription || jsonLD?.seo?.description
62+
: jsonLD?.seo?.description || productDescription) ||
63+
ctx.seo?.description || "";
64+
4665
const title = renderTemplateString(
4766
titleTemplate,
4867
titleProp || jsonLD?.seo?.title || ctx.seo?.title || "",
4968
);
5069
const description = renderTemplateString(
5170
descriptionTemplate,
52-
descriptionProp || jsonLD?.seo?.description || ctx.seo?.description || "",
71+
resolvedDescription,
5372
);
5473
const image = jsonLD?.product.image?.[0]?.url;
5574
const canonical = jsonLD?.seo?.canonical

0 commit comments

Comments
 (0)