WPResidence CRM Contacts — Developer Reference
This article documents the Contacts module of the WPResidence real estate CRM plugin from a code perspective: storage, CRUD API, AJAX endpoints, field map, hooks, and permissions.
Storage — wp_wpresidence_crm_contacts
Contacts live in a dedicated custom table with 44 columns, created in libs/db-setup.php. No CPT is used for new records — the legacy wpestate_crm_contact post type is kept only for backward compatibility and is migrated on activation.
Key Columns
| Column | Purpose |
|---|---|
contact_id |
Primary key, auto-increment |
first_name, last_name, prefix |
Personal info |
email, mobile, phone, home_phone |
Contact methods; email is the duplicate-detection key |
address, city, county, state, zipcode, country |
Address |
lifecycle_stage |
Default new_lead |
lifecycle_stage_changed_at |
Timestamp used by time-based automations |
lead_source, lead_type |
Marketing attribution |
status |
Active / Inactive / VIP / Blocked |
assigned_agent_id |
WP user ID of the owning agent |
user_id |
WP user ID of the creator |
wp_user_id |
WP user ID if the contact has a WP login |
tags |
Comma-separated string |
private_note |
Internal note |
pref_min_price, pref_max_price, pref_min_beds, pref_max_beds, pref_min_baths, pref_max_baths, pref_min_area, pref_max_area, pref_locations, pref_property_type, pref_property_status |
Buyer preferences used by the matching engine |
twitter, linkedin, facebook |
Social URLs |
created_at, updated_at |
Timestamps |
Indexes
On email, user_id, status, lifecycle_stage, assigned_agent_id, lead_source.
CRUD API — libs/contact-crud.php
| Function | Purpose |
|---|---|
wpestate_crm_insert_contact($data) |
Insert; returns contact_id or WP_Error |
wpestate_crm_get_contact($contact_id) |
Fetch one row |
wpestate_crm_get_contacts($args) |
Fetch many; supports status, lifecycle_stage, lead_source, lead_type, tags, assigned_agent_id, date range, search, orderby, limit, offset |
wpestate_crm_update_contact($id, $data) |
Update; fires wpestate_crm_after_update_contact |
wpestate_crm_delete_contact($id) |
Delete row and cascade clean up |
wpestate_crm_bulk_delete_contacts($ids) |
Bulk delete |
wpestate_crm_find_contact_by_email($email) |
Duplicate-detection helper |
wpestate_crm_contact_field_map() |
Maps form keys (e.g., crm_first_name) to DB columns |
Page and Form Templates
page-templates/wpestate-crm-dashboard_contacts.php— list view with 9 filters.templates/crm_contact_detail.php— detail page.templates/crm_add_contact.php— add/edit form.templates/dashboard_contact_unit.php— single contact row/card.
AJAX Endpoints
| Action | Nonce |
|---|---|
wpestate_crm_save_contact |
wpestate_crm_save_contact |
wpestate_crm_delete_contact |
wpestate_crm_delete_contact |
wpestate_crm_bulk_delete_contacts |
wpestate_crm_bulk_delete_contacts |
wpestate_crm_bulk_update_contacts |
wpestate_crm_bulk_update_contacts |
wpestate_crm_search_contacts |
wpestate_crm_search_contacts |
Hooks
wpestate_crm_after_insert_contact— fired after a row is inserted. Used by notifications, webhooks, HubSpot sync, automations.wpestate_crm_after_update_contact— fired after update; includes lifecycle stage change detection.wpestate_crm_after_delete_contact— fired after delete.
Permissions
- Capability:
manage_crm(baseline) pluswpestate_crm_user_can('contacts', $action). - Scope:
wpestate_crm_get_ownership_where()returns1=1for admins and(user_id = %d OR assigned_agent_id = %d)for agents. - Per-row guard:
wpestate_crm_user_owns_contact($id)is used in mutation AJAX handlers.
Default Picklists
Defined in libs/settings.php via wpestate_crm_get_setting():
crm_contact_statuses— Active, Inactive, VIP, Blockedcrm_lifecycle_stages— New Lead, Contacted, Appointment Set, Active Client, Under Contract, Closedcrm_contact_prefixes— Mr, Mrs, Ms, Dr, Profcrm_lead_sources— 10 defaults including Website, Referral, Social Media, Portal, Zillow, Realtor.comcrm_lead_types— Buyer, Seller, Tenant, Landlord, Investor, Other
Auto-Creation from Forms
The libs/auto-create.php module calls wpestate_crm_insert_contact() for every qualifying theme form submission. Duplicate detection is done by email; if matched, the code updates the existing contact instead of creating a new one.
HubSpot Field Mapping
first_name→firstnamelast_name→lastnamemobile→phoneemail→email(deduplication key)city,state,countrymapped as-is
See the HubSpot CRM integration guide for the full sync architecture.
Non-Latin Input
All text fields are passed through sanitize_text_field() or sanitize_textarea_field(), which are UTF-8 safe. Names, addresses, and notes preserve any script correctly.