{
  "name": "Contatti dal modulo del sito: valutazione e notifica",
  "nodes": [
    {
      "parameters": {
        "content": "## Contatti dal modulo del sito\nIl modulo del tuo sito invia i dati a questo workflow (webhook). Il contatto viene **valutato da 1 a 10**, ti arriva una notifica (con \"CALDO\" in oggetto sopra la soglia) e il cliente riceve una **conferma di ricezione**.\n\n**Collegamento al sito:** pubblica il workflow (*Publish*), poi copia la *Production URL* del nodo \"Modulo inviato\" e usala come `action` del modulo (metodo POST, campi `nome`, `email`, `telefono`, `messaggio`). Un campo nascosto `_gotcha` pieno viene trattato come spam.\n\nVuoi anche un registro? Aggiungi un nodo Google Sheets dopo \"Componi notifica\".\n\n**Credenziali da collegare dopo l'importazione**\n- **OpenAI** → nei nodi HTTP Request \"… con AI\": Header Auth con *Name* `Authorization` e *Value* `Bearer LA-TUA-CHIAVE`.\n- **Email (SMTP)** → nei nodi Send Email: l'account da cui partono i messaggi.\n\nPoi apri il nodo **Impostazioni** e cambia solo il blocco iniziale (email, attività, modello).\nFai una prova con *Execute workflow*, poi attivalo con *Publish* (in n8n 1.x: *Test workflow* e interruttore *Active*).",
        "width": 560,
        "height": 470,
        "color": 5
      },
      "id": "7520188b-9a19-5ac5-ac4c-0b3ef48edc1d",
      "name": "Leggimi",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        0,
        -290
      ]
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "nuovo-contatto",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "04cb3524-6608-59e5-8c51-38cbc67a449e",
      "name": "Modulo inviato",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        0,
        300
      ],
      "webhookId": "de985b6c-3751-5be9-b0a9-6e58fa94a3aa"
    },
    {
      "parameters": {
        "jsCode": "// ⚙️ IMPOSTAZIONI — modifica solo questo blocco\nconst cfg = {\n  model: 'gpt-4o-mini',\n  tuaEmail: 'tu@esempio.it',            // dove ricevi le notifiche\n  mittente: 'automazioni@esempio.it',   // indirizzo dell'account SMTP\n  attivita: 'studio di consulenza',     // la tua attività, in poche parole\n  sogliaCaldo: 7,                       // da 1 a 10: da qui in su il contatto è \"caldo\"\n  confermaAlCliente: true,              // false per non inviare la conferma al cliente\n  firma: 'Mario Rossi — Studio Rossi',\n};\nreturn $input.all().map(item => {\n  const b = item.json.body || item.json;   // il webhook mette i campi del modulo in \"body\"\n  const pick = (...keys) => { for (const k of keys) if (b[k]) return String(b[k]).trim(); return ''; };\n  const contatto = {\n    nome: pick('nome', 'name', 'Nome').slice(0, 120),\n    email: pick('email', 'Email', 'mail').slice(0, 200),\n    telefono: pick('telefono', 'phone', 'tel').slice(0, 40),\n    messaggio: pick('messaggio', 'message', 'testo', 'Messaggio').slice(0, 5000),\n  };\n  contatto.emailValida = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(contatto.email);\n  const spam = Boolean(b._gotcha) || (!contatto.messaggio && !contatto.email);\n  return { json: { contatto, spam, cfg, ricevuto: new Date().toISOString() } };\n});\n"
      },
      "id": "4ff0371a-a19a-508f-a4a1-54c8c5536440",
      "name": "Impostazioni e controllo",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        240,
        300
      ]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ ok: true }) }}",
        "options": {}
      },
      "id": "13fb73c8-78aa-5202-83c1-16d103720247",
      "name": "Rispondi al modulo",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        480,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "// gli invii marcati come spam si fermano qui\nreturn $input.all().filter(item => !item.json.spam).map(item => {\n  const { contatto: c, cfg } = item.json;\n  const istruzioni =\n    `Sei l'assistente commerciale di: ${cfg.attivita}. Valuta questo contatto arrivato dal sito. ` +\n    `Dai un punteggio intero da 1 (spam o fuori target) a 10 (richiesta chiara, concreta e urgente). ` +\n    `Rispondi solo con un oggetto JSON: {\"punteggio\": number, \"tipo\": string, \"motivo\": string (una frase), \"prossimoPasso\": string (una frase)}.`;\n  return { json: { ...item.json, body: {\n    model: cfg.model, temperature: 0.2, response_format: { type: 'json_object' },\n    messages: [\n      { role: 'system', content: istruzioni },\n      { role: 'user', content: `Nome: ${c.nome}\\nEmail: ${c.email}\\nTelefono: ${c.telefono}\\n\\n${c.messaggio}` },\n    ],\n  } } };\n});\n"
      },
      "id": "409b0658-1354-5c60-a985-c91dca52560d",
      "name": "Prepara richiesta AI",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        720,
        200
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.openai.com/v1/chat/completions",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify($json.body) }}",
        "options": {}
      },
      "id": "d6ed5100-c0b0-5b5d-a50c-992d5fc1b9e9",
      "name": "Valuta con AI",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        960,
        200
      ]
    },
    {
      "parameters": {
        "jsCode": "// Estrae il JSON dalla risposta di OpenAI; se non è valido restituisce `fallback`.\nfunction leggiAI(risposta, fallback) {\n  try { return JSON.parse(risposta.choices[0].message.content); } catch (e) { return fallback; }\n}\n\nconst origini = $('Prepara richiesta AI').all();\nreturn $input.all().map((item, i) => {\n  const { contatto: c, cfg, ricevuto } = origini[i].json;\n  const r = leggiAI(item.json, { punteggio: 0, tipo: 'Da verificare', motivo: 'Valutazione non riuscita.', prossimoPasso: '' });\n  const caldo = Number(r.punteggio) >= cfg.sogliaCaldo;\n  const oggetto = `${caldo ? '🔥 CALDO ' : ''}Nuovo contatto (${r.punteggio}/10): ${c.nome || c.email || 'senza nome'}`;\n  const testo = [\n    `Ricevuto: ${new Date(ricevuto).toLocaleString('it-IT')}`,\n    `Nome: ${c.nome}`, `Email: ${c.email}${c.emailValida ? '' : ' (non valida?)'}`, `Telefono: ${c.telefono}`, '',\n    `Punteggio: ${r.punteggio}/10 — ${r.tipo}`, `Motivo: ${r.motivo}`, `Prossimo passo: ${r.prossimoPasso}`, '',\n    '--- Messaggio ---', c.messaggio,\n  ].join('\\n');\n  return { json: { oggetto, testo, a: cfg.tuaEmail, da: cfg.mittente, punteggio: r.punteggio, contatto: c } };\n});\n"
      },
      "id": "a0e54220-afbb-5144-9880-44eb929997a6",
      "name": "Componi notifica",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1200,
        200
      ]
    },
    {
      "parameters": {
        "fromEmail": "={{ $json.da }}",
        "toEmail": "={{ $json.a }}",
        "subject": "={{ $json.oggetto }}",
        "emailFormat": "text",
        "text": "={{ $json.testo }}",
        "options": {}
      },
      "id": "b558f487-1207-5c06-a1a0-b735bf1274c0",
      "name": "Avvisa me",
      "type": "n8n-nodes-base.emailSend",
      "typeVersion": 2.1,
      "position": [
        1440,
        200
      ]
    },
    {
      "parameters": {
        "jsCode": "// conferma solo se attiva, con email valida e non spam\nreturn $input.all()\n  .filter(item => item.json.cfg.confermaAlCliente && !item.json.spam && item.json.contatto.emailValida)\n  .map(item => {\n    const { contatto: c, cfg } = item.json;\n    const testo = [\n      `Gentile ${c.nome || 'cliente'},`, '',\n      'grazie per averci scritto: abbiamo ricevuto il suo messaggio e le risponderemo al più presto.', '',\n      'Cordiali saluti,', cfg.firma,\n    ].join('\\n');\n    return { json: { oggetto: 'Abbiamo ricevuto il suo messaggio', testo, a: c.email, da: cfg.mittente } };\n  });\n"
      },
      "id": "7e622113-5e5e-5cf0-b2b2-9eafcb1f8000",
      "name": "Componi conferma",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        720,
        420
      ]
    },
    {
      "parameters": {
        "fromEmail": "={{ $json.da }}",
        "toEmail": "={{ $json.a }}",
        "subject": "={{ $json.oggetto }}",
        "emailFormat": "text",
        "text": "={{ $json.testo }}",
        "options": {}
      },
      "id": "81816b29-839b-545a-bf48-0baa20fdc882",
      "name": "Conferma al cliente",
      "type": "n8n-nodes-base.emailSend",
      "typeVersion": 2.1,
      "position": [
        960,
        420
      ]
    }
  ],
  "connections": {
    "Modulo inviato": {
      "main": [
        [
          {
            "node": "Impostazioni e controllo",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Impostazioni e controllo": {
      "main": [
        [
          {
            "node": "Rispondi al modulo",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Rispondi al modulo": {
      "main": [
        [
          {
            "node": "Prepara richiesta AI",
            "type": "main",
            "index": 0
          },
          {
            "node": "Componi conferma",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepara richiesta AI": {
      "main": [
        [
          {
            "node": "Valuta con AI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Valuta con AI": {
      "main": [
        [
          {
            "node": "Componi notifica",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Componi notifica": {
      "main": [
        [
          {
            "node": "Avvisa me",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Componi conferma": {
      "main": [
        [
          {
            "node": "Conferma al cliente",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {},
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "tags": []
}
