Documentation menu

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 typeKeyPublic
PropertypropertyYes — archive at /properties/
ConsultantteamYes
TestimonialtestimonialNo
Inquiryestatepoint_inquiryNo — admin only
TaxonomyKeyPost type
Property Categoriesproperty_categoryproperty
Property Typesproperty_typeproperty
Property Statuseslisting_typeproperty
Locationsproperty_locationproperty
Featuresproperty_featureproperty
Labelsproperty_labelproperty
Consultant categoriesteam_categoryteam

Listing meta keys

Listing facts are post meta on the property post, prefixed estatepoint_prop_:

MetaHolds
estatepoint_prop_pricePrice in the listing’s own currency
estatepoint_prop_price_basePrice normalized to the site base currency — what filters and sorting compare
estatepoint_prop_bedrooms, ..._bathrooms, ..._floorsCounts
estatepoint_prop_area_sqm, ..._lot_size_sqmAreas
estatepoint_prop_year_builtYear
estatepoint_prop_parking_spacesCount
estatepoint_prop_furnished, ..._pets_allowedFlags
estatepoint_prop_latitude, ..._longitudeMap coordinates
estatepoint_prop_listing_expiryY-m-d expiry date
estatepoint_prop_assigned_teamAssigned 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:

RouteMethodPurpose
/wp-json/estatepoint/v1/hero-searchGETSearch suggestions — locations, types, listings
/wp-json/estatepoint/v1/property-map-datasetGETMap markers for the current filters
/wp-json/estatepoint/v1/favoritesGETRendered cards for saved listing IDs
/wp-json/estatepoint/v1/consultant-listingsGETPaged listings for a consultant profile
/wp-json/estatepoint-core/v1/property-inquiryPOSTInquiry 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.