Il modo più rapido per individuare sconti reali e opportunità di pricing? Automatizzare il monitoraggio con uno scraper prezzi n8n che raccoglie listini da più store, pulisce e normalizza i dati, li archivia in uno storico e invia notifiche quando il prezzo cambia davvero. In questa guida costruisci un flusso completo: scheduler (Cron), raccolta con richieste HTTP e gestione cookie, parsing HTML/JSON, salvataggio dello storico, confronto con l’ultimo valore, regole di alert con soglie e cooldown, deduplicazione del rumore e digest giornalieri su Slack. Il risultato è un sistema robusto per monitoraggio prezzi e‑commerce con automazione che supporta casi pratici come vigilanza competitor, dynamic pricing, affiliate e content commerce. Troverai esempi di nodi, configurazioni e snippet pronti da incollare, oltre a best practice su anti‑bot e riduzione del rumore.

📚 Nuovo a n8n? Parti dalla guida completa: cos'è n8n e come funziona.

Architettura e modello dati: dal target alla notifica

Prima di toccare i nodi, chiarisci il perimetro. Cosa vuoi monitorare? SKU strategici, top seller, competitor diretti? Con una base chiara, il tracciamento variazioni di prezzo con flussi n8n diventa prevedibile e misurabile.

  • Pipeline logica: Scheduler → Raccolta → Parsing/Normalizzazione → Persistenza storico → Confronto ultimo prezzo → Regole/Severità → Notifica → Log.
  • KPI minimi: delta assoluto/percentuale, frequenza update, coverage (quanti prodotti × quanti store), tasso di falsi positivi (rumore).

Modello dati essenziale (per tabella “prices_history”)

  • product_id: ID interno o SKU.
  • store: dominio o etichetta dello store.
  • currency: ISO (es. EUR, USD).
  • price: numero decimale (2‑4 decimali).
  • timestamp: ISO o epoch.
  • selector_hash: hash del selettore usato (CSS/XPath) per tracciabilità.
  • url: URL della pagina prodotto.

Strategie di confronto

  • Ultima osservazione: confronta il prezzo attuale con l’ultimo rilevato per lo stesso product_id+store.
  • Rolling window: mediana/percentile delle ultime N osservazioni per attenuare outlier.
  • Regole: soglie su ±X% o valore assoluto; escalazione se il calo supera limiti anomali (es. >25%).

Insight operativo: separa “prodotti critici” (più frequenti, soglie strette) da “long tail” (frequenza minore, soglie più ampie) per ridurre costi e rumore.


Scheduler e raccolta: Cron + HTTP Request con header e fallback

Usa un Cron per lanciare il flusso alla frequenza desiderata (es. ogni ora per i top seller, ogni 6‑12 ore per la long tail). Poi esegui richieste con HTTP Request. Preferisci API/endpoint JSON quando disponibili; in alternativa, esegui scraping HTML con parsing personalizzato.

Esempio HTTP Request (GET JSON)

{
  "name": "Fetch Product JSON",
  "type": "n8n-nodes-base.httpRequest",
  "typeVersion": 1,
  "parameters": {
    "url": "https://api.example.com/products/{{$json.sku}}/price",
    "method": "GET",
    "responseFormat": "json",
    "queryParametersUi": {
      "parameter": [
        { "name": "currency", "value": "EUR" }
      ]
    },
    "continueOnFail": true
  }
}

Consigli pratici

  • Headers: imposta user‑agent, accept‑language e cache‑control per migliorare compatibilità. Se lo store blocca richieste senza header standard, usa HTTP Request con header personalizzati.
  • Gestione cookie/sessione: salva cookie da una prima chiamata (login o consenso) e riutilizzali nelle successive (supporta parametri header/cookie). Per sessioni complesse valuta integrazione con attori esterni di scraping via API.
  • Rate/Retry: con Split In Batches limita il batchSize per rispettare limiti. Imposta continueOnFail a true per non bloccare e instrada gli errori su rami di gestione.

Schedulazione

  • Fraziona i lanci nel tempo (SKU ad alta priorità più frequenti). Evita che tutti i target girino allo stesso minuto per ridurre carico e anti‑bot.

Parsing e normalizzazione: da HTML/JSON al numero affidabile

