Developer-focused documentation for the Leads module of the WPResidence real estate CRM plugin. Covers the custom table, CRUD API, AJAX endpoints, and relationship to Contacts.
Storage — wp_wpresidence_crm_leads
Leads are stored in a 14-column custom table created in libs/db-setup.php. A legacy wpestate_crm_lead CPT (post-types/leads.php) is retained for backward compatibility; new records are written directly to the custom table.
Columns
| Column | Purpose |
|---|---|
| lead_id | Primary key |
| contact_id | FK to wp_wpresidence_crm_contacts |
| user_id | WP user who created the lead |
| handler_agent_id | WP user ID of the assigned agent |
| lead_type | Buyer / Seller / Tenant / Landlord / Investor / Other |
| lead_source | Source picklist value |
| lead_source_link | Source URL |
| status | Default New |
| message | Prospect message |
| private_note | Internal note |
| from_email | Email captured from form |
| source_permalink | URL of the page that generated the lead |
| created_at, updated_at | Timestamps |
Indexes: contact_id, user_id, handler_agent_id, status.
CRUD API — libs/lead-crud.php
| Function | Purpose |
|---|---|
| wpestate_crm_insert_lead($data) | Insert |
| wpestate_crm_get_lead($id) | Fetch one |
| wpestate_crm_get_leads($args) | Filters: contact_id, handler_agent_id, status, lead_type, lead_source, date range, search |
| wpestate_crm_update_lead($id, $data) | Update |
| wpestate_crm_delete_lead($id) | Delete |
| wpestate_crm_bulk_delete_leads($ids) | Bulk delete |
| wpestate_crm_get_lead_form_values($id) | Pre-fill the add/edit form |
Templates
- page-templates/wpestate-crm-dashboard_leads.php — list view.
- templates/crm_add_lead.php — add/edit form.
- templates/dashboard_lead_unit.php — single-row partial.
AJAX Endpoints
| Action | Nonce |
|---|---|
| wpestate_crm_delete_lead | wpestate_crm_delete_lead |
| wpestate_crm_bulk_delete_leads | wpestate_crm_bulk_delete_leads |
| wpestate_crm_bulk_update_leads | wpestate_crm_bulk_update_leads |
Default Status Picklist
Setting key: crm_lead_statuses. Default value: New, Open, In progress, Open deal, Unqualified, Attempted to contact, Connected, Bad timing. Administrators edit the list via the CRM Settings admin page.
Relationship to Contacts
Leads always link to a contact via contact_id. When a lead is inserted:
- The handler calls wpestate_crm_find_contact_by_email().
- If found, the existing contact_id is used.
- If not, wpestate_crm_insert_contact() is called first, and the new ID is stored on the lead.
One contact may have many leads. This is how multiple enquiries from the same person stay tied to a single master record.
Auto-Create from Forms
Most lead rows are written by libs/auto-create.php in response to theme contact forms. The module also records a form_submission activity via wpestate_crm_record_activity_v2() and inserts an enquiries row for the same submission. See the Auto-Create article for the full data flow.
Ownership and Scope
Non-admin queries add (user_id = %d OR handler_agent_id = %d) via wpestate_crm_get_ownership_where(). Admins skip the filter entirely.
Extending Leads
- Use the wpestate_crm_after_insert_contact hook if your extension needs to run after contact creation but before follow-on lead/activity inserts.
- Store extra structured data in wp_wpresidence_crm_activities as typed activities rather than adding lead columns.
- If you must extend the lead row, add the column with dbDelta-compatible SQL in your own plugin and read/write it via $wpdb directly; do not edit the CRM plugin.