Skip to main content
Skip to main content

Developers Doc

Action Hooks

11 mins read 91 Views 3+

Havenlytics action hooks are the do_action() events the plugin fires at key moments during its lifecycle, rendering, and data operations. They let you run your own code — logging, CRM sync, custom markup, integrations — without editing a single plugin file. This reference documents every action hook that exists in Havenlytics 3.3.1, grouped by subsystem, with the exact parameters each one passes.

Note: Every Havenlytics hook is prefixed hvnly_. There are no havenlytics_ hooks. If a hook name is not listed on this page, it does not exist in the plugin — do not rely on it.

How action hooks work in Havenlytics

Havenlytics fires actions with the standard WordPress do_action() function. You subscribe with add_action(), matching the hook name and the number of arguments it passes:

<?php
/**
 * Run custom setup after Havenlytics has fully loaded.
 * Fired once, at the end of the plugin boot sequence.
 */
add_action( 'hvnly_loaded', function () {
    // All Havenlytics services, CPTs and REST routes are now available.
    if ( function_exists( 'HVNLY_NAB' ) ) {
        // e.g. warm a cache, register an integration, etc.
    }
} );

When a hook passes parameters, declare the priority and the argument count in add_action() so WordPress hands them to your callback:

<?php
// hvnly_property_agents_saved passes ( int $property_id, array $agent_ids )
add_action( 'hvnly_property_agents_saved', function ( $property_id, $agent_ids ) {
    error_log( sprintf(
        'Property %d now has %d assigned agent(s).',
        $property_id,
        count( $agent_ids )
    ) );
}, 10, 2 ); // priority 10, accepts 2 arguments

Lifecycle & bootstrap actions

These fire as the plugin and its modules initialize. Use them to register integrations at the right moment.

HookFires atParametersWhen it runs
hvnly_loadedhavenlytics.phpEnd of boot, after all services are wired.
hvnly_frontend_services_registeredincludes/Frontend.phpAfter frontend services are registered.
hvnly_database_services_registeredincludes/Database/Database.phparray $instancesAfter database services are registered.
hvnly_database_service_instantiatedincludes/Database/Database.phpstring $class, object $serviceAfter each database service is instantiated.
hvnly_agent_initincludes/Agent/AgentBootstrap.phpAgentBootstrap $thisAgent module initialized.
hvnly_contact_agent_before_bootstrapincludes/ContactAgent/ContactAgentModule.php$moduleBefore the Contact Agent module boots.
hvnly_contact_agent_bootstrappedincludes/ContactAgent/ContactAgentModule.php$moduleAfter the Contact Agent module boots.
hvnly_contact_agent_initincludes/ContactAgent/ContactAgentBootstrap.php$bootstrap, $moduleContact Agent bootstrap complete.
hvnly_contact_agent_frontend_registeredincludes/ContactAgent/ContactAgentFrontend.phpAfter the Contact Agent frontend registers.
hvnly_contact_agent_ajax_registeredincludes/ContactAgent/AjaxHandler.php$handlerAfter Contact Agent AJAX handlers register.

Settings & cache actions

Fire after configuration changes or cache clears — ideal for invalidating your own caches in sync with Havenlytics.

HookParametersWhen it runs
hvnly_settings_updatedstring $group, array $settingsA settings group (or all) was saved or reset.
hvnly_property_view_type_syncedstring $view_type, array $settingsThe property view-type option was synced.
hvnly_cache_clearedAll plugin cache was cleared.
hvnly_cache_pattern_clearedstring $patternCache entries matching a pattern were cleared.
hvnly_cache_expired_clearedExpired cache entries were cleared.
hvnly_set_cached_search_resultsstring $cache_key, mixed $data, int $durationSearch results were written to cache.
hvnly_shortcode_caches_clearedShortcode output caches were cleared.
hvnly_property_query_cache_setstring $key, mixed $payload, int $ttl, array $optionsA property query result was cached.
hvnly_property_query_cache_invalidatedint $generationThe property query cache generation was bumped.
hvnly_cleared_terms_cachestring $taxonomySearch-terms cache cleared for a taxonomy.
hvnly_cleared_all_search_cacheAll search caches cleared.
hvnly_cleared_property_cacheint $post_idCached search results for a property cleared.

Template & layout actions

These are the injection points inside Havenlytics templates. Hook them to add markup around content regions, single-property sections, or the property loop.