Quando hai JSON, leggi direttamente il campo prezzo. Con HTML, usa un Code node per estrarre e pulire il valore. Mantieni selettori CSS/XPath stabili e versiona i cambi; in assenza di un estrattore dedicato, il parsing testuale controllato è spesso sufficiente.

Parsing prezzo da JSON (Code)

// Input: { json: { data: { price: "€1.299,00", currency: "EUR" }, url, store, product_id } }
function toNumber(str) {
  if (!str) return null;
  const cleaned = str.replace(/[^\d,.\-]/g, '')
                     .replace(/\.(?=\d{3}\b)/g, '')
                     .replace(',', '.');
  const n = parseFloat(cleaned);
  return Number.isFinite(n) ? n : null;
}
const price = toNumber($json.data.price);
return [{ json: { ...$json, price, currency: $json.data.currency || 'EUR' } }];

Parsing HTML (Code, regex mirato al selettore noto)

// Input: { json: { html, url, store, product_id } }
const html = $json.html || '';
// Esempio: cerca contenuto in <span id="price">€1.299,00</span>
const m = html.match(/<span[^>]*id=["']price["'][^>]*>([^<]+)<\/span>/i);
const raw = m ? m[1].trim() : null;
function toNumber(str) {
  if (!str) return null;
  const cleaned = str.replace(/[^\d,.\-]/g, '')
                     .replace(/\.(?=\d{3}\b)/g, '')
                     .replace(',', '.');
  const n = parseFloat(cleaned);
  return Number.isFinite(n) ? n : null;
}
const price = toNumber(raw);
return [{ json: { ...$json, price, currency: 'EUR', selector_hash: 'id:price' } }];

Normalizzazione e conversione valuta (facoltativa)

// Input: { json: { price, currency } }  — esempio FX statico
const fx = { EUR: 1, USD: 0.93, GBP: 1.16 };
const target = 'EUR';
const rate = fx[$json.currency] || 1;
const price_eur = Math.round(($json.price * rate) * 100) / 100;
return [{ json: { ...$json, price_eur, currency: target } }];

Best practice

  • Deduplicazione: se ricevi più letture ravvicinate, mantieni l’ultima valida per finestra (es. 10 minuti).
  • Tracciabilità: salva selector_hash per capire quando cambiano i selettori.

Storico e confronto: salva, riprendi, calcola delta

Per confronto storico dei prezzi prodotti, scrivi l’osservazione odierna e carica l’ultima disponibile. Puoi usare un database relazionale. Con i nodi DB esegui SELECT/INSERT via query parameterizzate.

Esempio SELECT ultimo prezzo (query parametro da item)

{
  "name": "Get Last Price",
  "type": "n8n-nodes-base.mySql",
  "typeVersion": 1,
  "parameters": {
    "operation": "executeQuery",
    "query": "SELECT price, currency, timestamp FROM prices_history WHERE product_id = {{ $json.product_id }} AND store = {{ $json.store }} ORDER BY timestamp DESC LIMIT 1"
  }
}

Esempio INSERT nuova osservazione

{
  "name": "Insert Price",
  "type": "n8n-nodes-base.mySql",
  "typeVersion": 1,
  "parameters": {
    "operation": "executeQuery",
    "query": "INSERT INTO prices_history (product_id, store, currency, price, url, selector_hash, timestamp) VALUES ({{ $json.product_id }}, {{ $json.store }}, {{ $json.currency }}, {{ $json.price }}, {{ $json.url }}, {{ $json.selector_hash }}, NOW())"
  }
}

Merge per confronto (unisci “corrente” e “storico” per product_id)

{
  "name": "Merge Current vs Last",
  "type": "n8n-nodes-base.merge",
  "typeVersion": 1,
  "parameters": {
    "mode": "mergeByKey",
    "propertyName": "product_id",
    "outputDataFrom": "both"
  }
}

Calcolo delta in Code

// Input: item con current.price e last.price
const current = $json.current_price;
const last = $json.last_price;
const delta = current - last;
const deltaPct = last ? (delta / last) * 100 : null;
return [{ json: { ...$json, delta, deltaPct: deltaPct !== null ? Math.round(deltaPct * 100) / 100 : null } }];

Suggerimenti

  • Se usi più store, includi store nella chiave di merge.
  • Gestisci outlier: ignora variazioni impossibili (es. >70% senza input promozioni).

Regole di alert e riduzione del rumore: soglie, cooldown, digest

Definisci regole chiare per regole di alert su calo prezzo evitando notifiche eccessive.

If (soglia percentuale)

{
  "name": "Is Price Drop > 10%",
  "type": "n8n-nodes-base.if",
  "typeVersion": 2,
  "parameters": {
    "conditions": {
      "conditions": [
        {
          "leftValue": "={{ $json.deltaPct }}",
          "rightValue": "-10",
          "operator": { "type": "number", "operation": "smaller" }
        }
      ],
      "combinator": "and"
    }
  }
}

Riduzione rumore

  • Cooldown per prodotto/store (es. max 1 alert/24h): memorizza l’ultimo alert in DB e filtra.
  • Raggruppamento/digest: aggrega tutte le variazioni significative e invia un unico messaggio a fine giornata.
  • Escalation: se il delta supera soglia alta (es. >25%), invia immediatamente un alert “critico”.

Esempio digest in Code (compatta una lista di cambi in un Markdown)

const lines = items.map(i => `- ${i.json.product_id} @ ${i.json.store}: ${i.json.last_price} → ${i.json.current_price} (${i.json.deltaPct}%)`);
return [{ json: { text: `Price drop digest:\n` + lines.join('\n') } }];

Notifiche: Slack e messaggi strutturati

Invia notifiche su canali di team (pricing/merchandising). Usa un testo conciso, link alla pagina e delta percentuale. Con notifiche su Slack/Email ottieni visibilità immediata senza seppellire il team di alert.

Slack (Send Message)

{
  "name": "Send Slack Message",
  "type": "n8n-nodes-base.slack",
  "typeVersion": 1,
  "parameters": {
    "resource": "message",
    "operation": "send",
    "channel": "C01234567",
    "text": "Price drop: {{$json.product_id}} @ {{$json.store}} da {{$json.last_price}} a {{$json.current_price}} ({{$json.deltaPct}}%). Link: {{$json.url}}"
  },
  "credentials": {
    "slackApi": { "name": "Slack OAuth2" }
  }
}

Consigli

  • Per digest: invia un solo messaggio con elenco puntato.
  • Per casi critici: messaggio dedicato con emoji/menzioni del team.

Anti‑bot e resilienza: header, batching, retry

Molti e‑commerce limitano scraping aggressivo. Minimizza rischi di blocco e garantisci stabilità.

  • Header realistici: imposta user‑agent e accept‑language; ruota user‑agent su elenchi noti.
  • Intervalli casuali e batching: usa Split In Batches per processare piccoli lotti (batchSize 5‑10). Evita picchi.
{
  "name": "Batch Loop",
  "type": "n8n-nodes-base.splitInBatches",
  "typeVersion": 1,
  "parameters": { "batchSize": 10 }
}
  • Retry mirati: su HTTP Request imposta continueOnFail: true e instrada gli errori su un ramo che riprova solo i prodotti falliti dopo un intervallo (via scheduling separato).
  • Cookie/sessione: dove serve login, ottieni cookie/headers con una prima chiamata e riusali per le successive.
  • Rispetto di robots.txt/ToS: valuta i limiti d’uso e considera soluzioni con attori esterni quando necessario.

Osservabilità

  • Logga errori transitori e finali (dead‑letter list) per capire quali store/selettori sono problematici.
  • Monitora error rate per store e regola batchSize/frequenza di conseguenza.

Qualità dati e controllo: deduplica, varianti, valute

Deduplicazione e controllo qualità sono essenziali per evitare falsi positivi.

  • Deduplica: se più URL puntano allo stesso SKU/variante, scegli la fonte principale e marca le altre come di supporto.
  • Varianti: per taglie/colore/bundle, assegna product_id varianti (es. SKU‑RED‑M) per differenziare prezzi.
  • Valute: normalizzazione e conversione valuta coerente (EUR come base).
  • Selettori: salva selector_hash; se il sito cambia markup, individui rapidamente cosa aggiornare.

Controlli automatici

  • Validità prezzo: scarta valori nulli, 0 non attesi, o delta estremo (probabile parsing errato).
  • Controllo formati: normalizza separatori migliaia/decimali (internazionale vs locale).
  • Audit: salva timestamp, URL, store, selector_hash, user‑agent per ricostruire l’estrazione.

Esempio di flusso completo: dal CSV di target al digest Slack

Scenario: hai un CSV con product_id, store, url, currency. Vuoi un digest giornaliero con i cali >10%.

  • Cron: ogni giorno alle 08:00.
  • HTTP Request: scarica CSV target o leggi da DB.
  • Split In Batches: batchSize 8.
  • HTTP Request (per item): tenta JSON API, altrimenti HTML page.
  • Code: parsing prezzo, normalizzazione valuta.
  • DB SELECT: ultimo prezzo per product_id+store.
  • Merge: unisci “corrente” e “ultimo”.
  • Code: delta/deltaPct e filtri qualità.
  • If: deltaPct < -10.
  • Aggrega “true” in lista; genera testo digest (Code).
  • Slack: invia digest al canale.

Vantaggi

  • Riduzione rumore grazie a soglia e digest.
  • Tracciabilità completa (storico + selector_hash).
  • Scalabilità via batching controllato.

Quick Takeaways

  • Progetta il modello dati (productid, store, currency, price, timestamp, selectorhash) prima del primo run.
  • Usa HTTP Request con header realistici e Split In Batches per ridurre blocchi anti‑bot.
  • Normalizza prezzi e valute con Code; salva storico e confronta con l’ultima osservazione.
  • Applica If con soglie percentuali e digest giornalieri per ridurre il rumore.
  • Invia notifiche strutturate su Slack, con link e delta; escalazione per cali anomali.
  • Monitora errori e selettori: aggiorna rapidamente quando gli store cambiano markup.

Conclusione

Uno scraper prezzi n8n ben progettato trasforma dati pubblici in insight azionabili per pricing, merchandising e content commerce. Con una pipeline che parte da Cron, raccoglie via HTTP, pulisce con Code, archivia lo storico e confronta l’ultimo prezzo, puoi impostare regole chiare e notifiche efficaci senza sommergere i team di alert inutili. La chiave è l’equilibrio: limiti al traffico (batching e frequenze), parsing affidabile e tracciabile (selector_hash, audit), regole con soglie sensate e digest per concentrare l’attenzione su eventi che contano. Inizia piccolo (pochi SKU strategici), misura il rumore, calibra soglie e frequenza, poi scala coverage e integrazioni. Così ottieni un sistema di monitoraggio prezzi e‑commerce con automazione che supporta decisioni quotidiane, anticipa il mercato e libera tempo ai marketer per le attività ad alto impatto.


FAQ

1) Come scelgo la frequenza di raccolta?
Dipende da volumi e priorità. Per i top seller usa schedulazione cron per raccolta dati ogni 1‑3 ore; per la long tail ogni 6‑24 ore. Aumenta la frequenza in periodi promozionali.

2) Come gestisco pagine con markup che cambia spesso?
Salva selector_hash e monitora aumenti di errori di parsing. Se un dominio cambia spesso, passa a selettori più robusti, aggiungi fallback e un test automatico che valida il selettore prima del run.

3) Come evitare notifiche eccessive?
Applica soglie (±X% o valore), cooldown per prodotto/store (un alert ogni 24h) e digest giornalieri. Raggruppa più variazioni in un solo messaggio su Slack.

4) Come tratto le valute?
Normalizza tutto verso una base (es. EUR). Applica conversione con tassi aggiornati e arrotondamento coerente. Conserva anche la valuta originale per audit.

5) Posso integrare servizi esterni di scraping?
Sì, tramite integrazione con attori di scraping esterni via API (chiamati con HTTP Request). Valuta costi, compatibilità anti‑bot e affidabilità; usa questi attori per store più complessi.


Ci dai una mano?

Qual è il primo prodotto o categoria che vuoi monitorare con lo scraper prezzi n8n? Condividi la tua idea e gira l’articolo al team: vediamo insieme come tarare soglie e digest per segnalazioni davvero utili!

Vuoi automazioni AI su misura per la tua azienda?
Scopri la consulenza →