• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 12+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » How to build custom Classic Core PHP extensions utilizing modern Heartbeat API schemas

How to build custom Classic Core PHP extensions utilizing modern Heartbeat API schemas

Understanding the Heartbeat API and Extension Architecture

The WordPress Heartbeat API, while often associated with real-time features like auto-saves and online user indicators, provides a robust foundation for building custom background processes and data synchronization mechanisms within the WordPress ecosystem. This API operates on AJAX requests that fire at regular intervals, allowing for communication between the browser and the server. To leverage this for custom extensions, we need to understand its core components: the `wp_heartbeat_send_data` filter and the `wp_heartbeat_tick` action.

Building a custom “Classic Core” PHP extension implies creating a self-contained PHP file that can be included or managed independently, rather than a traditional plugin structure. This approach is suitable for highly specific, performance-critical functionalities that might not warrant a full plugin. For this guide, we’ll focus on creating a simple extension that synchronizes a custom piece of data to the WordPress database at regular intervals, demonstrating how to hook into the Heartbeat API.

Setting Up the Custom Extension File

We’ll start by creating a standalone PHP file. For demonstration purposes, let’s name it custom-heartbeat-sync.php. This file will contain our logic for interacting with the Heartbeat API. To ensure this file is loaded, we can either include it manually in wp-config.php (not recommended for production but useful for local development) or, more appropriately, create a minimal plugin structure around it.

For a more robust setup, let’s assume this file will reside within a custom plugin directory, e.g., wp-content/plugins/my-custom-extension/my-custom-extension.php. The core logic will be within this file.

Registering a Custom Heartbeat Interval

The Heartbeat API allows you to define custom intervals for its ticks. By default, it ticks every 15-60 seconds. We can override this or add our own specific intervals. To do this, we’ll use the heartbeat_intervals filter.

Defining the Interval in PHP

Add the following PHP code to your my-custom-extension.php file:

<?php
/*
Plugin Name: My Custom Heartbeat Sync
Description: Synchronizes custom data using the Heartbeat API.
Version: 1.0
Author: Antigravity
*/

// Prevent direct access to the file
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

/**
 * Define custom heartbeat intervals.
 *
 * @param array $intervals Existing intervals.
 * @return array Modified intervals.
 */
function my_custom_heartbeat_intervals( $intervals ) {
    // Add a custom interval for our data sync, e.g., every 30 seconds.
    // The key is a unique identifier for your interval.
    $intervals['my_custom_data_sync'] = 30000; // 30000 milliseconds = 30 seconds
    return $intervals;
}
add_filter( 'heartbeat_intervals', 'my_custom_heartbeat_intervals' );

// ... rest of the code will follow
?>

In this snippet, we’ve added a new interval named my_custom_data_sync that will trigger every 30 seconds (30000 milliseconds). The key my_custom_data_sync is arbitrary but should be unique to avoid conflicts.

Sending Custom Data with Heartbeat

The core of our custom extension lies in sending and receiving data via the Heartbeat API. We use the wp_heartbeat_send_data filter to add our custom data to the Heartbeat payload when it’s sent from the browser to the server. We also need to process this data on the server.

Implementing Data Sending and Processing

We’ll extend our my-custom-extension.php file with the following functions:

/**
 * Add custom data to the Heartbeat payload.
 *
 * @param array $data Data to send.
 * @param array $screen Current screen information.
 * @return array Modified data.
 */
function my_custom_heartbeat_send_data( $data, $screen ) {
    // Only send data when our custom interval is supposed to tick.
    // This is a basic check; more sophisticated logic might be needed.
    // We can also check $screen['base'] to target specific admin pages.
    if ( isset( $_POST['data']['my_custom_data_sync'] ) ) {
        // Add our custom data. This could be anything:
        // - A timestamp of the last sync
        // - A status flag
        // - A small piece of configuration
        $data['my_custom_extension_data'] = array(
            'last_sync_timestamp' => time(),
            'custom_setting_value' => get_option( 'my_custom_setting', 'default_value' ),
        );
    }
    return $data;
}
add_filter( 'wp_heartbeat_send_data', 'my_custom_heartbeat_send_data', 10, 2 );

/**
 * Process incoming Heartbeat data.
 *
 * @param array $response Response data.
 * @param array $data Incoming data from the client.
 * @return array Modified response data.
 */
function my_custom_heartbeat_process_data( $response, $data ) {
    // Check if our custom data is present in the incoming payload.
    if ( isset( $data['my_custom_extension_data'] ) ) {
        $incoming_data = $data['my_custom_extension_data'];

        // Example: Update a custom option in the database if the timestamp is newer.
        // In a real-world scenario, you'd have more robust validation and logic.
        $current_stored_timestamp = get_option( 'my_custom_extension_last_sync' );
        if ( ! $current_stored_timestamp || $incoming_data['last_sync_timestamp'] > $current_stored_timestamp ) {
            update_option( 'my_custom_extension_last_sync', $incoming_data['last_sync_timestamp'] );
            // You could also update other options or perform actions here.
            // For example, if this data sync is meant to update a setting:
            // update_option( 'my_custom_setting', $incoming_data['custom_setting_value'] );
        }

        // You can also send data back to the client in the response.
        $response['my_custom_extension_feedback'] = 'Data processed successfully.';
    }
    return $response;
}
add_filter( 'heartbeat_received', 'my_custom_heartbeat_process_data', 10, 2 );

