Skip to main content
G

Gaetano Castaldo

1
Workflow

Workflows by Gaetano Castaldo

Workflow preview: Secure web form to Odoo CRM lead creation with UTM tracking
Free advanced

Secure web form to Odoo CRM lead creation with UTM tracking

# 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.source` → `source_id` - `utm.medium` → `medium_id` - `utm.campaign` → `campaign_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` ```json { "firstname": "John", "lastname": "Doe", "email": "[email protected]", "phone": "+393331234567", "notes": "Wants a demo", "source": "Ads", "medium": "Website", "campaign": "Spring 2025" } ``` ## Quick test ```bash 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.*`.

G
Gaetano Castaldo
Lead Generation
12 Aug 2025
1712
0