HookParametersWhen it runs
hvnly_before_main_contentBefore the main content region (single, archive, taxonomy, search shortcode).
hvnly_after_main_contentAfter the main content region.
hvnly_single_property_elementsSingle-property element render point.
hvnly_single_property_headerSingle-property header section.
hvnly_single_property_layout_gridSingle-property grid layout.
hvnly_single_property_main_contentSingle-property main content.
hvnly_single_property_sidebarSingle-property sidebar.
hvnly_single_property_similar_propertiesSimilar-properties section.
hvnly_single_agent_headerSingle-agent header.
hvnly_single_agent_profile_rowSingle-agent profile row.
hvnly_single_agent_listings_sectionSingle-agent listings section.
hvnly_single_agent_main_contentSingle-agent main content.
hvnly_single_agent_sidebarSingle-agent sidebar.
hvnly_before_single_agency / hvnly_after_single_agencyarray $agency, WP_Term $termAround single-agency content.
hvnly_before_property_taxonomy / hvnly_after_property_taxonomyAround the property-taxonomy (no-results) block.
hvnly_property_loop_start / hvnly_property_loop_endAt the start and end of the property loop.
hvnly_before_template_part / hvnly_after_template_partstring $template_name, string $template_path, string $located, array $argsAround every template part loaded via hvnly_get_template().
hvnly_get_template_part_{$slug}string $slug, string $name, array $argsDynamic — fires per template-part slug (e.g. hvnly_get_template_part_content).

Tip: hvnly_get_template_part_{$slug} is a dynamic hook. The {$slug} is replaced by the template-part slug being loaded, so hvnly_get_template_part('content','single-property') fires hvnly_get_template_part_content.

Archive, card & shortcode actions

HookParametersWhen it runs
hvnly_before_archive_property / hvnly_after_archive_propertyAround each property archive card.
hvnly_before_archive_agent / hvnly_after_archive_agentAround each agent archive card.
hvnly_before_archive_agency / hvnly_after_archive_agencyAround each agency archive card.
hvnly_before_shortcode_loop / hvnly_after_shortcode_looparray $attsAround a shortcode property loop (grid/list).
hvnly_after_shortcode_assets_enqueuedAfter shortcode assets are enqueued.

Agent & agency actions

HookParametersWhen it runs
hvnly_agent_post_type_registeredstring $slugThe hvnly_agent CPT was registered.
hvnly_agent_agency_taxonomy_registeredstring $taxonomyThe hvnly_agent_agency taxonomy was registered.
hvnly_property_agents_savedint $property_id, array $agent_idsA property’s assigned agents were saved.
hvnly_agent_profile_savedint $agent_idAn agent profile was saved.
hvnly_agent_delete_wizard_completedint $agent_id, int $user_id, mixed $targetThe agent delete wizard finished.

Agent Workspace & portal actions

HookParametersWhen it runs
hvnly_workspace_initWorkspaceBootstrap $thisThe Workspace module initialized.
hvnly_workspace_enqueue_assetsThe Workspace shortcode requested asset enqueue.
hvnly_workspace_assets_registeredarray $assetA Workspace asset was registered.
hvnly_workspace_assets_enqueuedWorkspace assets were enqueued.
hvnly_workspace_page_createdint $page_idThe Workspace page was auto-created.
hvnly_workspace_before_template / hvnly_workspace_after_templatestring $path, string $template, array $argsAround a Workspace template load.
hvnly_workspace_auditstring $event, array $contextA Workspace security-audit event.
hvnly_portal_notification_createdint $id, array $rowA portal notification row was created.
hvnly_workspace_agent_activityint $user_id, string $activityAgent activity (login / workspace visit) recorded.
hvnly_property_workflow_transitionedint $post_id, string $to, string $from, int $user_idA property workflow status transitioned.

Authentication, identity & provisioning actions

HookParametersWhen it runs
hvnly_workspace_registration_status_changedint $user_id, string $status, int $agent_id, string $previousAn agent’s registration status changed.
hvnly_workspace_agent_provisionedint $agent_id, int $user_idAn Agent CPT was provisioned for a user.
hvnly_workspace_user_provisioned_for_agentint $user_id, int $agent_idA WordPress user was provisioned for an agent.
hvnly_workspace_identity_link_setint $agent_id, int $user_id, mixed $currentThe agent↔user identity link was set.
hvnly_identity_verification_loggedarray $entryAn identity-verification audit entry was logged.

Email verification actions

HookParametersWhen it runs
hvnly_email_verification_email_before_sendint $user_id, array $context, bool $is_resendJust before a verification email is sent.
hvnly_email_verification_email_sentint $user_id, bool $is_resendA verification email was sent.
hvnly_email_verification_sentint $user_idVerification email dispatched (first send).
hvnly_email_verification_resentint $user_idVerification email resent.
hvnly_email_verification_verifiedint $user_idA user verified their email.
hvnly_email_verification_expiredint $user_idA verification token expired.
hvnly_email_verification_failedint $user_id, string $reasonA verification attempt failed.
hvnly_email_verification_admin_verifiedint $user_id, int $actor_idAn admin manually verified a user’s email.
hvnly_email_changedint $user_id, string $old_email, string $new_emailA user’s email changed (triggers re-verification).

Email pipeline actions

