Skip to content

Commit 39eb31a

Browse files
(fix/site-2312): adicionando, context, types e verificacoes para seoplp decoapps
1 parent be56347 commit 39eb31a

File tree

1 file changed

+110
-31
lines changed

1 file changed

+110
-31
lines changed

commerce/sections/Seo/SeoPLP.tsx

Lines changed: 110 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ function Section({ jsonLD, ...props }: Props) {
1717
const canonical = props.canonical
1818
? props.canonical
1919
: jsonLD?.seo?.canonical
20-
? jsonLD.seo.canonical
21-
: jsonLD?.breadcrumb
22-
? canonicalFromBreadcrumblist(jsonLD?.breadcrumb)
23-
: undefined;
20+
? jsonLD.seo.canonical
21+
: jsonLD?.breadcrumb
22+
? canonicalFromBreadcrumblist(jsonLD?.breadcrumb)
23+
: undefined;
2424

2525
const noIndexing = props.noIndexing ||
2626
jsonLD?.seo?.noIndexing ||
@@ -43,70 +43,149 @@ function Section({ jsonLD, ...props }: Props) {
4343
];
4444

4545
if (Array.isArray(obj)) {
46-
return obj.map((item) => sanitizeObj(item)) as T;
46+
return obj.map(item => sanitizeObj(item)) as T;
4747
}
4848

49-
if (typeof obj === "object" && obj !== null) {
49+
if (typeof obj === 'object' && obj !== null) {
5050
return Object.fromEntries(
5151
Object.entries(obj)
5252
.filter(([key]) => !propsToRemove.includes(key))
53-
.map(([key, value]) => [key, sanitizeObj(value)]),
53+
.map(([key, value]) => [key, sanitizeObj(value)])
5454
) as T;
5555
}
5656

5757
return obj;
5858
}
5959

6060
function formatProductListing(data: ProductListingPage | null) {
61-
if (!data) return null;
62-
63-
const itemListElement: ProductListingPageListItem[] = data.products.reduce(
64-
(accu: ProductListingPageListItem[], product, index) => {
65-
accu.push({
66-
"@type": "ListItem",
61+
if (!data || !data.products || data.products.length === 0) return null;
62+
63+
64+
const itemListElement: ProductListingPageListItem[] = data.products
65+
.filter(product => product && product.sku)
66+
.map((product, index) => {
67+
68+
const sanitizedProduct = sanitizeObj(product);
69+
70+
71+
if (typeof sanitizedProduct === 'object' && sanitizedProduct !== null) {
72+
73+
const productWithDefaults = {
74+
...sanitizedProduct,
75+
"@type": sanitizedProduct["@type"] || "Product",
76+
77+
url: sanitizedProduct.url || `#product-${product.sku}`
78+
};
79+
80+
return {
81+
"@type": "ListItem" as const,
82+
position: index + 1,
83+
item: productWithDefaults
84+
};
85+
}
86+
87+
return {
88+
"@type": "ListItem" as const,
6789
position: index + 1,
68-
item: sanitizeObj(product),
69-
});
70-
return accu;
71-
},
72-
[],
73-
);
90+
item: sanitizedProduct
91+
};
92+
});
7493

94+
7595
return {
76-
"@type": "ItemList",
77-
"itemListElement": itemListElement,
96+
"@context": "https://schema.org",
97+
"@type": "ItemList" as const,
98+
"numberOfItems": itemListElement.length,
99+
"itemListElement": itemListElement
78100
};
79101
}
80102

81103
function formatBreadCrumb(data: ProductListingPage | null) {
82-
if (!data) return null;
104+
if (!data || !data.breadcrumb || !data.breadcrumb.itemListElement) return null;
105+
106+
107+
const validItems = data.breadcrumb.itemListElement
108+
.filter(item => item && item.name && item.item)
109+
.map((item, index) => ({
110+
"@type": "ListItem" as const,
111+
position: index + 1,
112+
name: item.name,
113+
item: item.item
114+
}));
83115

116+
if (validItems.length === 0) return null;
117+
118+
84119
return {
85-
"@type": "BreadcrumbList",
86-
"itemListElement": data.breadcrumb.itemListElement,
120+
"@context": "https://schema.org",
121+
"@type": "BreadcrumbList" as const,
122+
"itemListElement": validItems
87123
};
88124
}
89125

90126
function formatNewJsonLd(data: ProductListingPage | null) {
91-
const items = [formatProductListing(data), formatBreadCrumb(data)].filter((
92-
item,
93-
) => item !== null && item !== undefined);
94-
95-
return [{ ...items, pageInfo: jsonLD?.pageInfo, seo: jsonLD?.seo }];
127+
if (!data) return [];
128+
129+
130+
const jsonLdArray = [];
131+
132+
133+
const productList = formatProductListing(data);
134+
if (productList) {
135+
jsonLdArray.push(productList);
136+
}
137+
138+
139+
const breadcrumb = formatBreadCrumb(data);
140+
if (breadcrumb) {
141+
jsonLdArray.push(breadcrumb);
142+
}
143+
144+
145+
if (jsonLdArray.length > 0 && (data.seo || data.pageInfo)) {
146+
const webPageSchema = {
147+
"@context": "https://schema.org",
148+
"@type": "CollectionPage",
149+
...(data.seo?.title && { "name": data.seo.title }),
150+
...(data.seo?.description && { "description": data.seo.description }),
151+
...(data.seo?.canonical && { "url": data.seo.canonical }),
152+
153+
...(productList && { "mainEntity": productList }),
154+
...(breadcrumb && { "breadcrumb": breadcrumb })
155+
};
156+
157+
158+
return [webPageSchema];
159+
}
160+
161+
return jsonLdArray;
96162
}
97163

164+
98165
const newJsonLd = formatNewJsonLd(jsonLD);
166+
167+
168+
const validJsonLd = newJsonLd.filter(item => {
169+
try {
170+
171+
JSON.stringify(item);
172+
return true;
173+
} catch {
174+
console.error("Invalid JSON-LD item:", item);
175+
return false;
176+
}
177+
});
99178

100179
return (
101180
<Seo
102181
{...props}
103182
title={title || props.title}
104183
description={description || props.description}
105184
canonical={canonical}
106-
jsonLDs={newJsonLd}
185+
jsonLDs={validJsonLd}
107186
noIndexing={noIndexing}
108187
/>
109188
);
110189
}
111190

112-
export default Section;
191+
export default Section;

0 commit comments

Comments
 (0)