Skip to main content

Secure web form to Odoo CRM lead creation with UTM tracking

Workflow preview

Secure web form to Odoo CRM lead creation with UTM tracking preview
Open on n8n.io

Important notice

This workflow is provided as-is. Please review and test before using in production.

Overview

# Web-to-Odoo Lead Funnel (UTM-ready)

Create crm.lead records in Odoo from any webform via a secure webhook.
The workflow validates required fields, resolves UTMs by name (source, medium, campaign) and writes standard lead fields in Odoo. Clean, portable, and production-ready.

Key features

  • Secure Webhook with Header Auth (x-webhook-token)
  • Required fields validation (firstname, lastname, email)
  • UTM lookup by name (utm.source, utm.medium, utm.campaign)
  • Clean consolidation before create (name, contact_name, email_from, phone, description, type, UTM IDs)
  • Clear HTTP responses: 200 success / 400 bad request

Prerequisites

  • Odoo with Leads enabled (CRM → Settings → Leads)
  • Odoo API Key for your user (use it as the password)
  • n8n Odoo credentials: URL, DB name, Login, API Key
  • Public URL for the webhook (ngrok/托管平台/reverse proxy). Ensure WEBHOOK_URL / N8N_HOST / N8N_PROTOCOL / N8N_PORT are consistent
  • Header Auth secret (e.g., x-webhook-token: <your-secret>)

How it works

  1. Ingest – The Webhook receives a POST at /webhook(-test)/lead-webform with Header Auth.
  2. Validate – An IF node checks required fields; if missing → respond with 400 Bad Request.
  3. UTM lookup – Three Odoo getAll queries fetch IDs by name:
    • utm.sourcesource_id
    • utm.mediummedium_id
    • utm.campaigncampaign_id
      If a record is not found, the corresponding ID remains null.
  4. Consolidate – Merge + Code nodes produce a single clean object:
    { name, contact_name, email_from, phone, description, type: "lead", campaign_id, source_id, medium_id }
  5. Create in Odoo – Odoo node (crm.lead → create) writes the lead with standard fields + UTM Many2one IDs.
  6. Respond – Success node returns 200 with { status: "ok", lead_id }.

Payload (JSON)

Required: firstname, lastname, email
Optional: phone, notes, source, medium, campaign

{
  "firstname": "John",
  "lastname": "Doe",
  "email": "[email protected]",
  "phone": "+393331234567",
  "notes": "Wants a demo",
  "source": "Ads",
  "medium": "Website",
  "campaign": "Spring 2025"
}

Quick test

curl -X POST "https://<host>/webhook-test/lead-webform" \
  -H "Content-Type: application/json" \
  -H "x-webhook-token: <secret>" \
  -d '{"firstname":"John","lastname":"Doe","email":"[email protected]",
       "phone":"+39333...", "notes":"Demo",
       "source":"Ads","medium":"Website","campaign":"Spring 2025"}'

Notes

  • Recent Odoo versions do not use the mobile field on leads/partners: use phone instead.
  • Keep secrets and credentials out of the template; the user will set their own after import.
  • If you want to auto-create missing UTM records, add an IF after each getAll and a create on utm.*.