HookParametersWhen it runs
hvnly_email_import_success_sentint $import_count, WP_User $user, array $contextThe import-success email was sent.
hvnly_email_property_workflow_sentbool $sent, string $email_type, int $object_id, array $contextA property workflow email was sent.
hvnly_email_property_admin_alert_sentbool $sent, int $object_id, array $admin_contextA property admin-alert email was sent.
hvnly_workspace_account_email_sentbool $sent, string $email_type, string $to, array $contextA Workspace account email was sent.
hvnly_workspace_registration_email_sentbool $sent, string $email_type, int $user_id, array $contextA registration email was sent.
hvnly_workspace_registration_admin_alert_sentbool $sent, WP_User $user, array $admin_contextA registration admin-alert email was sent.

Contact Agent (inquiry) actions

HookParametersWhen it runs
hvnly_contact_agent_inquiries_table_createdThe inquiries database table was created.
hvnly_contact_agent_inquiry_replies_table_createdThe inquiry-replies table was created.
hvnly_contact_agent_inquiry_createdint $inquiry_id, array $rowA new inquiry was persisted.
hvnly_contact_agent_inquiry_status_updatedint $inquiry_id, string $statusAn inquiry’s status was updated.
hvnly_contact_agent_inquiry_deletedint $inquiry_idAn inquiry was deleted.
hvnly_contact_agent_inquiry_validatedarray $persist_payloadAn inquiry payload passed validation (AJAX).
hvnly_contact_agent_inquiry_notifiedint $inquiry_id, array $results, array $contextInquiry notifications were sent.
hvnly_contact_agent_inquiry_reply_sentint $reply_id, int $inquiry_id, int $user_id, array $inquiryA reply to an inquiry was sent.

Worked examples

1. Inject a banner above every property archive card

<?php
add_action( 'hvnly_before_archive_property', function () {
    echo '<div class="my-featured-ribbon">New this week</div>';
} );

2. Push new inquiries into an external CRM

<?php
add_action( 'hvnly_contact_agent_inquiry_created', function ( $inquiry_id, $row ) {
    // $row contains sender_name, sender_email, property_id, message, etc.
    wp_remote_post( 'https://crm.example.com/api/leads', array(
        'timeout' => 5,
        'headers' => array( 'Content-Type' => 'application/json' ),
        'body'    => wp_json_encode( array(
            'name'     => $row['sender_name']  ?? '',
            'email'    => $row['sender_email'] ?? '',
            'property' => $row['property_id']  ?? 0,
            'source'   => 'havenlytics',
        ) ),
    ) );
}, 10, 2 );

3. Notify a Slack channel when an agent is approved

<?php
add_action( 'hvnly_workspace_registration_status_changed', function ( $user_id, $status, $agent_id, $previous ) {
    if ( 'approved' !== $status ) {
        return;
    }
    $user = get_userdata( $user_id );
    wp_remote_post( 'https://hooks.slack.com/services/XXX/YYY/ZZZ', array(
        'body' => wp_json_encode( array(
            'text' => sprintf( 'Agent approved: %s', $user ? $user->user_email : $user_id ),
        ) ),
    ) );
}, 10, 4 );

Best practices

  • Match the argument count. If a hook passes two parameters, register with add_action( $hook, $cb, 10, 2 ). Omitting the count means your callback silently receives fewer arguments.
  • Register on hvnly_loaded or later when your integration depends on Havenlytics services (HVNLY_NAB(), CPTs, REST routes).
  • Keep template-hook callbacks output-only. Hooks like hvnly_before_main_content run mid-render — echo markup, don’t perform heavy queries there.
  • Prefer filters for data changes. Actions are for side effects; to change property data, queries, or template paths, use the corresponding Havenlytics filter hooks instead.

Performance recommendations

Performance: Actions that fire inside loops — hvnly_before_archive_propertyhvnly_property_loop_starthvnly_get_template_part_{$slug} — run once per item. Avoid database calls or remote requests inside them; precompute data on hvnly_loaded or cache it.

  • Offload slow work (CRM sync, webhooks) from request-time hooks by scheduling it with wp_schedule_single_event() and processing it via WP-Cron.
  • Use the cache actions (hvnly_cache_clearedhvnly_property_query_cache_invalidated) to invalidate your own caches in lockstep, rather than clearing them on every request.

Security notes

Security: Hook payloads are data, not trusted output. Escape everything you print inside template actions with esc_html()esc_attr(), or esc_url(), and treat inquiry fields (hvnly_contact_agent_inquiry_created) as untrusted user input before sending them anywhere.

  • Never expose user email, tokens, or identity data from hvnly_workspace_* and hvnly_email_verification_* hooks to the front end or logs in production.
  • When calling external services from an action, use wp_remote_post() with a short timeout and validate/sanitize the payload first — a hook firing is not authorization to leak PII.

Common mistakes

  • Forgetting the argument-count parameter in add_action(), so parameters arrive as null.
  • Trying to modify data inside an action — actions do not use return values; use the matching filter hook instead.
  • Assuming a hook fires on every request — many (e.g. hvnly_workspace_*) only fire in the Agent Workspace context, and admin-only actions never fire on the front end.

Need more help?

Can't find what you're looking for? Our team and community are here to help you ship faster.