
🛒 Ordini duplicati in WooCommerce: 3 script per il blocco a livello di carrello
Il cliente ha cliccato due volte su «Effettua ordine» e ora nel pannello di amministrazione compaiono due ordini identici a pochi secondi di distanza. L’addebito è doppio, il cliente è furioso e tu ti ritrovi a gestire un rimborso.
Gli ordini duplicati non sono un’ipotesi teorica. Circa un negozio su tre su WooCommerce li incontra, specie con hosting instabile o gateway di pagamento lenti. Ma anche su un server veloce un utente può aggiungere di nuovo un prodotto via URL o acquistare decine di volte un prodotto digitale gratuito.
Abbiamo preparato tre script funzionanti che coprono diversi scenari di duplicazione: dalla vendita forzata di un singolo pezzo al blocco degli inserimenti ripetuti via URL. Qui sotto trovi l’analisi completa con il codice.
Perché gli ordini si duplicano in WooCommerce
💡 Panoramica rapida:
- Scoprirai perché gli ordini si duplicano a livello di carrello, URL e acquisto ripetuto
- Installerai uno script per forzare la vendita di un singolo pezzo tramite campi meta
- Impedirai gli acquisti ripetuti di variazioni gratuite (beni digitali, coupon)
- Eliminerai la duplicazione via URL con
add-to-cartal refresh della pagina - Testerai la protezione e capirai cos’altro può causare duplicati a livello server
I duplicati di ordine nascono da tre scenari principali.
Primo, l’utente clicca più volte su «Effettua ordine». Succede quando la pagina è lenta, la persona non vede alcuna risposta e clicca di nuovo il pulsante. Su hosting lento, una storia comune.
Secondo scenario, i prodotti gratuiti. Se hai un prodotto digitale gratuito, nulla impedisce a un utente di «acquistarlo» dieci volte di fila. WooCommerce nativo non tiene traccia del fatto che lo stesso cliente abbia già preso lo stesso prodotto gratuito in precedenza.
Terzo, un link diretto con il parametro ?add-to-cart=123. Si aggiorna la pagina del carrello, il prodotto viene aggiunto di nuovo. Si segue due volte un link da una newsletter, due copie nel carrello.
Tutti e tre gli scenari si risolvono lato server tramite hook di WooCommerce. Nessun plugin, solo codice.
Metodo 1: forzare la vendita di un singolo pezzo tramite campi meta

