diff --git a/prerender/seo/category.cjs b/prerender/seo/category.cjs index 492e1f2..74bc16a 100644 --- a/prerender/seo/category.cjs +++ b/prerender/seo/category.cjs @@ -50,11 +50,6 @@ const generateCategoryJsonLd = (category, products = [], baseUrl, config) => { const root = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl; const categoryUrl = `${root}/Kategorie/${category.seoName}`; - // Calculate price valid date (current date + 3 months) - const priceValidDate = new Date(); - priceValidDate.setMonth(priceValidDate.getMonth() + 3); - const priceValidUntil = priceValidDate.toISOString().split("T")[0]; - const id = { business: `${root}#business`, website: `${root}#website`, @@ -117,87 +112,19 @@ const generateCategoryJsonLd = (category, products = [], baseUrl, config) => { const graph = [businessNode, websiteNode, breadcrumbNode, collectionPageNode]; - // Add product list if products are available - if (products && products.length > 0) { + // ItemList: URLs only — full Product/Offer markup belongs on each /Artikel/… page (Google guidelines). + const withUrls = (products || []).filter((p) => p && p.seoName); + if (withUrls.length > 0) { collectionPageNode.mainEntity = { "@id": id.itemList }; graph.push({ "@id": id.itemList, "@type": "ItemList", - numberOfItems: products.length, - itemListElement: products.slice(0, 20).map((product, index) => ({ + numberOfItems: withUrls.length, + itemListElement: withUrls.map((product, index) => ({ "@type": "ListItem", position: index + 1, - item: { - "@type": "Product", - name: product.name, - url: `${root}/Artikel/${product.seoName}`, - image: - product.pictureList && product.pictureList.trim() - ? `${root}/assets/images/prod${product.pictureList - .split(",")[0] - .trim()}.avif` - : `${root}/assets/images/nopicture.jpg`, - description: product.description - ? product.description.replace(/<[^>]*>/g, "").substring(0, 200) - : `${product.name} - Hochwertiges Growshop Produkt`, - sku: product.articleNumber || product.seoName, - brand: { - "@type": "Brand", - name: product.manufacturer || config.brandName, - }, - offers: { - "@type": "Offer", - url: `${root}/Artikel/${product.seoName}`, - price: - product.price && !isNaN(product.price) - ? product.price.toString() - : "0.00", - priceCurrency: config.currency, - priceValidUntil: priceValidUntil, - availability: product.available - ? "https://schema.org/InStock" - : "https://schema.org/OutOfStock", - seller: { "@id": id.business }, - itemCondition: "https://schema.org/NewCondition", - hasMerchantReturnPolicy: { - "@type": "MerchantReturnPolicy", - applicableCountry: "DE", - returnPolicyCategory: - "https://schema.org/MerchantReturnFiniteReturnWindow", - merchantReturnDays: 14, - returnMethod: "https://schema.org/ReturnByMail", - returnFees: "https://schema.org/FreeReturn", - }, - shippingDetails: { - "@type": "OfferShippingDetails", - shippingRate: { - "@type": "MonetaryAmount", - value: 5.9, - currency: "EUR", - }, - shippingDestination: { - "@type": "DefinedRegion", - addressCountry: "DE", - }, - deliveryTime: { - "@type": "ShippingDeliveryTime", - handlingTime: { - "@type": "QuantitativeValue", - minValue: 0, - maxValue: 1, - unitCode: "DAY", - }, - transitTime: { - "@type": "QuantitativeValue", - minValue: 2, - maxValue: 3, - unitCode: "DAY", - }, - }, - }, - }, - }, + item: `${root}/Artikel/${product.seoName}`, })), }); }