Build & extend
Developer reference
Post types, meta keys, REST routes, filters, and template overrides for custom work.
Everything here belongs in a child theme or a small custom plugin. Editing the theme or EstatePoint Core directly means losing the change on the next update.
Content model
| Post type | Key | Public |
|---|---|---|
| Property | property | Yes — archive at /properties/ |
| Consultant | team | Yes |
| Testimonial | testimonial | No |
| Inquiry | estatepoint_inquiry | No — admin only |
| Taxonomy | Key | Post type |
|---|---|---|
| Property Categories | property_category | property |
| Property Types | property_type | property |
| Property Statuses | listing_type | property |
| Locations | property_location | property |
| Features | property_feature | property |
| Labels | property_label | property |
| Consultant categories | team_category | team |
Listing meta keys
Listing facts are post meta on the property post, prefixed estatepoint_prop_:
| Meta | Holds |
|---|---|
estatepoint_prop_price | Price in the listing’s own currency |
estatepoint_prop_price_base | Price normalized to the site base currency — what filters and sorting compare |
estatepoint_prop_bedrooms, ..._bathrooms, ..._floors | Counts |
estatepoint_prop_area_sqm, ..._lot_size_sqm | Areas |
estatepoint_prop_year_built | Year |
estatepoint_prop_parking_spaces | Count |
estatepoint_prop_furnished, ..._pets_allowed | Flags |
estatepoint_prop_latitude, ..._longitude | Map coordinates |
estatepoint_prop_listing_expiry | Y-m-d expiry date |
estatepoint_prop_assigned_team | Assigned consultant post ID |
Never write estatepoint_prop_price_base yourself — it is derived from the price and the current exchange rates.
REST routes
Public, used by the front end:
| Route | Method | Purpose |
|---|---|---|
/wp-json/estatepoint/v1/hero-search | GET | Search suggestions — locations, types, listings |
/wp-json/estatepoint/v1/property-map-dataset | GET | Map markers for the current filters |
/wp-json/estatepoint/v1/favorites | GET | Rendered cards for saved listing IDs |
/wp-json/estatepoint/v1/consultant-listings | GET | Paged listings for a consultant profile |
/wp-json/estatepoint-core/v1/property-inquiry | POST | Inquiry submission |
The agent dashboard uses an authenticated estatepoint-agent/v1 namespace for listing and lead operations.
Public routes are rate limited, and inquiry submission additionally requires a nonce and passes a honeypot check.
Useful filters
// Map default center and zoom (empty or unfiltered first paint).
add_filter( 'astora_property_map_default_center', fn() => array( 41.0082, 28.9784 ) );
add_filter( 'estatepoint_property_map_default_zoom', fn() => 11 );
// Where a listing inquiry email is delivered.
add_filter( 'estatepoint_core_inquiry_mail_target', function ( $target, $property_id ) {
return $target;
}, 10, 2 );
// Who is notified when a listing expires.
add_filter( 'estatepoint_property_listing_expiry_notification_recipients', function ( $emails ) {
$emails[] = 'operations@example.com';
return $emails;
} );
// Keep attachments when they are removed from a listing.
add_filter( 'estatepoint_property_media_purge_enabled', '__return_false' );
// Consultant position presets in the profile editor.
add_filter( 'estatepoint_team_position_presets', function ( $presets ) {
$presets['lettings'] = __( 'Lettings Manager', 'your-textdomain' );
return $presets;
} );
// Inquiry pipeline stages.
add_filter( 'estatepoint_inquiry_pipeline_statuses', function ( $statuses ) {
return $statuses;
} );
Add a spam challenge — Turnstile, reCAPTCHA, anything — to the inquiry form with the challenge hook:
add_filter( 'estatepoint_core_property_inquiry_challenge', function ( $ok, $request ) {
return your_verifier( $request->get_param( 'your_token' ) );
}, 10, 2 );
Browse query parameters
The archive reads its filters from the query string. Building links programmatically is often simpler than filtering WP_Query:
/properties/?listing_type=for-sale&property_location=lisbon&price_max=500000&sort=price_asc
The full parameter list is in Property archive.
Template overrides
Copy a template file from the parent theme into the same relative path in the child theme and edit the copy. Front-end listing blocks read typed data structures rather than querying meta inline, so an override usually only needs markup changes.
Keep overrides few. Each one stops receiving upstream fixes, and most visual changes are reachable through Elementor Style controls or CSS.
Front-end runtime
The theme prints layout state — sticky, overlay, layout variant — server-side on the page shell, and ships a single client runtime object that scripts read. Do not toggle header, footer, or body classes from JavaScript after load to change layout mode: the server already decided, and the two will disagree on the next page.
Translation
Text domain: estatepoint for both theme and Core. languages/estatepoint.pot ships in the package. Translate with Loco Translate or Poedit, or a WordPress language pack workflow, and keep translations in wp-content/languages/themes/ so an update does not overwrite them.
Debugging
// wp-config.php, staging only
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
define( 'SCRIPT_DEBUG', true );
Then check wp-content/debug.log. For layout problems, compare the front end with the Elementor editor — see Troubleshooting.