Cohort Odoo Integration
WordPress plugin that connects a contact form to Odoo CRM.
by Cohort · github.com/sanjeevan-git/cohort-odoo-integration · website
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/sanjeevan-git/cohort-odoo-integration/archive/refs/heads/main.zipProduction-ready WordPress plugin that connects a custom theme contact form to Odoo CRM via the Odoo External API (JSON-RPC).
Requirements
- WordPress 6.0+
- PHP 8.0+
- Odoo instance with External API access
- Odoo user account with API key
Installation
- Copy the
cohort-odoo-integrationfolder towp-content/plugins/. - Activate Cohort Odoo Integration in Plugins.
- Go to Settings → Odoo Integration and enter your credentials.
Admin Configuration
| Setting | Description |
|---|---|
| Odoo URL | Base URL of your Odoo instance (e.g. https://your-company.odoo.com) |
| Database Name | Odoo database used for authentication |
| Username | Odoo user with CRM/API access |
| API Key | API key for the Odoo user (leave blank on save to keep the existing key) |
| Debug Mode | Writes diagnostic logs to wp-content/uploads/cohort-odoo-logs/cohort-odoo.log |
Credentials are stored in the WordPress database (cohort_odoo_settings) with autoload disabled for performance. They are never exposed to the frontend or in error responses.
Theme Integration
The plugin does not render the form. Add the HTML in your custom theme and ensure field names match exactly.
Recommended markup
Use the shortcode in page content or a theme template:
<?php echo do_shortcode( '[cohort_contact_form]' ); ?>
The shortcode renders the theme contact form markup (template-parts/contact-form.php) and loads plugin JavaScript. You do not need to include the form HTML manually.
For a manual HTML example (field names must match exactly):
<form class="cohort-contact-form" method="post" novalidate>
<label for="contact-name">Name</label>
<input type="text" id="contact-name" name="name" required>
<label for="contact-email">Email</label>
<input type="email" id="contact-email" name="email" required>
<label for="contact-message">Message</label>
<textarea id="contact-message" name="message" required></textarea>
<button type="submit">Send</button>
<div class="cohort-contact-message" aria-live="polite"></div>
</form>
Required field names
nameemailmessage
Asset loading (performance)
JavaScript is not loaded globally. It enqueues only when a contact form marker is detected:
- CSS class
cohort-contact-form - Attribute
data-cohort-contact-formon the<form>element - Shortcode
[cohort_contact_form]anywhere in post content or templates (renders the form)
Form in a PHP template
If the form lives in a template file outside post_content, call this before wp_footer():
<?php cohort_odoo_enable_contact_form_assets(); ?>
Optional styling
The script adds these classes to the message container (no plugin CSS is shipped):
.cohort-contact-message--success.cohort-contact-message--error
Style them in your theme as needed.
Odoo Lead Mapping
Submissions create a record on the crm.lead model:
| Odoo field | Value |
|---|---|
name |
Website Inquiry - {User Name} |
contact_name |
Form name |
email_from |
Form email |
description |
Form message |
How It Works
- Visitor submits the form; vanilla JS sends a POST request to
/wp-json/cohort/v1/contact. - The contact handler verifies the nonce, sanitizes input, and validates required fields.
- The API class authenticates with Odoo and creates a CRM lead via JSON-RPC.
- A JSON success or error response is returned; the page does not reload.
REST API
Endpoint: POST /wp-json/cohort/v1/contact
Body (JSON):
{
"nonce": "…",
"name": "Jane Doe",
"email": "jane@example.com",
"message": "Hello"
}
Success (200):
{
"success": true,
"message": "Thank you. Your message has been sent."
}
Error (4xx/5xx):
{
"success": false,
"code": "cohort_error_code",
"message": "Error description"
}
The nonce is validated on every request. Invalid nonces return HTTP 403.
Rate limiting: 5 submissions per IP every 10 minutes (HTTP 429 when exceeded). Limits remain active even when debug mode is enabled. Limits are filterable via cohort_odoo_rate_limit_max and cohort_odoo_rate_limit_window.
Spam Protection
- A hidden honeypot field (
cohort_hp) is injected automatically bycontact.js. - Themes may also include their own honeypot input with
name="cohort_hp". - Submissions with a filled honeypot are rejected.
- Extend validation with the
cohort_odoo_validate_submissionfilter (supports future reCAPTCHA or Turnstile integrations).
Debug Logging
Enable Debug Mode under Settings → Odoo Integration.
Logs are written to a protected directory:
wp-content/uploads/cohort-odoo-logs/cohort-odoo.log
The log directory is protected with index.php and .htaccess rules. Logs rotate automatically at 1 MB. Sensitive values (API keys, passwords, tokens, email addresses) are redacted. Disable debug mode in production unless troubleshooting.
Security
- Nonce verification on every submission
- IP-based REST rate limiting (5 requests / 10 minutes)
- Honeypot spam protection with extensible validation filter
- Input sanitization (
sanitize_text_field,sanitize_email,sanitize_textarea_field) - Output escaping in admin; JSON-safe messages in REST responses
manage_optionscapability required for settings- Direct file access blocked via
ABSPATHchecks and directoryindex.phpfiles - Protected log directory; credentials and emails redacted from debug logs
- API credentials never included in frontend errors
Performance
- Conditional script loading for classic themes, block themes, template parts, and shortcodes
- Single option row, autoload disabled
- No third-party PHP libraries
- No jQuery
- Admin code loads only in wp-admin
- External HTTP requests only to Odoo during form submission
Plugin Structure
cohort-odoo-integration/
├── cohort-odoo-integration.php # Bootstrap
├── uninstall.php # Cleanup on delete
├── includes/
│ ├── class-plugin.php # Orchestrator
│ ├── class-settings.php # Settings API
│ ├── class-admin.php # Admin UI
│ ├── class-contact-handler.php # REST API + assets
│ ├── class-api.php # Odoo JSON-RPC
│ ├── class-logger.php # Debug logging
│ └── helpers.php # Theme helpers
└── assets/js/contact.js # Frontend handler
Uninstall
Deleting the plugin from Plugins → Installed Plugins removes:
- The
cohort_odoo_settingsoption - Protected log directory and log files under
wp-content/uploads/cohort-odoo-logs/ - Legacy log file at
wp-content/uploads/cohort-odoo.log(if present)
Deactivating the plugin does not remove settings.
Troubleshooting
| Issue | Check |
|---|---|
| Form submits but nothing happens | Confirm the page has a form marker so contact.js is loaded |
| “Something went wrong. Please try again.” | Check the protected debug log for the underlying Odoo/API error; verify credentials under Settings → Odoo Integration |
| “Unable to connect to CRM” | Verify Odoo URL, database, username, and API key; enable debug mode and inspect the log |
| Script not loading in a template | Call cohort_odoo_enable_contact_form_assets() in the template |
License
GPL-2.0-or-later