AutomationFlowsMarketing & Ads › Pinapp — Diagnostic Lead Pipeline

Pinapp — Diagnostic Lead Pipeline

Pinapp — Diagnostic Lead Pipeline. Uses notion, gmail, httpRequest. Webhook trigger; 10 nodes.

Webhook trigger★★★★☆ complexity10 nodesNotionGmailHTTP Request
Marketing & Ads Trigger: Webhook Nodes: 10 Complexity: ★★★★☆ Added:

This workflow follows the Gmail → HTTP Request recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "Pinapp \u2014 Diagnostic Lead Pipeline",
  "meta": {
    "description": "Importer dans n8n Cloud. Webhook POST JSON (formulaire pinapp.fr). Variables : NOTION_DB_LEADS_ID, SLACK_WEBHOOK_URL. Credentials : Notion OAuth2, Gmail (ou SMTP). Apr\u00e8s activation, coller l\u2019URL webhook dans index.html (PINAPP_WEBHOOK_URL)."
  },
  "nodes": [
    {
      "id": "wh-diag",
      "name": "Webhook Diagnostic",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        240,
        300
      ],
      "parameters": {
        "httpMethod": "POST",
        "path": "pinapp-diagnostic",
        "responseMode": "responseNode",
        "options": {}
      }
    },
    {
      "id": "code-validate",
      "name": "Validate & Score",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        480,
        300
      ],
      "parameters": {
        "jsCode": "const item = $input.first().json;\nconst data = item.body && typeof item.body === 'object' ? item.body : item;\n\nif (data.website && String(data.website).trim() !== '') {\n  return [{ json: { _phase: 'spam', _received_at: new Date().toISOString() } }];\n}\n\nconst required = ['prenom', 'nom', 'email', 'secteur', 'budget', 'description', 'rgpd'];\nconst missing = required.filter((f) => !data[f] || (typeof data[f] === 'string' && !String(data[f]).trim()));\nif (missing.length) {\n  return [{ json: { _phase: 'invalid', _error: 'missing_fields', _missing: missing } }];\n}\n\nconst email = String(data.email || '');\nif (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email)) {\n  return [{ json: { _phase: 'invalid', _error: 'invalid_email' } }];\n}\n\nconst projets = Array.isArray(data.projet) ? data.projet : data.projet ? [data.projet] : [];\nif (!projets.length) {\n  return [{ json: { _phase: 'invalid', _error: 'missing_projet' } }];\n}\n\nlet score = 0;\nconst budget = String(data.budget || '');\nif (/gt25k/.test(budget)) score += 40;\nelse if (/10k-25k/.test(budget)) score += 30;\nelse if (/5k-10k/.test(budget)) score += 20;\nelse if (/2k-5k/.test(budget)) score += 10;\n\nif (data.urgence === 'asap') score += 25;\nelse if (data.urgence === '1-3m') score += 15;\nelse if (data.urgence === '3-6m') score += 5;\n\nif (projets.length >= 3) score += 25;\nelse if (projets.length === 2) score += 15;\nelse if (projets.length === 1) score += 5;\n\nif (data.description && String(data.description).length > 300) score += 10;\nif (data.entreprise) score += 5;\nif (data.telephone) score += 5;\nif (data.site_actuel) score += 5;\n\nlet tier = 'cold';\nif (score >= 75) tier = 'hot';\nelse if (score >= 45) tier = 'warm';\n\nconst slackEmoji = tier === 'hot' ? '\ud83d\udd25' : tier === 'warm' ? '\u26a1' : '\u2744\ufe0f';\n\nconst payload = {\n  ...data,\n  projet: projets,\n  _phase: 'lead',\n  _server_score: score,\n  _tier: tier,\n  _projets_str: projets.join(', '),\n  _received_at: new Date().toISOString(),\n  _slack_emoji: slackEmoji,\n};\n\nreturn [{ json: payload }];"
      }
    },
    {
      "id": "if-spam",
      "name": "Is spam?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        720,
        300
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "spam",
              "leftValue": "={{ $json._phase }}",
              "rightValue": "spam",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        }
      }
    },
    {
      "id": "if-invalid",
      "name": "Is invalid?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        960,
        420
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "inv",
              "leftValue": "={{ $json._phase }}",
              "rightValue": "invalid",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        }
      }
    },
    {
      "id": "notion-lead",
      "name": "Create Notion Lead",
      "type": "n8n-nodes-base.notion",
      "typeVersion": 2,
      "position": [
        1180,
        200
      ],
      "parameters": {
        "resource": "databasePage",
        "operation": "create",
        "databaseId": "={{ $env.NOTION_DB_LEADS_ID }}",
        "title": "={{ $json.prenom }} {{ $json.nom }} \u2014 {{ $json.secteur }}",
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Email|email",
              "emailValue": "={{ $json.email }}"
            },
            {
              "key": "T\u00e9l\u00e9phone|phone_number",
              "phoneValue": "={{ $json.telephone || '' }}"
            },
            {
              "key": "Entreprise|rich_text",
              "textContent": "={{ $json.entreprise || '' }}"
            },
            {
              "key": "Secteur|select",
              "selectValue": "={{ $json.secteur }}"
            },
            {
              "key": "Projets|multi_select",
              "multiSelectValue": "={{ $json._projets_str }}"
            },
            {
              "key": "Budget|select",
              "selectValue": "={{ $json.budget }}"
            },
            {
              "key": "Urgence|select",
              "selectValue": "={{ $json.urgence || 'non-precise' }}"
            },
            {
              "key": "Score|number",
              "numberValue": "={{ $json._server_score }}"
            },
            {
              "key": "Tier|select",
              "selectValue": "={{ $json._tier }}"
            },
            {
              "key": "Source|select",
              "selectValue": "={{ $json.source || 'non-precise' }}"
            },
            {
              "key": "Description|rich_text",
              "textContent": "={{ $json.description }}"
            },
            {
              "key": "Statut|select",
              "selectValue": "Nouveau"
            }
          ]
        },
        "options": {}
      },
      "notesInFlow": true,
      "notes": "Mapper les propertyValues aux noms/types exacts de la base Notion (voir docs/LEAD_FLOW.md)."
    },
    {
      "id": "gmail-confirm",
      "name": "Email confirmation prospect",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 1,
      "position": [
        1400,
        200
      ],
      "parameters": {
        "operation": "send",
        "toList": "={{ $('Validate & Score').item.json.email }}",
        "subject": "=Bien re\u00e7u, {{ $('Validate & Score').item.json.prenom }} \u2014 on revient sous 24h \u00b7 Pinapp",
        "message": "=Bonjour {{ $('Validate & Score').item.json.prenom }},\n\nNous avons bien re\u00e7u votre demande. Nous revenons vers vous sous 24h ouvr\u00e9es \u00e0 {{ $('Validate & Score').item.json.email }}.\n\nR\u00e9cap : secteur {{ $('Validate & Score').item.json.secteur }} \u00b7 projets {{ $('Validate & Score').item.json._projets_str }} \u00b7 budget {{ $('Validate & Score').item.json.budget }}.\n\nEn attendant : https://pinapp.fr/realisations/ et https://pinapp.fr/#formations\n\nLauralie & Micha\u00ebl \u2014 Pinapp\ncontact@pinapp.fr"
      }
    },
    {
      "id": "http-slack",
      "name": "Slack Notif",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4,
      "position": [
        1620,
        200
      ],
      "parameters": {
        "method": "POST",
        "url": "={{ $env.SLACK_WEBHOOK_URL }}",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ text: $('Validate & Score').item.json._slack_emoji + ' Nouveau lead Pinapp \u2014 ' + $('Validate & Score').item.json._tier + ' (' + $('Validate & Score').item.json._server_score + '/100)\\n' + $('Validate & Score').item.json.prenom + ' ' + $('Validate & Score').item.json.nom + ' \u00b7 ' + $('Validate & Score').item.json.email }) }}",
        "options": {
          "timeout": 10000
        }
      }
    },
    {
      "id": "resp-ok",
      "name": "Webhook OK",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        1840,
        200
      ],
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ success: true, message: 'Re\u00e7u, on revient sous 24h', reference: $('Validate & Score').item.json._received_at }) }}"
      }
    },
    {
      "id": "resp-spam",
      "name": "Webhook OK silent",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        960,
        120
      ],
      "parameters": {
        "respondWith": "json",
        "responseBody": "={\"success\":true,\"message\":\"Re\u00e7u\"}"
      }
    },
    {
      "id": "resp-err",
      "name": "Webhook Error",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        1180,
        520
      ],
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ success: false, error: $json._error || 'invalid_data' }) }}",
        "options": {
          "responseCode": 400
        }
      }
    }
  ],
  "connections": {
    "Webhook Diagnostic": {
      "main": [
        [
          {
            "node": "Validate & Score",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate & Score": {
      "main": [
        [
          {
            "node": "Is spam?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is spam?": {
      "main": [
        [
          {
            "node": "Webhook OK silent",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Is invalid?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is invalid?": {
      "main": [
        [
          {
            "node": "Webhook Error",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create Notion Lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Notion Lead": {
      "main": [
        [
          {
            "node": "Email confirmation prospect",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Email confirmation prospect": {
      "main": [
        [
          {
            "node": "Slack Notif",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack Notif": {
      "main": [
        [
          {
            "node": "Webhook OK",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Pinapp — Diagnostic Lead Pipeline. Uses notion, gmail, httpRequest. Webhook trigger; 10 nodes.

Source: https://github.com/lauraliedaguzay-lang/pinapp-site/blob/572daf3ea3ae48e0b147a5156f120d5e42b6255b/n8n-workflows/diagnostic-pinapp.json — original creator credit. Request a take-down →

More Marketing & Ads workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Marketing & Ads

This workflow automates bulk email campaigns with built-in validation, deliverability protection, and smart send-time optimization.

HTTP Request, Postgres, Gmail
Marketing & Ads

This workflow acts as an instant SDR that replies to new inbound leads across multiple channels in real time. It first captures and normalizes all incoming lead data into a unified structure. The work

Google Sheets, HTTP Request, Gmail +1
Marketing & Ads

A comprehensive n8n workflow template for streamlining influencer application processing with real-time social media data validation, intelligent scoring algorithms, and automated onboarding workflows

N8N Nodes Verifiemail, Stop And Error, HTTP Request +2
Marketing & Ads

Cana V2 Lead Processor. Uses httpRequest, gmail, dataTable. Webhook trigger; 20 nodes.

HTTP Request, Gmail, Data Table
Marketing & Ads

AI Lead Qualification & Follow-Up. Uses httpRequest, slack, googleSheets, gmail. Webhook trigger; 18 nodes.

HTTP Request, Slack, Google Sheets +2