Developer documentation for the matching engine in the WPResidence real estate CRM. The engine lives in libs/matching-functions.php and matches buyer preference fields stored on contacts against estate_property posts.
Core Function
wpestate_crm_match_properties( $contact_id, $args = [] )
$args supports per_page, paged, agent_only. Returns {post_ids: int[], count: int}.
Input Fields Used
Read from the contacts table: pref_property_type, pref_property_status, pref_locations, pref_min_price, pref_max_price, pref_min_beds, pref_max_beds, pref_min_baths, pref_max_baths, pref_min_area, pref_max_area.
Query Construction
A WP_Query is built against post_type=estate_property with:
- tax_query: relation AND.
property_category+property_statusfilters. Location is a nested OR matching city or area taxonomy terms. - meta_query: relation AND. BETWEEN filters on
property_price,property_bedrooms,property_bathrooms,property_size. post_status=publish.
Missing preference fields are skipped (no filter added). A contact with no preferences returns an empty result rather than all listings.
AJAX Endpoints
| Action | Nonce | Purpose |
|---|---|---|
wpestate_crm_match_properties |
wpestate_crm_nonce (security param) |
Run match; returns post data |
wpestate_crm_email_matches |
wpestate_crm_nonce |
Email matched listings to contact |
wpestate_crm_get_viewed_listings |
wpestate_crm_nonce |
Fetch viewed-listings history (related feature) |
Email Dispatcher
wpestate_crm_ajax_email_matches() builds an HTML email with one property card per listing (thumbnail, title, price, beds, baths, area) and sends it via wpestate_send_emails() (or wp_mail() fallback).
Settings
wp_estate_crm_matching_email_subject— default Properties matching your preferences.wp_estate_crm_matching_email_header— HTML above the listing cards.wp_estate_crm_matching_email_footer— HTML below the listing cards.wp_estate_crm_matching_email_max_listings— per-email cap, default 20.
Placeholders
Supports the 20-placeholder set from wpestate_crm_resolve_placeholders(). Common ones: {contact_name}, {site_name}, {agent_name}.
Activity Record
Each email records a listing_email_sent activity with meta JSON containing listing_count and listing_ids.
New-Listing Trigger
Hooked to publish_estate_property. When a listing is published for the first time, a one-time cron wpestate_crm_match_new_listing is scheduled 60 seconds later. The handler runs match queries against all active contacts with buyer preferences and emails them the new listing if it is a fit.
Automation Action
The action type run_matching (in libs/automations.php) calls wpestate_crm_match_properties() and optionally emails the agent if matches are found. Used by default rules 24, 25, 26.
Scoring
Matching is currently binary — a listing is either within the preference ranges or it is not. There is no numerical score. Extend by adding a custom filter that ranks the returned post IDs by some proximity metric (e.g., distance from midpoint price).
Extending
- Add custom meta filters by extending the query builder in a child plugin and hooking a filter on the returned
WP_Queryarguments. - Store additional preference fields on the contact row as custom meta or in a dedicated extension table; the engine reads from the contacts table by column name.
- For very large inventories, consider switching the engine to use a dedicated search index table (the theme has an in-progress
wpestate_26_search_indexmodule for this purpose).