Il primo script obbliga WooCommerce a trattare un prodotto specifico come «venduto singolarmente», anche se quella casella non è spuntata nelle impostazioni del prodotto. Il controllo avviene tramite un campo meta.
Quando il campo meta maximum_allowed_quantity è uguale a 1, il filtro woocommerce_is_sold_individually restituisce true e WooCommerce stesso blocca l’aggiunta di una seconda unità al carrello. Funziona sia per i prodotti semplici sia per le variazioni.
Aggiungi il codice al file functions.php del tema child oppure tramite il plugin Code Snippets:
1 function sd_woocommerce_is_sold_individually( $return, $product ) { 2 switch ( $product->get_type() ) { 3 case 'variation': 4 if ( $product->get_meta( 'variation_maximum_allowed_quantity' ) == 1 ) { 5 return true; 6 } 7 break; 8 case 'simple': 9 if ( $product->get_meta( 'maximum_allowed_quantity' ) == 1 ) { 10 return true; 11 } 12 break; 13 } 14 return $return; 15 } 16 add_filter( 'woocommerce_is_sold_individually', 'sd_woocommerce_is_sold_individually', 10, 2 );
Cosa succede qui: l’hook woocommerce_is_sold_individually si attiva ogni volta che WooCommerce verifica se un prodotto può essere aggiunto al carrello più di una volta. La funzione esamina i campi meta del prodotto e, se trova maximum_allowed_quantity = 1, attiva forzatamente la modalità «Venduto singolarmente». Per le variazioni il campo si chiama variation_maximum_allowed_quantity.
Come applicarlo. Entra nella modifica di un prodotto o di una variazione, aggiungi un campo personalizzato con nome maximum_allowed_quantity (oppure variation_maximum_allowed_quantity per una variazione) e valore 1. Salva. Fine, ora quel prodotto non può essere inserito due volte nel carrello.
Metodo 2: impedire gli acquisti ripetuti di variazioni gratuite
I prodotti digitali gratuiti sono la falla principale nella protezione dai duplicati. L’utente ha effettuato l’accesso, il prezzo del prodotto è zero, WooCommerce lascia passare l’ordine senza fare domande. Dieci ordini del genere da un solo cliente, dieci voci identiche nel pannello di amministrazione.
Lo script qui sotto verifica tramite wc_customer_bought_product() se lo stesso utente ha già acquistato lo stesso prodotto in precedenza. Se sì, l’aggiunta al carrello viene bloccata con un avviso chiaro.
1 function sd_disable_repeat_purchase_for_free_products( $passed, $product_id, $quantity, $variation_id = 0 ) { 2 $current_user = wp_get_current_user(); 3 $product = $variation_id > 0 ? wc_get_product( $variation_id ) : wc_get_product( $product_id ); 4 $target_id = $variation_id > 0 ? $variation_id : $product_id; 5 6 if ( floatval( $product->get_price() ) == 0 ) { 7 if ( wc_customer_bought_product( $current_user->user_email, $current_user->ID, $target_id ) ) { 8 wc_add_notice( 9 sprintf( __( 'You have already purchased "%s" and cannot purchase it again.', 'sd' ), $product->get_name() ), 10 'error' 11 ); 12 return false; 13 } 14 } 15 return $passed; 16 } 17 add_filter( 'woocommerce_add_to_cart_validation', 'sd_disable_repeat_purchase_for_free_products', 10, 4 );
Dopo l’installazione, l’utente vede un messaggio di errore quando prova ad aggiungere al carrello un prodotto gratuito già acquistato. L’ordine in sé non viene creato.
Due condizioni importanti. Primo, il cliente deve aver effettuato l’accesso. Per gli ospiti wp_get_current_user() restituisce un oggetto vuoto e il controllo non funziona. Secondo, il prezzo del prodotto deve essere esattamente zero (floatval elimina i problemi di formattazione). Lo script non tocca i prodotti con prezzo superiore a zero.
Metodo 3: protezione contro la duplicazione via URL con add-to-cart
WooCommerce permette di aggiungere un prodotto al carrello tramite un link diretto: /cart/?add-to-cart=123. Comodo per il marketing, ma se l’utente aggiorna la pagina o segue di nuovo il link, il prodotto viene aggiunto un’altra volta.
Questo script intercetta il caricamento della pagina del carrello o del checkout e, se il prodotto indicato nel parametro URL è già nel carrello, rimuove silenziosamente i parametri di query e reindirizza a un URL pulito.
1 function sd_prevent_duplicate_add_to_cart_redirect() { 2 if ( ( is_cart() || is_checkout() ) && isset( $_GET['add-to-cart'] ) ) { 3 $current_url = home_url( add_query_arg( null, null ) ); 4 $product_id = intval( $_GET['add-to-cart'] ); 5 $variation_id = isset( $_GET['variation_id'] ) ? intval( $_GET['variation_id'] ) : 0; 6 7 foreach ( WC()->cart->get_cart() as $cart_item ) { 8 if ( $cart_item['product_id'] == $product_id 9 && ( $variation_id == 0 || $cart_item['variation_id'] == $variation_id ) ) { 10 wp_redirect( remove_query_arg( array( 'add-to-cart', 'variation_id' ), $current_url ) ); 11 exit; 12 } 13 } 14 } 15 } 16 add_action( 'template_redirect', 'sd_prevent_duplicate_add_to_cart_redirect' );
L’hook template_redirect si attiva prima che WordPress inizi a generare la pagina. Lo script controlla se il parametro add-to-cart è presente nell’URL, cerca quel prodotto nel contenuto del carrello (WC()->cart->get_cart()) e, se lo trova, esegue un wp_redirect alla stessa pagina senza parametri di query.
L’aggiunta ripetuta via URL è eliminata. Allo stesso tempo, la prima aggiunta (quando il prodotto non è ancora nel carrello) funziona normalmente.
Mettere tutto insieme
Tutti e tre gli script non sono in conflitto e funzionano in modo indipendente:
- Il primo limita a 1 la quantità di un singolo prodotto, protezione contro le aggiunte multiple.
- Il secondo blocca gli acquisti ripetuti di prodotti gratuiti, protezione contro lo «spam di clic» sugli omaggi.
- Il terzo elimina la duplicazione via URL, protezione contro le aggiunte ripetute accidentali.
Aggiungi il codice tramite il plugin Code Snippets su WP.org, non direttamente nel file functions.php del tema. Il plugin permette di attivare e disattivare gli snippet uno per uno senza mandare in crash il sito in caso di errore e non perde il codice quando si cambia tema. Crea tre snippet separati, è più facile fare debug in questo modo.
Cos’altro verificare se i duplicati persistono
Gli script qui sopra coprono i duplicati a livello di carrello e checkout. Ma ci sono altre due fonti del problema che il codice non può risolvere.
Cache delle pagine carrello e checkout. Plugin di caching come WP Rocket o LiteSpeed Cache escludono queste pagine di default, ma dopo un aggiornamento delle impostazioni l’esclusione può saltare. Verifica: carrello, checkout e mio account non devono essere memorizzati nella cache a livello di plugin, di server o di CDN.
Retry dal gateway di pagamento. Se il gateway (Stripe, PayPal) non riceve conferma dal server in tempo, invia di nuovo la notifica e WooCommerce crea un secondo ordine. La causa di solito è un hosting lento o un firewall che blocca le richieste di callback. Soluzione: controlla i log del gateway per verificare invii ripetuti di webhook e assicurati che l’URL di callback sia accessibile dall’esterno.
Come testare la protezione
Dopo aver installato gli script, ricordati di testare ogni scenario su un sito di prova.
Metodo 1, crea un prodotto con il campo meta maximum_allowed_quantity = 1 e prova ad aggiungere due unità al carrello. Deve essere aggiunta solo un’unità.
Metodo 2, effettua l’accesso, acquista un prodotto gratuito, poi prova ad acquistarlo di nuovo. Dovresti vedere un messaggio di errore.
Metodo 3, aggiungi un prodotto al carrello tramite un link diretto con ?add-to-cart=ID, poi aggiorna la pagina. Il numero di articoli nel carrello non deve cambiare.
Testa in un’installazione separata o su un sito di staging. Sul negozio live, solo dopo un controllo completo.
⁉️🤔 Domande frequenti
Perché gli ordini si duplicano se il pulsante «Effettua ordine» è stato cliccato una volta sola?
Il motivo è quasi sempre una risposta lenta del server. L’utente clicca il pulsante, la richiesta parte, ma la pagina non si aggiorna per diversi secondi. La persona pensa di non aver cliccato e clicca di nuovo. Entrambe le richieste raggiungono WooCommerce e vengono creati due ordini. Gli script di questo articolo non coprono questa situazione; qui serve una protezione lato client (disabilitare il pulsante dopo il clic) oppure un controllo di unicità dell’ordine lato server tramite un token nonce.
Un gateway di pagamento può creare duplicati da solo?
Sì. Se il gateway non riceve un HTTP 200 dal tuo server in risposta a un IPN/webhook, ripete l’invio. A ogni tentativo WooCommerce può creare un nuovo ordine. Il problema si risolve velocizzando l’hosting e verificando che l’URL di callback del gateway non sia bloccato da un firewall e non richieda autenticazione HTTP.
Questa protezione blocca gli ordini ripetuti legittimi di un cliente?
No. Gli script agiscono nella fase di aggiunta al carrello, non nella fase di creazione dell’ordine. Se un cliente ha fatto deliberatamente un ordine e una settimana dopo ne fa un secondo, gli script non interferiscono. Eccezione: il metodo 2, che vieta l’acquisto ripetuto di un prodotto gratuito da parte dello stesso utente.
È obbligatorio usare Code Snippets o si può mettere in functions.php?
Puoi usare
functions.php, ma consigliamo Code Snippets. Con un errore di battitura nel codice difunctions.phpti trovi una schermata bianca e puoi accedere solo via FTP. Il plugin Code Snippets intercetta gli errori fatali e disattiva automaticamente lo snippet problematico, il sito resta in piedi.
I plugin per prevenire i duplicati sono utili?
Plugin specializzati come WooCommerce Duplicate Order Blocker lavorano a un livello diverso: tracciano i duplicati per IP, email o impronta digitale del browser nella fase di checkout. Questo copre lo scenario del doppio clic che i nostri script non coprono. Tuttavia i plugin non risolvono il problema dei duplicati via URL add-to-cart e degli acquisti ripetuti di un prodotto gratuito. L’opzione ideale: gli script di questo articolo più un plugin blocker sul checkout.
Riepilogo: tre livelli di protezione dai duplicati
Tre script coprono tre scenari specifici di duplicazione degli ordini. Installali tutti insieme: ognuno è responsabile della propria area e insieme offrono una protezione efficace a livello di carrello.
Se dopo l’installazione compaiono ancora duplicati, guarda in direzione dell’hosting e del gateway di pagamento. Un doppio clic sul pulsante «Effettua ordine» non si può curare con il codice a livello di carrello; qui serve un plugin blocker oppure una protezione personalizzata del pulsante via JavaScript.
Testa la protezione su un sito di prova, poi portala in produzione. Quindici minuti per installare tre snippet fanno risparmiare ore di gestione rimborsi.


