diff --git a/prerender/seo/feeds.cjs b/prerender/seo/feeds.cjs index 6af6f8e..351ac57 100644 --- a/prerender/seo/feeds.cjs +++ b/prerender/seo/feeds.cjs @@ -104,6 +104,9 @@ const determineUnitPricingData = (product) => { return result; }; +const fs = require('fs'); +const path = require('path'); + const generateProductsXml = (allProductsData = [], baseUrl, config) => { const currentDate = new Date().toISOString(); @@ -297,6 +300,10 @@ const generateProductsXml = (allProductsData = [], baseUrl, config) => { let processedCount = 0; let skippedCount = 0; + // Track products with missing data for logging + const productsNeedingWeight = []; + const productsNeedingDescription = []; + // Category IDs to skip (seeds, plants, headshop items) const skipCategoryIds = [689, 706, 709, 711, 714, 748, 749, 896, 710]; @@ -386,6 +393,17 @@ const generateProductsXml = (allProductsData = [], baseUrl, config) => { const cleanDescription = escapeXml(rawDescription) || "Produktbeschreibung nicht verfügbar"; + // Check if description is missing or too short (less than 20 characters) + const originalDescription = product.description ? cleanTextContent(product.description) : ''; + if (!originalDescription || originalDescription.length < 20) { + productsNeedingDescription.push({ + id: product.articleNumber || product.seoName, + name: product.name || 'Unnamed', + currentDescription: originalDescription || 'NONE', + url: `/Artikel/${product.seoName}` + }); + } + // Clean product name const rawName = product.name || "Unnamed Product"; const cleanName = escapeXml(cleanTextContent(rawName)) || "Unnamed Product"; @@ -473,6 +491,13 @@ const generateProductsXml = (allProductsData = [], baseUrl, config) => { if (product.weight && !isNaN(product.weight)) { productsXml += ` ${parseFloat(product.weight).toFixed(2)} g`; + } else { + // Track products without weight + productsNeedingWeight.push({ + id: product.articleNumber || product.seoName, + name: product.name || 'Unnamed', + url: `/Artikel/${product.seoName}` + }); } // Add unit pricing data (required by German law for many products) @@ -503,6 +528,47 @@ const generateProductsXml = (allProductsData = [], baseUrl, config) => { console.log(` 📊 Processing summary: ${processedCount} products included, ${skippedCount} skipped`); + // Write log files for products needing attention + const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); + const logsDir = path.join(process.cwd(), 'logs'); + + // Ensure logs directory exists + if (!fs.existsSync(logsDir)) { + fs.mkdirSync(logsDir, { recursive: true }); + } + + // Write missing weight log + if (productsNeedingWeight.length > 0) { + const weightLogContent = `# Products Missing Weight Data +# Generated: ${new Date().toISOString()} +# Total products missing weight: ${productsNeedingWeight.length} + +${productsNeedingWeight.map(product => `${product.id}\t${product.name}\t${baseUrl}${product.url}`).join('\n')} +`; + + const weightLogPath = path.join(logsDir, `missing-weight-${timestamp}.log`); + fs.writeFileSync(weightLogPath, weightLogContent, 'utf8'); + console.log(`\n ⚠️ Products missing weight (${productsNeedingWeight.length}) - saved to: ${weightLogPath}`); + } + + // Write missing description log + if (productsNeedingDescription.length > 0) { + const descLogContent = `# Products With Insufficient Description Data +# Generated: ${new Date().toISOString()} +# Total products needing description: ${productsNeedingDescription.length} + +${productsNeedingDescription.map(product => `${product.id}\t${product.name}\t"${product.currentDescription}"\t${baseUrl}${product.url}`).join('\n')} +`; + + const descLogPath = path.join(logsDir, `missing-description-${timestamp}.log`); + fs.writeFileSync(descLogPath, descLogContent, 'utf8'); + console.log(`\n ⚠️ Products with insufficient description (${productsNeedingDescription.length}) - saved to: ${descLogPath}`); + } + + if (productsNeedingWeight.length === 0 && productsNeedingDescription.length === 0) { + console.log(` ✅ All products have adequate weight and description data`); + } + return productsXml; };