In my_custom_heartbeat_send_data, we check if our custom interval key (my_custom_data_sync) is present in the POST data. If it is, we add our custom data array, my_custom_extension_data, to the payload. This data includes a timestamp and a value retrieved from WordPress options.

The my_custom_heartbeat_process_data function hooks into heartbeat_received, which fires on the server after the Heartbeat AJAX request is received. Here, we inspect the incoming $data for our custom key. If found, we can perform actions, such as updating WordPress options based on the received data. We also demonstrate how to send data back to the client by adding it to the $response array.

Client-Side Handling (Optional but Recommended)

While the server-side logic handles the core synchronization, you might want to interact with the data on the client-side (e.g., in the WordPress admin area). The Heartbeat API also provides JavaScript hooks for this.

Enqueuing a JavaScript File

First, we need to enqueue a JavaScript file that will contain our client-side Heartbeat logic. This should be done only for the admin area.

/**
 * Enqueue custom JavaScript for Heartbeat interaction.
 */
function my_custom_heartbeat_enqueue_scripts( $hook_suffix ) {
    // Only load on admin pages
    if ( ! is_admin() ) {
        return;
    }

    // Enqueue the script
    wp_enqueue_script(
        'my-custom-heartbeat-script',
        plugin_dir_url( __FILE__ ) . 'js/custom-heartbeat-admin.js',
        array( 'jquery', 'heartbeat' ), // Dependencies: jQuery and Heartbeat API script
        filemtime( plugin_dir_path( __FILE__ ) . 'ઈ/custom-heartbeat-admin.js' ), // Cache busting
        true // Load in footer
    );

    // Localize script with data if needed
    wp_localize_script( 'my-custom-heartbeat-script', 'myCustomHeartbeatData', array(
        'ajax_url' => admin_url( 'admin-ajax.php' ),
        'nonce'    => wp_create_nonce( 'my_custom_heartbeat_nonce' ),
    ) );
}
add_action( 'admin_enqueue_scripts', 'my_custom_heartbeat_enqueue_scripts' );

This code enqueues a JavaScript file located at js/custom-heartbeat-admin.js. It depends on jquery and heartbeat, ensuring they are loaded first. We also use wp_localize_script to pass PHP data (like the AJAX URL and a nonce for security) to our JavaScript file.

JavaScript for Client-Side Interaction

Create the js/custom-heartbeat-admin.js file with the following content:

jQuery(document).ready(function($) {
    // Ensure the heartbeat is enabled
    if (typeof wp !== 'undefined' && typeof wp.heartbeat !== 'undefined') {
        var heartbeat = wp.heartbeat;

        // Listen for the heartbeat tick event
        heartbeat.connectGlobal(); // Connect to the global heartbeat

        // Custom interval tick event
        // The key 'my_custom_data_sync' must match the one defined in PHP
        $(document).on('heartbeat-tick', function(e, data) {
            // Check if our custom data is present in the response from the server
            if (data['my_custom_extension_feedback']) {
                console.log('Heartbeat feedback:', data['my_custom_extension_feedback']);
                // You can update the UI here based on the feedback
                // For example, display a message to the user.
            }

            // You can also send additional data on specific ticks if needed,
            // but our primary data sending is handled by wp_heartbeat_send_data filter.
            // If you needed to send data *only* on this specific tick, you could do:
            // if (data.hasOwnProperty('my_custom_data_sync')) {
            //     heartbeat.enqueue({
            //         'my_custom_extension_data': {
            //             'client_message': 'Hello from JS!'
            //         }
            //     });
            // }
        });

        // Optional: Handle heartbeat connection errors
        $(document).on('heartbeat-error', function(e, error) {
            console.error('Heartbeat error:', error);
        });

        // Optional: Handle heartbeat connection established
        $(document).on('heartbeat-connected', function() {
            console.log('Heartbeat connected.');
        });

        // Optional: Handle heartbeat connection stopped
        $(document).on('heartbeat-stopped', function() {
            console.log('Heartbeat stopped.');
        });

    } else {
        console.error('WordPress Heartbeat API not found.');
    }
});

This JavaScript code uses jQuery to hook into the Heartbeat API events. It listens for heartbeat-tick, where it can inspect the data received from the server (like our my_custom_extension_feedback) and update the UI accordingly. It also shows how to connect to the global heartbeat and handle connection status events.

Testing and Debugging

