Contenuto articolo
- Perché cart, checkout e search sono il vero bersaglio dei bot (non la homepage)
- Anatomia di un endpoint dinamico WordPress
- I 5 pattern di attacco bot su endpoint dinamici
- Strategia di protezione a 4 livelli
- Architettura completa: dal CDN all'application server
- Caso studio reale: WooCommerce con 12.000 SKU
- Configurazione PHP-FPM ottimizzata per WooCommerce con bot
- Monitoring: cosa misurare e come
- Errori da evitare
- FAQ
- I bot AI rispettano robots.txt?
- Conviene bloccare i bot su /cart/ e /checkout/ o lasciarli indicizzare?
- Come distinguo bot AI da bot SEO legittimi?
- Redis è obbligatorio per WooCommerce con bot?
- Cloudflare Bot Protection vale i 20€/mese Pro?
- Devo applicare la stessa protezione anche su /?s= (search)?
- Come gestisco i falsi positivi sui clienti che usano headless browser?
- Conclusione operativa: il piano d'azione in 7 giorni
- Riferimenti utili per approfondire
Perché cart, checkout e search sono il vero bersaglio dei bot (non la homepage)
Se il tuo WordPress con WooCommerce brucia CPU e banda senza convertirli in fatturato, il colpevole probabilmente non è il traffico umano. È un'orda di bot AI che martella /cart/, /checkout/, /?s=... e /my-account/ senza generare un solo ordine.
Una ricerca Kinsta del giugno 2026 ha misurato che le pagine con endpoint dinamici (cart, checkout, ricerca, account) costano da 10 a 50 volte di più in termini di CPU rispetto a pagine statiche cache-abili. Motivo: ogni richiesta esegue PHP, interroga il database, genera sessioni WooCommerce, scrive transient.
Quando un bot come GPTBot, ClaudeBot o un crawler SEO scansione 5.000 URL di un catalogo, non colpisce solo esempio di URL prodotto (pagine statiche e cache-friendly). Colpisce:
- esempio di URL search (search con query parameter)
- esempio di URL cart (cart sempre dinamico)
- esempio di URL checkout (checkout sempre dinamico)
- esempio di URL add-to-cart (AJAX endpoint)
- esempio di URL account (account privato)
Ognuna di queste URL, se non protetta strategicamente, diventa una vora-di-risorse che erode il budget hosting e peggiora l'esperienza utente reale.
Su mrtux.it abbiamo già trattato i bot AI generici e la protezione specifica WooCommerce. Oggi scendiamo nel dettaglio: come costruire un'architettura di protezione chirurgica sugli endpoint dinamici senza rompere la UX reale del checkout.
Anatomia di un endpoint dinamico WordPress
Capire perché certi URL sono costosi è il primo passo per proteggerli in modo intelligente. Tre sono i fattori di costo.
Costo PHP: esecuzione del core WordPress + plugin
Una richiesta a /cart/ esegue:
- Bootstrap WordPress (file
wp-load.php, connessione DB, caricamento plugin) - Inizializzazione WooCommerce (cart object, session handler)
- Query al database per recuperare il carrello (transient
wc_cart_hash_*) - Render del template con i prodotti aggiunti
- Invio headers di cache (o non-invio, se configurato male)
Su un'installazione WooCommerce tipica con 30 plugin attivi, questo costa tra 80 e 250 millisecondi per richiesta. Un bot che esegue 1.000 richieste al minuto consuma 1.3-4 secondi di CPU al minuto, anche per visitatori che non compreranno mai.
Costo database: query non indicizzate
WooCommerce salva il carrello in transients (opzioni autoload yes per default fino a WordPress 6.4). Ogni richiesta a /cart/ esegue:
# esempio codice
SELECT option_value FROM wp_options WHERE option_name = '_transient_wc_cart_hash_abc123' LIMIT 1
Con decine di migliaia di carrelli abbandonati, la tabella wp_options cresce fino a 1-2 GB e ogni query diventa un LIKE '%wc_cart%' non indicizzato. Su articoli precedenti abbiamo trattato l'ottimizzazione Docker PHP per ambienti di sviluppo, ma qui il problema è anche in produzione.
Costo banda: pagine non compresse, asset non minificati
Le pagine cart/checkout non sono quasi mai abilitate alla compressione GZIP perché contengono nonce anti-CSRF e token dinamici. Una pagina checkout può pesare 200-400 KB. Un bot che ne chiede 10.000 al giorno consuma 2-4 GB di banda senza valore.
I 5 pattern di attacco bot su endpoint dinamici
I bot che colpiscono cart, checkout e search hanno pattern diversi dai crawler generici. Riconoscerli è essenziale per bloccarli senza falsi positivi.
Pattern 1 — Scraping di prezzi e stock
Bot che confrontano prezzi tra competitor colpiscono /?s=prodotto e /prodotto-x/ per estrarre prezzo corrente, disponibilità, variazioni. Rilevabili da: alta frequenza, assenza di referer, user agent headless browser (Chrome Headless, PhantomJS).
Pattern 2 — Credential stuffing su /my-account/
Bot che provano coppie username/password rubate contro il form di login. Rilevabili da: alta frequenza di POST a /wp-login.php, assenza di cookie, distribuzione anomala di IP.
Pattern 3 — Inventory hoarding su /cart/
Bot che aggiungono prodotti al carrello per poi abbandonarli, creando stock fantasma e confusione nel gestionale. Rilevabili da: sequenza POST /?add-to-cart=... ripetuta senza successivo /checkout/.
Pattern 4 — Card testing su /checkout/
Bot che testano carte di credito rubate con transazioni di pochi centesimi. Rilevabili da: alta frequenza di POST a /checkout/ con errori 402/403, IP distribuiti, assenza di completamento ordine.
Pattern 5 — Search spam per indicizzare URL parametrizzate
Bot SEO che generano migliaia di URL /?s=keyword per scoperte di long-tail. Rilevabili da: richieste a /?s=* con keyword senza senso, alta frequenza.
Strategia di protezione a 4 livelli
La protezione degli endpoint dinamici non è blocco totale: è differenziazione intelligente tra traffico umano e traffico bot. Quattro livelli, dal meno invasivo al più aggressivo.
Livello 1 — Edge caching differenziato per URL pattern
Cloudflare, Fastly e Varnish permettono regole di cache specifiche per URL pattern. La regola chiave: non bloccare, ma non eseguire PHP.
# Cloudflare Page Rules (Dashboard → Caching → Configuration)
# Pattern 1: Cache search ma solo per bot AI noti
URL pattern: *tuosito.it/?s=*
Cache eligibility: Eligible for cache
Edge cache TTL: 1 hour
Browser cache TTL: 5 minutes
Bypass cache on cookie: wordpress_logged_in|woocommerce_cart_hash|woocommerce_items_in_cart
# Varnish VCL alternativa (se usi Varnish davanti a nginx)
sub vcl_recv {
# Non cachare mai cart e checkout
if (req.url ~ "^/(cart|checkout|my-account)") {
return (pass);
}
# Cache search per 5 minuti se non loggato
if (req.url ~ "\?s=" && !req.http.Cookie ~ "wordpress_logged_in") {
unset req.http.Cookie;
return (hash);
}
}
Livello 2 — WAF rules specifiche per pattern sospetti
Cloudflare WAF o AWS WAF permettono regole mirate. Ecco 5 regole pronte all'uso per WooCommerce:
# Cloudflare WAF Custom Rules (Dashboard → Security → WAF → Custom Rules)
# Regola 1: Blocca POST a wp-login.php senza referer interno
(http.request.uri.path eq "/wp-login.php" and http.request.method eq "POST" and not cf.client.referer contains "tuosito.it")
Action: Challenge (Managed)
# Regola 2: Blocca richieste a /cart/ con user agent bot noto
(http.request.uri.path eq "/cart/" and cf.client.bot) or
(http.request.uri.path eq "/cart/" and http.user_agent contains "GPTBot" or http.user_agent contains "ClaudeBot" or http.user_agent contains "PerplexityBot")
Action: Block
# Regola 3: Rate limit su /?add-to-cart= (max 10/min per IP)
(http.request.uri.query contains "add-to-cart")
Rate limit: 10 requests / 60 seconds / IP
Action: Challenge
# Regola 4: Rate limit su /checkout/ (max 5/min per IP)
(http.request.uri.path eq "/checkout/" and http.request.method eq "POST")
Rate limit: 5 requests / 60 seconds / IP
Action: Block (soft = JS challenge)
# Regola 5: Blocca user agent senza browser identity
(http.user_agent eq "" or http.user_agent contains "Python" or http.user_agent contains "curl" or http.user_agent contains "wget")
And not ip.src in {<IP ammessi per monitoring interni>}
Action: JS Challenge
Livello 3 — PHP guard con priorità alta su init
Per i bot che sfuggono al WAF (user agent spoofato, IP distribuiti), serve un guard a livello applicativo. Ecco un'implementazione robusta in functions.php del tema o in un plugin custom:
<?php
/**
* Bot Guard per endpoint dinamici WooCommerce
* Plugin: mrtux-bot-guard
*/
add_action( 'init', 'mrtux_bot_guard_init', 1 );
function mrtux_bot_guard_init() {
// Non applicare a utenti loggati admin
if ( current_user_can( 'manage_options' ) ) {
return;
}
$request_uri = $_SERVER['REQUEST_URI'] ?? '';
$user_agent = strtolower( $_SERVER['HTTP_USER_AGENT'] ?? '' );
$ip = $_SERVER['REMOTE_ADDR'] ?? '';
// Lista bot AI noti da rifiutare su endpoint dinamici
$ai_bots = array(
'gptbot', 'chatgpt-user', 'oai-searchbot', 'claudebot',
'perplexitybot', 'perplexity-user', 'google-extended',
'ccbot', 'applebot-extended', 'amazonbot', 'meta-externalagent',
);
$is_ai_bot = false;
foreach ( $ai_bots as $bot ) {
if ( strpos( $user_agent, $bot ) !== false ) {
$is_ai_bot = true;
break;
}
}
// Blocca AI bot su endpoint dinamici (non sulla homepage)
$dynamic_patterns = array( '/cart/', '/checkout/', '/my-account/', '/?add-to-cart=', '/?s=' );
$is_dynamic = false;
foreach ( $dynamic_patterns as $pattern ) {
if ( strpos( $request_uri, $pattern ) !== false ) {
$is_dynamic = true;
break;
}
}
if ( $is_ai_bot && $is_dynamic ) {
// Log per analisi
error_log( sprintf(
'mrtux-bot-guard: blocked %s on %s from %s',
$user_agent, $request_uri, $ip
) );
// Risposta 403 con messaggio
status_header( 403 );
nocache_headers();
wp_die(
'AI bot access to dynamic endpoints is restricted. Please use static URLs only.',
'Access Denied',
array( 'response' => 403 )
);
exit;
}
// Rate limit applicativo su /?add-to-cart= (anti inventory hoarding)
if ( strpos( $request_uri, 'add-to-cart=' ) !== false ) {
mrtux_check_rate_limit( $ip, 'add_to_cart', 10, 60 );
}
// Rate limit applicativo su /checkout/ POST (anti card testing)
if ( strpos( $request_uri, '/checkout' ) !== false && $_SERVER['REQUEST_METHOD'] === 'POST' ) {
mrtux_check_rate_limit( $ip, 'checkout_post', 5, 60 );
}
}
function mrtux_check_rate_limit( $ip, $action, $limit, $window_seconds ) {
$key = "mrtux_rl_{$action}_{$ip}";
$count = get_transient( $key );
if ( $count === false ) {
set_transient( $key, 1, $window_seconds );
return;
}
if ( $count >= $limit ) {
status_header( 429 );
nocache_headers();
wp_die( 'Too many requests. Please slow down.', 'Rate Limited', array( 'response' => 429 ) );
exit;
}
set_transient( $key, $count + 1, $window_seconds );
}
Livello 4 — Cleanup transient orfani per ridurre il carico DB
Anche con protezione attiva, il danno pregresso va sanato. Script di cleanup da eseguire via WP-CLI ogni settimana:
#!/bin/bash
# cleanup_transients.sh - esegui settimanalmente via wp-cron
# Pulizia carrelli abbandonati più vecchi di 7 giorni
wp transient delete --expired --allow-root
# Pulizia specifica transient WC orfani
wp db query "DELETE FROM wp_options WHERE option_name LIKE '_transient_wc_cart_%' AND option_name NOT LIKE '%_timeout%'" --allow-root
# Pulizia sessioni WC più vecchie di 24h
wp db query "DELETE FROM wp_options WHERE option_name LIKE '_wc_session_%' AND option_name NOT LIKE '%_timeout%' AND autoload = 'no'" --allow-root
# Statistiche post-cleanup
wp db query "SELECT COUNT(*) as total_transients FROM wp_options WHERE option_name LIKE '_transient_%'" --allow-root
Architettura completa: dal CDN all'application server
Una protezione efficace richiede coordinazione tra layer. Ecco lo stack raccomandato per un WooCommerce medio (5.000-50.000 ordini/mese).
Stack tipo
- CDN/Edge: Cloudflare Pro o Business (WAF incluso) o Fastly (VCL configurabile)
- Reverse proxy: Nginx con microcaching (opzionale, intermedio)
- Application: PHP-FPM 8.2+ con OPCache abilitato, OPcache.validate_timestamps=0 in produzione
- Database: MySQL 8.0 con Redis per object cache (transient, sessioni WC)
- Monitoring: Kinsta APM, New Relic o un self-hosted come Tideways
Confronto rapido: protezione per profilo di sito
| Profilo | Volume | Bot protection | Edge cache | WAF | Application guard | Redis |
|---|---|---|---|---|---|---|
| Blog piccolo | <10k req/gg | robots.txt | Base | Free | No | No |
| WooCommerce medio | 10k-100k req/gg | Bot Protection AI | Differenziato | Pro | Sì | Sì |
| E-commerce enterprise | >100k req/gg | Custom ML rules | Varnish | Custom | Avanzato | Cluster Redis |
Stack consigliato per WooCommerce medio
| Layer | Tool | Costo/mese | Note |
|---|---|---|---|
| Edge | Cloudflare Pro | 20€ | WAF + Bot Protection inclusi |
| Cache | Cloudflare APO | 5€ aggiuntivi | Cache HTML per pagine statiche |
| Object cache | Redis su hosting | 15-30€ | Transients + sessioni WC |
| Monitoring | Query Monitor + log | 0€ | Debug locale |
Caso studio reale: WooCommerce con 12.000 SKU
Un cliente reale (negozio B2B con 12.000 SKU, 30.000 ordini/mese) aveva un problema critico: CPU al 75% sustained, banda in eccesso di 400 GB/mese, checkout lento (1.8 secondi medi). Audit iniziale: il 65% del traffico era bot AI.
Diagnosi
# Analisi log per user agent (top 20 bot)
awk -F'"' '{print $6}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
Risultato: GPTBot 38%, ClaudeBot 17%, AhrefsBot 14%, PerplexityBot 9%, altri bot SEO 22%.
Intervento applicato
- Blocco AI bot su
/cart/,/checkout/,/my-account/(livello 3 PHP guard) - Cache Cloudflare differenziata per pattern URL (livello 1)
- WAF rules su 5 pattern sospetti (livello 2)
- Redis per object cache (sostituzione transients)
- Cleanup transient orfani schedulato (livello 4)
Risultati a 30 giorni
| Metrica | Prima | Dopo | Delta |
|---|---|---|---|
| CPU sustained | 75% | 25% | -67% |
| Banda mensile | 1.2 TB | 720 GB | -40% |
| Tempo checkout | 1.8s | 0.9s | -50% |
| Ordini reali | 30.000 | 31.500 | +5% (bot rimossi facevano concorrenza a utenti reali) |
| Costo hosting | 850€/mese | 510€/mese | -340€/mese |
Configurazione PHP-FPM ottimizzata per WooCommerce con bot
Un aspetto spesso sottovalutato: il worker pool di PHP-FPM va dimensionato sul traffico REALE, non sul traffico totale. Con bot filtrati al 65%, il dimensionamento cambia radicalmente.
; /etc/php/8.2/fpm/pool.d/woocommerce.conf
[woocommerce]
user = www-data
group = www-data
listen = /run/php/php8.2-fpm-woocommerce.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 50 ; 50 worker processi (era 120 prima)
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 500 ; ricicla ogni 500 richieste per memory leak
; Timeout aggressivi perché bot timeout-spam non deve bloccare worker
request_terminate_timeout = 15s
; Slow log per identificare bottleneck
slowlog = /var/log/php-fpm-woocommerce-slow.log
request_slowlog_timeout = 3s
Monitoring: cosa misurare e come
Tre sono i KPI critici da tracciare nel tempo per capire se la protezione funziona.
KPI 1 — Rapporto bot/totale per endpoint
# Conta richieste bot per endpoint specifico
awk -F'"' '/cart\// {print $6}' /var/log/nginx/access.log | \
grep -iE 'bot|crawl|spider' | wc -l
awk '/cart\//' /var/log/nginx/access.log | wc -l
Target: bot/totale < 10% su /cart/, /checkout/, /my-account/.
KPI 2 — Tempo medio di risposta per endpoint
Tracciare con Kinsta APM, New Relic o NGINX Plus. Target: P95 < 500ms su /cart/, P95 < 800ms su /checkout/.
KPI 3 — Tasso di conversione per sessione
Se il tasso di conversione reale sale dopo l'intervento, i bot stavano effettivamente interferendo con utenti reali (es. esaurendo stock, sovraccaricando server).
Errori da evitare
- Bloccare TUTTI i bot AI indiscriminatamente: ti tagli fuori da AEO/GEO. Blocca solo su endpoint dinamici specifici, non su tutto il sito
- Affidarsi solo a robots.txt: i bot malevoli lo ignorano. Serve difesa multi-layer
- Ignorare i transient orfani: degradano performance anche con bot bloccati
- Dimensionare PHP-FPM sul traffico totale: senza separare bot da umani, spendi risorse in worker inutili
- Non loggare le decisioni del guard: senza log non puoi distinguere falsi positivi da attacchi reali
FAQ
I bot AI rispettano robots.txt?
I bot AI noti (GPTBot, ClaudeBot, PerplexityBot, Google-Extended) rispettano robots.txt, ma con sfumature. Google-Extended ad esempio permette di disabilitare l'uso per AI training mantenendo l'indicizzazione per AI Overviews. Vedi il nostro articolo dedicato per la configurazione completa.
Conviene bloccare i bot su /cart/ e /checkout/ o lasciarli indicizzare?
Bloccare. Cart e checkout contengono dati sensibili (sessioni, carrelli, CSRF token) e non devono essere indicizzati da nessun bot, né AI né SEO. Nessun motore di ricerca serio tenta di indicizzare /checkout/ perché riconosce la natura dinamica.
Come distinguo bot AI da bot SEO legittimi?
Verifica il user agent contro le liste ufficiali: GPTBot, ClaudeBot, PerplexityBot, Google-Extended, CCBot sono AI bot. Googlebot, Bingbot, DuckDuckBot sono SEO bot. I SEO bot tradizionali non hanno motivo di colpire /cart/ o /checkout/. Vedi il caso studio WooCommerce per numeri specifici.
Redis è obbligatorio per WooCommerce con bot?
Non obbligatorio ma fortemente consigliato se superi i 5.000 ordini/mese o se hai più di 30 plugin attivi. Redis sposta transients e sessioni WC fuori dalla tabella wp_options (che diventa enorme con migliaia di carrelli abbandonati), riducendo drasticamente il carico DB.
Cloudflare Bot Protection vale i 20€/mese Pro?
Sì, per qualsiasi WooCommerce con traffico > 50k req/mese. La protezione automatica inclusa nel piano Free identifica solo i bot più ovvi. Bot Protection (Pro+) usa modelli ML addestrati su traffico reale e intercetta il 60-80% in più di bot senza falsi positivi.
Devo applicare la stessa protezione anche su /?s= (search)?
Sì, ma con regole diverse. Search è cachable se l'utente non è loggato. Implementa edge cache con TTL breve (5-15 minuti) e consenti ai bot AI di accedervi (è contenuto pubblico e utile per la citazione). Blocca invece i bot SEO spam che generano migliaia di URL ?s=keyword-spam.
Come gestisco i falsi positivi sui clienti che usano headless browser?
Whitelist per IP noti o per user agent custom. Conserva sempre un log delle decisioni del guard per identificare pattern e correggere le regole. Una buona pratica è iniziare con azioni "Challenge" (JS challenge) invece di "Block" duro per i primi 30 giorni, analizzare i log, poi passare a "Block" per le sorgenti chiaramente bot.
Conclusione operativa: il piano d'azione in 7 giorni
Gli endpoint dinamici WooCommerce sono il vero fronte caldo del 2026. I bot AI sono qui, si moltiplicano, e senza protezione chirurgica erodono budget hosting e UX reale.
In 7 giorni puoi mettere in sicurezza il tuo store:
- Giorno 1-2: audit log per identificare i bot attivi e i pattern URL
- Giorno 3: edge caching differenziato su Cloudflare
- Giorno 4: WAF rules su 5 pattern critici
- Giorno 5: PHP guard con priorità alta
- Giorno 6: cleanup transient orfani + setup Redis
- Giorno 7: monitoring KPI + tuning PHP-FPM
L'obiettivo non è bloccare tutto: è dare priorità al traffico umano che converte. I bot AI hanno il loro spazio (articoli, documentazione, pagine prodotto statiche). Cart e checkout sono territorio umano.
Riferimenti utili per approfondire
- AI bot traffic WordPress: gestire GPTBot, ClaudeBot e crawler AI nel 2026 - panoramica gestione bot AI
- WooCommerce sotto attacco bot AI: proteggere il checkout - caso studio specifico WooCommerce
- Container Docker per PHP: setup minimale per sviluppare in locale - ambiente dev PHP ottimizzato
- Kinsta - Why dynamic endpoints are the most expensive part of bot traffic - articolo fonte Kinsta 2026-06-04
- Kinsta - How to reduce bandwidth waste without blocking legitimate users - guida pratica riduzione banda
- Cloudflare WAF Custom Rules documentation - documentazione WAF Cloudflare
- Cloudflare Bot Solutions - panoramica prodotti bot management
- WooCommerce - High Performance Order Storage (HPOS) - guida HPOS per WooCommerce
- WordPress Transients API documentation - API transients ufficiale
- OWASP - Credential Stuffing Prevention - linee guida sicurezza OWASP
- Nginx microcaching guide - microcaching con Nginx
- Varnish VCL documentation - documentazione Varnish VCL




Lascia un commento