Back to Templates

Secure Web Form to Odoo CRM Lead Creation with UTM Tracking

Created by

Created by: Gaetano Castaldo || castaldosolutions

Gaetano Castaldo

Last update

Last update a day ago

Share


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/Cloudflare/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.*.