From 8bc80c872d140b2c6a1c89c54eba587d4385887b Mon Sep 17 00:00:00 2001 From: sebseb7 Date: Fri, 18 Jul 2025 16:09:37 +0200 Subject: [PATCH] Enhance GTIN validation in product XML generation: Improved the GTIN validation logic in feeds.cjs to include checksum verification, ensuring only products with valid GTINs are processed. This update enhances data integrity for SEO purposes. --- prerender/seo/feeds.cjs | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/prerender/seo/feeds.cjs b/prerender/seo/feeds.cjs index 3ecc436..531922b 100644 --- a/prerender/seo/feeds.cjs +++ b/prerender/seo/feeds.cjs @@ -343,11 +343,32 @@ const generateProductsXml = (allProductsData = [], baseUrl, config) => { return; } - // Validate GTIN format (must be numeric and proper length) + // Validate GTIN format and checksum const gtinString = product.gtin.toString().trim(); - const isValidGtin = /^\d{8}$|^\d{12}$|^\d{13}$|^\d{14}$/.test(gtinString); - if (!isValidGtin) { + // Helper function to validate GTIN with proper checksum validation + const isValidGTIN = (gtin) => { + if (!/^\d{8}$|^\d{12,14}$/.test(gtin)) return false; // Only 8, 12, 13, 14 digits allowed + + const digits = gtin.split('').map(Number); + const length = digits.length; + let sum = 0; + + for (let i = 0; i < length - 1; i++) { + // Even/odd multiplier depends on GTIN length + let multiplier = 1; + if (length === 8) { + multiplier = (i % 2 === 0) ? 3 : 1; + } else { + multiplier = ((length - i) % 2 === 0) ? 3 : 1; + } + sum += digits[i] * multiplier; + } + const checkDigit = (10 - (sum % 10)) % 10; + return checkDigit === digits[length - 1]; + }; + + if (!isValidGTIN(gtinString)) { skippedCount++; return; } @@ -404,8 +425,8 @@ const generateProductsXml = (allProductsData = [], baseUrl, config) => { return; } - // Generate GTIN/EAN if available - const gtin = product.gtin ? escapeXml(product.gtin.toString().trim()) : null; + // Generate GTIN/EAN if available (use the already validated gtinString) + const gtin = gtinString ? escapeXml(gtinString) : null; // Generate product ID (using articleNumber or seoName) const rawProductId = product.articleNumber || product.seoName || `product_${Date.now()}_${Math.random().toString(36).substr(2, 5)}`;