@@ -60,16 +60,21 @@ const OUT_OF_STOCK = 'http://schema.org/OutOfStock'
6060const getSKUAvailabilityString = ( seller ) =>
6161 isSkuAvailable ( seller ) ? IN_STOCK : OUT_OF_STOCK
6262
63- const formatGTIN = ( gtin ) => {
64- if ( ! gtin || typeof gtin !== 'string' ) return null
63+ const normalizeGTIN = ( raw ) => {
64+ if ( raw === null || raw === undefined ) return null
65+ const digits = String ( raw ) . replace ( / \D + / g, '' )
66+
67+ if ( ! digits || / ^ 0 + $ / . test ( digits ) ) return null
6568
6669 const validLengths = [ 8 , 12 , 13 , 14 ]
6770
68- if ( validLengths . includes ( gtin . length ) ) return gtin
71+ if ( validLengths . includes ( digits . length ) ) return digits
72+
73+ const validLengthsTarget = validLengths . find ( ( len ) => digits . length < len )
6974
70- const targetLength = validLengths . find ( ( len ) => gtin . length < len ) || 14
75+ if ( validLengthsTarget ) return digits . padStart ( validLengthsTarget , '0' )
7176
72- return gtin . padStart ( targetLength , '0' )
77+ return null
7378}
7479
7580const parseSKUToOffer = (
@@ -82,14 +87,8 @@ const parseSKUToOffer = (
8287 : lowHighForSellers ( item . sellers , { pricesWithTax } ) . low
8388
8489 const availability = getSKUAvailabilityString ( seller )
85-
8690 const price = getFinalPrice ( seller , getSpotPrice , { decimals, pricesWithTax } )
8791
88- const rawGTIN = item ?. [ gtinValue ]
89- const isGTINField = gtinValue !== 'itemId' && typeof rawGTIN === 'string'
90- const gtin = isGTINField ? formatGTIN ( rawGTIN ) : null
91- const skuValue = isGTINField ? gtin : item . itemId
92-
9392 // When a product is not available the API can't define its price and returns zero.
9493 // If we set structured data product price as zero, Google will show that the
9594 // product it's free (wrong info), but out of stock.
@@ -98,12 +97,16 @@ const parseSKUToOffer = (
9897 return null
9998 }
10099
100+ const rawSkuValue = item ?. [ gtinValue ]
101+ const normalizedGtin = normalizeGTIN ( rawSkuValue )
102+ const offerSku = normalizedGtin || item . itemId
103+
101104 const offer = {
102105 '@type' : 'Offer' ,
103106 price,
104107 priceCurrency : currency ,
105108 availability,
106- sku : skuValue ,
109+ sku : offerSku ,
107110 itemCondition : 'http://schema.org/NewCondition' ,
108111 priceValidUntil : path ( [ 'commertialOffer' , 'PriceValidUntil' ] , seller ) ,
109112 seller : {
@@ -220,12 +223,12 @@ export const parseToJsonLD = ({
220223 }
221224
222225 const baseUrl = getBaseUrl ( )
223-
224226 const category = getCategoryName ( product )
225227
226228 const rawGTIN = selectedItem ?. [ gtinValue ]
227- const gtin = formatGTIN ( rawGTIN )
228- const fallbackSKU = selectedItem ?. itemId || null
229+ const gtin = normalizeGTIN ( rawGTIN )
230+
231+ const merchantSKU = gtin || selectedItem ?. itemId || null
229232
230233 const productLD = {
231234 '@context' : 'https://schema.org/' ,
@@ -238,7 +241,7 @@ export const parseToJsonLD = ({
238241 : images [ 0 ] ?. imageUrl || null ,
239242 description : product . metaTagDescription || product . description ,
240243 mpn,
241- sku : gtin || fallbackSKU ,
244+ sku : merchantSKU ,
242245 category,
243246 offers : disableOffers ? null : offers ,
244247 gtin,
@@ -275,6 +278,8 @@ function StructuredData({ product, selectedItem }) {
275278 gtinValue,
276279 } )
277280
281+ if ( ! productLD ) return null
282+
278283 return < script { ...jsonLdScriptProps ( productLD ) } />
279284}
280285
0 commit comments