Developer documentation for the HubSpot integration in the WPResidence real estate CRM. Code lives in libs/hubspot/, main file libs/hubspot/hubspot.php. Full architectural overview is in the HubSpot CRM integration guide.
API
- Version: HubSpot CRM v3.
- Base URL: https://api.hubapi.com/crm/v3/.
- Auth: Bearer token (Private App access token).
- HTTP client: wp_remote_post(), wp_remote_get(), wp_remote_request().
Settings (dual source)
Settings are read via wpestate_crm_get_setting() first, falling back to legacy Redux keys via wpresidence_get_option():
| CRM key | Legacy Redux key |
|---|---|
| crm_hubspot_enabled | wp_estate_enable_hubspot_integration |
| crm_hubspot_enabled_for_all | wp_estate_enable_hubspot_integration_for_all |
| crm_hubspot_api_token | wp_estate_hubspot_api |
| crm_hubspot_first_stage | wp_estate_hubspot_first_stage |
| hubspot_stage_map | (none) |
Contact Sync
wpestate_crm_hubspot_sync_contact( $contact_id, $data )
Hooked to wpestate_crm_after_insert_contact and wpestate_crm_after_update_contact at priority 20. Flow:
- Check crm_hubspot_enabled and confirm the API token is present.
- Build field map: first_name → firstname, last_name → lastname, mobile → phone, plus email, city, state, and country.
- Filter out empty values so non-destructive updates do not clear HubSpot fields.
- Search HubSpot by email to detect an existing contact.
- If found: PATCH /crm/v3/objects/contacts/{id}.
- If not found: POST /crm/v3/objects/contacts.
Deal Sync
wpestate_crm_hubspot_sync_deal( $deal_id, $data )
Hooked to wpestate_crm_after_insert_deal and wpestate_crm_after_update_deal at priority 20. Flow:
- Check enabled status and token.
- Build properties: dealname from deal_title or title, amount from deal_value, dealstage from the hubspot_stage_map lookup, with fallback to sanitize_title() of the CRM stage name or crm_hubspot_first_stage.
- Create or PATCH the deal.
- If the CRM deal has a contact_id, look up the HubSpot contact by email and associate it via PUT /crm/v3/objects/deals/{deal_id}/associations/contacts/{contact_id}/deal_to_contact.
- Store the returned HubSpot deal ID in the CRM deals table as hubspot_deal_id.
Helper Functions
| Function | Purpose |
|---|---|
| wpestate_crm_return_api_hubspot($lead_id) | Resolves API token from agent, agency, or developer CPT meta first, then CRM settings, then Redux |
| wpestate_hubspot_enabled($who) | Checks the enabled flag; $who=’all’ enforces the global sync-for-all flag |
Legacy Functions
Maintained for backward compatibility with older form handlers:
- wpestate_create_contact_hubspot()
- wpestate_create_deal_hubspot()
- wpestate_create_tickets_hubspot()
- wpestate_hubspot_crm_associate()
- wpestate_hubspot_sync_deal_stage()
- wpestate_hubspot_sync_deal_value()
Test Connection AJAX
| Property | Value |
|---|---|
| Action | wpestate_crm_test_hubspot_connection |
| Nonce | wpestate_crm_test_hubspot (security param) |
| Capability | manage_options |
Four checks run sequentially:
- GET /crm/v3/objects/contacts?limit=1 – contacts read.
- GET /crm/v3/objects/deals?limit=1 – deals read.
- GET /crm/v3/pipelines/deals – pipelines; counts stages.
- Create a test contact, then immediately DELETE it – contacts write.
Error Handling
- All HTTP failures are silent. They never block the CRM operation that triggered them.
- is_wp_error() is checked on every HTTP response.
- Errors are logged to the plugin’s logs/ directory.
Sync Direction
One-way only: WPResidence CRM → HubSpot. There is no inbound sync path. If you need two-way sync, implement a HubSpot webhook that calls back into a WordPress REST endpoint you write.
Extending
- Map additional fields by filtering the property array in your child plugin before the wp_remote_post() call. Add an apply_filters() in a fork if needed, or wrap the function.
- Sync custom CRM objects, such as tasks or activities, by adding new hooks that call the HubSpot API directly using the existing auth token resolver.