To test your custom extension:

  • Ensure your custom extension file is correctly placed and activated (if using a plugin structure).
  • Navigate to any WordPress admin page.
  • Open your browser’s developer console (usually by pressing F12).
  • Look for messages in the console related to Heartbeat (e.g., “Heartbeat connected.”, “Heartbeat feedback: …”).
  • You can also use browser network tools to inspect the AJAX requests being made to admin-ajax.php. Look for requests with the action heartbeat. Examine the request payload and response.
  • Check your WordPress database (e.g., using phpMyAdmin) for the options you are updating (my_custom_extension_last_sync, my_custom_setting) to verify they are being modified as expected.

For more detailed debugging, you can temporarily add error_log() statements in your PHP functions to write messages to your server’s PHP error log. For instance, within my_custom_heartbeat_process_data:

// Inside my_custom_heartbeat_process_data function:
if ( isset( $data['my_custom_extension_data'] ) ) {
    error_log( 'Heartbeat received custom data: ' . print_r( $data['my_custom_extension_data'], true ) );
    // ... rest of your processing logic
}

Advanced Considerations and Best Practices

When building production-ready extensions using the Heartbeat API:

  • Security: Always use nonces for any AJAX requests initiated from JavaScript. The wp_create_nonce() and check_ajax_referer() functions are essential.
  • Performance: Be mindful of the frequency of your Heartbeat ticks. Very frequent ticks can increase server load. Only use custom intervals when necessary. Optimize your server-side processing logic to be as efficient as possible.
  • Scope: Use $screen and $hook_suffix in your filters and actions to ensure your Heartbeat logic only runs on relevant admin pages or contexts. This prevents unnecessary processing.
  • Data Validation: Thoroughly validate any data received from the client before processing or saving it to the database.
  • Error Handling: Implement robust error handling on both the server and client sides.
  • User Experience: If your Heartbeat activity impacts the user interface, ensure it’s smooth and non-disruptive. Provide clear feedback to the user if necessary.
  • Alternatives: For complex background tasks that don’t require real-time browser interaction, consider using WordPress Cron or dedicated background job queues. The Heartbeat API is best suited for tasks that benefit from periodic, short-lived server-client communication.

By following these guidelines and leveraging the Heartbeat API’s filtering and action hooks, you can build powerful, custom background functionalities for your WordPress sites, extending its core capabilities in a controlled and efficient manner.

Primary Sidebar

A little about the Author

Having 12+ Years of Experience in Software Development, Vinay is a principal software architect, senior systems engineer, and elite technical consultant. He specializes in bespoke PHP/WordPress development, high-performance Magento 2 & Shopify architectures, custom plugin/theme development from scratch, and legacy code modernization (including VB6, VB.NET, PyQt, and Crystal Reports). Known for solving complex database bottlenecks, speed optimization (Core Web Vitals), and advanced security code auditing, Vinay engineers production-ready systems designed to scale under heavy concurrent load conditions.



Chat on WhatsApp

Recent Posts

  • Implementing automated compliance reporting for custom online course lessons ledgers using mpdf engine
  • WordPress Development Recipe: Efficient binary storage and retrieval in custom tables using Anonymous Classes
  • Step-by-Step Guide to building a custom interactive mapping module block for Gutenberg using Vanilla JS Web Components
  • WordPress Development Recipe: Secure token-based API authentication for Stripe Payment webhook in custom plugins
  • Troubleshooting namespace class loading collisions in production when using modern Genesis child themes wrappers

Categories

  • apache (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (650)
  • Desktop Applications (14)
  • DevOps (7)
  • DevOps & Cloud Scaling (962)
  • Django (1)
  • Laravel (4)
  • Migration & Architecture (192)
  • Mobile Applications (24)
  • MySQL (1)
  • Performance & Optimization (858)
  • PHP (5)
  • PHP Development (38)
  • Plugins & Themes (244)
  • Programming Languages (9)
  • Python (20)
  • Ruby on Rails (1)
  • Security & Compliance (629)
  • SEO & Growth (492)
  • Server (23)
  • Ubuntu (9)
  • VB6 & VB.NET (8)
  • Web Applications & Frontend (19)
  • Web Assembly (Wasm) (2)
  • WordPress (22)
  • WordPress Plugin Development (299)
  • WordPress Theme Development (357)

Recent Posts

  • Implementing automated compliance reporting for custom online course lessons ledgers using mpdf engine
  • WordPress Development Recipe: Efficient binary storage and retrieval in custom tables using Anonymous Classes
  • Step-by-Step Guide to building a custom interactive mapping module block for Gutenberg using Vanilla JS Web Components

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (858)
  • Debugging & Troubleshooting (650)
  • Security & Compliance (629)
  • SEO & Growth (492)
  • Business & Monetization (390)

Our Products

  • ERP & LMS Systems (4)
  • Directories & Marketplaces (4)
  • Healthcare Portals (3)
  • Point of Sale (POS) (2)
  • E-Commerce Engines (2)

Our Services

  • E-Commerce Development (10)
  • WordPress Development (8)
  • Python & Desktop GUI (7)
  • General Consulting (7)
  • Legacy Modernization (5)
  • Mobile App Development (4)

Copyright © 2026 · Vinay Vengala