La documentazione Google sulle schede prodotto separa due cose che molti articoli confondono: le proprietà richieste perché una pagina sia idonea a un risultato avanzato, e le proprietà che arricchiscono quel risultato quando sono presenti. Le informazioni su resi e spedizione appartengono al secondo gruppo. Search Central le classifica esplicitamente tra gli arricchimenti di risultato, insieme alle valutazioni, alla disponibilità e ai cali di prezzo.
Questo articolo ripercorre il markup Product così come è documentato, sezione per sezione: cosa è obbligatorio, cosa non lo è e dove collocare ogni blocco su PrestaShop 8/9 e WooCommerce.
La base obbligatoria sono cinque proprietà
Su Product:
nameimage, uno o più URL scansionabili e indicizzabilioffers
Su Offer:
price, oppurepriceSpecification.pricepriceCurrency, oppurepriceSpecification.priceCurrency
A questo si aggiungono tre vincoli. Le esperienze merchant listing richiedono un Offer e non un AggregateOffer, perché il venditore siete voi. Il prezzo deve essere maggiore di zero. E la pagina deve riguardare un singolo prodotto o le sue varianti, non un elenco né una categoria.
Google distingue inoltre due famiglie di markup. Il product snippet riguarda le pagine in cui non si può acquistare direttamente, tipicamente una recensione editoriale, con opzioni aggiuntive sulle recensioni. Il merchant listing riguarda le pagine in cui il visitatore acquista da voi, con taglie, spedizione e resi. Coprire le proprietà obbligatorie del merchant listing rende in genere la pagina idonea anche al product snippet.
Tutto il resto è consigliato
La tabella delle proprietà consigliate di Offer contiene availability, itemCondition, url, priceValidUntil, validFrom, validThrough, hasMerchantReturnPolicy e shippingDetails. Su Product: brand.name, sku, mpn, la famiglia gtin, description, category, color, size, material, pattern, audience, hasCertification, review, aggregateRating, inProductGroupWithID, isVariantOf e subjectOf.
Queste proprietà sbloccano visualizzazioni: valutazione media, costo di spedizione e spedizione gratuita, disponibilità, informazioni sui resi, calo di prezzo. Google precisa che gli arricchimenti vengono mostrati a discrezione di ciascuna esperienza e possono cambiare nel tempo, e consiglia quindi di fornire tutte le informazioni prodotto disponibili invece di puntare a una visualizzazione specifica.
Il passaggio che chiude la discussione: la procedura di messa in produzione chiede di correggere gli errori critici segnalati dal Rich Results Test, e aggiunge che i problemi non critici possono migliorare la qualità dei dati strutturati, ma che correggerli non è necessario per essere idonei ai risultati avanzati. E «Missing field hasMerchantReturnPolicy» e «Missing field shippingDetails» compaiono proprio come non critici in Search Console.
Resi e spedizione: il livello giusto è Organization
Per una policy di reso che copre tutto o quasi tutto il catalogo, Google chiede di dichiararla una sola volta, sulla pagina che descrive quella policy, in un MerchantReturnPolicy annidato sotto Organization (o OnlineStore) tramite hasMerchantReturnPolicy. Non serve ripeterla su ogni pagina del sito.
A questo livello ci sono due opzioni di markup minimo:
- Opzione A:
applicableCountryereturnPolicyCategory. Se la categoria èMerchantReturnFiniteReturnWindow, alloramerchantReturnDaysdiventa obbligatoria. - Opzione B:
merchantReturnLink, l’URL della pagina che descrive la policy ai clienti.
Il resto è consigliato e permette di essere precisi: returnFees, returnMethod, returnShippingFeesAmount, returnPolicyCountry, refundType, restockingFee, returnLabelSource, itemCondition, le varianti customerRemorse* e itemDefect*, e returnPolicySeasonalOverride per restringere la finestra durante le festività.
{
"@context": "https://schema.org",
"@type": "OnlineStore",
"name": "Il mio negozio",
"url": "https://example.com",
"hasMerchantReturnPolicy": {
"@type": "MerchantReturnPolicy",
"@id": "https://example.com/resi#policy",
"applicableCountry": ["IT", "SM"],
"returnPolicyCountry": "IT",
"returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow",
"merchantReturnDays": 30,
"returnMethod": "https://schema.org/ReturnByMail",
"returnFees": "https://schema.org/FreeReturn",
"refundType": "https://schema.org/FullRefund"
}
}
Il livello Offer serve solo a due casi: derogare alla policy standard per un prodotto specifico, oppure non avere alcuna policy standard. Le proprietà supportate lì sono un sottoinsieme di quelle disponibili a livello negozio. Per referenziare senza ambiguità la policy globale da una scheda basta un @id:
"hasMerchantReturnPolicy": { "@id": "https://example.com/resi#policy" }
La spedizione segue la stessa logica. La policy standard si dichiara sotto Organization, con un insieme di proprietà più ampio di quello disponibile a livello prodotto, e una scheda può rimandarvi tramite hasShippingService:
"shippingDetails": {
"@type": "OfferShippingDetails",
"hasShippingService": { "@id": "https://example.com/spedizioni#policy" }
}
Se descrivete la spedizione direttamente a livello Offer, quattro proprietà sono richieste per l’arricchimento: deliveryTime (con handlingTime e transitTime), shippingDestination (con addressCountry in ISO 3166-1 alpha-2), shippingRate.currency e shippingRate.value oppure shippingRate.maxValue. Una tariffa per blocco OfferShippingDetails: per più tariffe servono più blocchi.
Il markup arriva ultimo nell’ordine di priorità
Google documenta un ordine di precedenza per le informazioni sui resi, dalla fonte più forte alla più debole:
- Content API for Shopping, impostazioni di reso
- Impostazioni in Merchant Center o in Search Console
- Markup a livello di scheda prodotto
- Markup a livello
Organization
Due conseguenze pratiche. Se i vostri resi sono già configurati in Search Console o in Merchant Center, è quella configurazione a essere usata e il markup diventa ridondante. E l’assenza di markup su una scheda non equivale a «nessuna policy di reso»: Google scende semplicemente lungo la catena per trovare l’informazione. Per un catalogo in cui le spese di spedizione cambiano spesso, la documentazione suggerisce anzi Merchant Center al posto del markup.
priceValidUntil non è una data da rinnovare ogni anno
Definizione ufficiale: la data e l’ora dopo le quali il prezzo non sarà più disponibile, in formato ISO 8601. La documentazione aggiunge un solo avvertimento, e non è quello che si legge ovunque: la scheda potrebbe non essere mostrata se priceValidUntil indica una data passata. Il rischio nasce da una data scaduta, non da una proprietà assente.
Dopo la riscrittura della sezione dedicata alla durata delle promozioni, il ruolo di questa proprietà è preciso: delimitare uno sconto. L’inizio si dichiara con validFrom, la fine con validThrough oppure con priceValidUntil. Google raccomanda di fornire entrambi gli estremi, di verificare che l’inizio preceda la fine e di includere ora e fuso orario.
"offers": {
"@type": "Offer",
"price": 10.00,
"priceCurrency": "EUR",
"validFrom": "2026-11-20T08:00:00+01:00",
"priceValidUntil": "2026-11-30T23:59:59+01:00",
"priceSpecification": {
"@type": "UnitPriceSpecification",
"priceType": "https://schema.org/StrikethroughPrice",
"price": 15.00,
"priceCurrency": "EUR"
}
}
Attenzione al posizionamento. Sul nodo Offer, priceValidUntil e validThrough sono intercambiabili. Su un nodo PriceSpecification funziona solo validThrough: priceValidUntil non è applicabile lì.
Se il vostro prezzo non ha una data di fine reale, non mettete priceValidUntil. Una data mobile a un anno, generata automaticamente, non descrive nulla e equivale ad annunciare una fine promozione che non esiste.
Prezzo barrato, prezzo socio, prezzo al litro
Sono riconosciuti tre tipi di prezzo, codificati in priceSpecification sotto Offer:
- Prezzo attivo: né
priceTypenévalidForMemberTier. Può anche restare a livello di offerta, inprice. - Prezzo barrato:
priceTypecon valorehttps://schema.org/StrikethroughPrice. È ciò che attiva la visualizzazione promozionale, e il prezzo attivo diventa il prezzo scontato. - Prezzo socio:
validForMemberTierche punta a unMemberProgramTierdefinito in Merchant Center o in unMemberProgramsottoOrganization.
I due marcatori non si combinano: una specifica di prezzo che porta insieme priceType e validForMemberTier viene ignorata. Se compilate sia offers.price sia offers.priceSpecification per il prezzo attivo, Google usa offers.price.
Per i prodotti venduti a volume, peso o lunghezza, il prezzo unitario passa da referenceQuantity dentro una UnitPriceSpecification. La documentazione segnala che questo formato conta in particolare nell’Unione europea, in Nuova Zelanda e in Australia.
Varianti: ProductGroup e due strutture possibili
Una sola proprietà è obbligatoria su ProductGroup: name. L’identificativo del gruppo si dichiara con productGroupID sul ProductGroup (lo SKU padre) oppure con inProductGroupWithID su ciascuna variante. Se li indicate entrambi, devono coincidere. variesBy elenca gli assi di variazione, con sei valori supportati: color, size, material, pattern, suggestedAge e suggestedGender.
Sono documentate due strutture. O le varianti sono annidate nel ProductGroup tramite hasVariant, oppure sono dichiarate a fianco e rimandano al padre con isVariantOf e un @id. Google raccomanda la prima, descritta come la rappresentazione più compatta e naturale. La seconda è spesso più semplice da generare da un CMS.
I vincoli tecnici pesano quanto il markup. Ogni variante ha bisogno di un identificativo univoco (sku o gtin) e di un URL distinto che la preselezioni, con immagine, prezzo e disponibilità corretti e la possibilità di aggiungerla al carrello. Su un sito a pagina singola, un solo URL canonico rappresenta il gruppo. Su un sito multipagina, ogni pagina deve avere un markup completo e autonomo, con la definizione del ProductGroup ripetuta.
Etichettatura energetica: hasCertification
Per elettrodomestici, lampadine o schermi venduti nell’UE, la proprietà da usare è hasCertification, con un oggetto Certification:
issuedBy.name:ECoEuropean_Commissionper le etichette energetiche UE,ADEMEeBMWKper le classi di CO2 dei veicoli.name:EPREL,Vehicle_CO2_ClassoVehicle_CO2_Class_Discharged_Battery.certificationIdentification: il codice EPREL, richiesto per le etichette energetiche europee.certificationRating: per i casi senza codice EPREL (Norvegia, Svizzera, Regno Unito) o per le classi di CO2.ratingValueè obbligatorio, e per l’efficienza energetica lo sono anchebestRatingeworstRating.
Fino a dieci certificazioni per prodotto. La vecchia proprietà hasEnergyConsumptionDetails viene ancora letta, ma la documentazione consiglia di passare a hasCertification.
E gli AI Overview?
Nessuna documentazione pubblica di Google condiziona la comparsa negli AI Overview a hasMerchantReturnPolicy, shippingDetails o a un’altra proprietà di Product. Queste proprietà sono documentate per le esperienze merchant listing: pannello di conoscenza Shopping, Popular products, Google Immagini, Google Lens e product snippet.
Un markup pulito aiuta i sistemi di Google a capire la pagina, e già questo giustifica la cura. Ma finché nessuna documentazione né uno studio riproducibile lo dimostra, non c’è base per allocare budget su un rapporto di causa ed effetto tra queste proprietà e le risposte generative.
Implementazione su PrestaShop 8 e 9
Il tema Classic produce un JSON-LD Product con offers, ma né le policy di reso e spedizione né la struttura ProductGroup per le varianti. Due cantieri distinti, da non confondere.
Lato catalogo. O si sovrascrive nel tema figlio il template che emette il JSON-LD, con la manutenzione che questo comporta a ogni aggiornamento, oppure si passa da un modulo. In entrambi i casi, verificate che venga emesso un solo blocco Product per pagina: due moduli SEO attivi insieme producono due markup in concorrenza.
Lato negozio. La policy di reso e quella di spedizione si dichiarano una volta, sulle pagine CMS corrispondenti, dentro un blocco Organization. La via più semplice è un campo di codice personalizzato iniettato nell’head di quelle due pagine.
Il modulo DataFirefly All in One SEO copre il primo cantiere: grafo JSON-LD con Organization, WebSite, BreadcrumbList, Product con offers, priceValidUntil e l’AggregateRating presa da productcomments, più FAQPage e LocalBusiness. Fornisce anche i campi di codice personalizzato in head e a fine body, dove dichiarare le policy a livello negozio.
Implementazione su WooCommerce
WooCommerce emette nativamente un Product con offers, modificabile tramite il filtro woocommerce_structured_data_product. Yoast SEO e Rank Math costruiscono ciascuno il proprio grafo ed espongono il proprio punto di estensione. Scegliete una sola di queste tre fonti: sommarle significa pubblicare più blocchi Product sullo stesso URL.
Per le policy la logica è identica a PrestaShop: un blocco Organization sulla pagina dei resi e su quella delle spedizioni, referenziato dalle schede con @id se volete togliere ogni ambiguità. Il plugin llms.txt + AEO Schema WooCommerce gestisce questa parte di grafo e la FAQ per gli agenti.
Verificare il risultato
- Rich Results Test. Correggete gli errori critici. Gli avvisi non critici restano una vostra scelta: decidete in base agli arricchimenti che volete ottenere.
- Validatore schema.org. Sintassi JSON-LD e coerenza dei
@type, indipendentemente dalle regole di Google. - Search Console, report Merchant listings. Lo stato reale in produzione, una volta riscansionate le pagine. Mettete in conto diversi giorni dopo la pubblicazione.
- Merchant Center o Search Console, impostazioni di reso. Verificate che una configurazione esistente non stia già prevalendo sul vostro markup.
Da dove cominciare
- Verificare che
name,image,offers,priceepriceCurrencysiano presenti e corretti sul 100 % delle schede. È l’unico punto davvero bloccante. - Aggiungere
availability,itemCondition,sku,brand.namee il GTIN quando esiste. - Dichiarare la policy di reso e quella di spedizione una volta, a livello
Organization, sulle pagine dedicate. - Mettere
priceValidUntilsolo sui prezzi con una data di fine reale, insieme avalidFrom. - Trattare le varianti con
ProductGroup, dopo essersi assicurati che ogni variante abbia un URL proprio.
Una regola sta sopra tutto il resto: il markup deve descrivere ciò che la pagina mostra. Un reso gratuito dichiarato nel markup va annunciato sul sito, una finestra di 30 giorni dichiarata deve essere una finestra di 30 giorni reale. È questo principio, non il numero di proprietà, a spiegare la maggior parte delle azioni manuali sui dati strutturati.
Da leggere anche: la guida completa alla SEO e-commerce e il FAQ schema e i rich snippet.
Per passare all’azione: la nostra selezione di moduli per ottimizzare le schede prodotto.