• 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 WooCommerce core overrides extensions utilizing modern Heartbeat API schemas

How to build custom WooCommerce core overrides extensions utilizing modern Heartbeat API schemas

Leveraging the Heartbeat API for Custom WooCommerce Core Overrides

While direct modification of WooCommerce core files is strongly discouraged due to upgrade complications, there are scenarios where specific behaviors need to be altered or extended. The WordPress Heartbeat API, often overlooked for its potential beyond simple autosave functionality, offers a robust mechanism for real-time communication between the browser and the server. This post will demonstrate how to harness the Heartbeat API to implement custom overrides for WooCommerce core functionalities, ensuring a maintainable and upgrade-safe solution.

Understanding the Heartbeat API

The Heartbeat API, introduced in WordPress 3.6, provides a persistent connection that allows JavaScript in the browser to send requests to the server at regular intervals (by default, every 15-60 seconds). This is primarily used for features like post locking and autosaving. However, its underlying mechanism, the `heartbeat_received` and `heartbeat_send` filters, can be repurposed for custom data synchronization and action triggering.

The core idea is to send custom data from the client-side JavaScript to the server via Heartbeat requests, process this data on the server using PHP hooks, and then potentially send back data to update the client. This is particularly useful for real-time updates in the WooCommerce admin, such as modifying order statuses, updating inventory counts, or triggering custom actions based on user activity without full page reloads.

Scenario: Real-time Inventory Adjustment on Product Edit Screen

Let’s consider a common requirement: automatically adjusting the stock quantity of a related product when the stock of a primary product is modified on the WooCommerce product edit screen. Direct modification of the `save_post` hook for products can be complex and prone to race conditions. Using the Heartbeat API allows us to trigger this adjustment more granularly and with better control.

Client-Side JavaScript for Heartbeat Data Transmission

We’ll enqueue a custom JavaScript file that listens for changes on the stock quantity input field and sends this data via Heartbeat. This script should only run on the product edit screen.

First, create a JavaScript file, for example, wp-content/plugins/my-custom-woo-overrides/assets/js/admin-product-heartbeat.js.

assets/js/admin-product-heartbeat.js

jQuery(document).ready(function($) {
    // Target only the product edit screen
    if (typeof wc_admin_product_edit_params === 'undefined' || $('#woocommerce_product_data_tabs').length === 0) {
        return;
    }

    var $stock_input = $('#_stock');
    var original_stock_value = $stock_input.val();

    // Listen for changes on the stock input
    $stock_input.on('input', function() {
        var current_stock_value = $(this).val();
        // Only send if the value has actually changed
        if (current_stock_value !== original_stock_value) {
            // Trigger a heartbeat event with custom data
            $(document).trigger('heartbeat-send', {
                'my_custom_woo_data': {
                    'action': 'update_related_stock',
                    'product_id': $('#post_ID').val(),
                    'new_stock': current_stock_value
                }
            });
            original_stock_value = current_stock_value; // Update original value for next comparison
        }
    });

    // Optional: Handle Heartbeat response if needed
    $(document).on('heartbeat-tick', function(e, data) {
        if (data.my_custom_woo_data && data.my_custom_woo_data.message) {
            console.log('Heartbeat response:', data.my_custom_woo_data.message);
            // Example: Display a success message or update UI elements
        }
    });
});

Enqueuing the JavaScript File

Now, we need to enqueue this script on the appropriate admin pages. We’ll use the `admin_enqueue_scripts` hook.

my-custom-woo-overrides.php (Main Plugin File)

<?php
/**
 * Plugin Name: My Custom WooCommerce Overrides
 * Description: Implements custom WooCommerce overrides using the Heartbeat API.
 * Version: 1.0.0
 * Author: Your Name
 * Author URI: yourwebsite.com
 * Text Domain: my-custom-woo
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly.
}

/**
 * Enqueue admin scripts.
 */
function mco_enqueue_admin_scripts( $hook ) {
    // Only load on the product edit screen.
    if ( 'post.php' !== $hook && 'post-new.php' !== $hook ) {
        return;
    }

    // Check if it's a WooCommerce product post type.
    global $post_type;
    if ( 'product' !== $post_type ) {
        return;
    }

    wp_enqueue_script(
        'my-custom-woo-admin-product-heartbeat',
        plugin_dir_url( __FILE__ ) . 'assets/js/admin-product-heartbeat.js',
        array( 'jquery', 'heartbeat' ), // Dependencies: jQuery and Heartbeat API
        '1.0.0',
        true // Load in footer
    );

    // Localize script if needed, e.g., for product ID or other dynamic data.
    // wp_localize_script('my-custom-woo-admin-product-heartbeat', 'mco_admin_params', array(
    //     'product_id' => get_the_ID(),
    // ));
}
add_action( 'admin_enqueue_scripts', 'mco_enqueue_admin_scripts' );

/**
 * Process Heartbeat data.
 *
 * @param array $response Data to send back to the browser.
 * @param array $data Data sent from the browser.
 * @return array Modified response data.
 */
function mco_heartbeat_received( $response, $data ) {
    if ( isset( $data['my_custom_woo_data'] ) && is_array( $data['my_custom_woo_data'] ) ) {
        $custom_data = $data['my_custom_woo_data'];

        if ( isset( $custom_data['action'] ) && 'update_related_stock' === $custom_data['action'] ) {
            $product_id = isset( $custom_data['product_id'] ) ? intval( $custom_data['product_id'] ) : 0;
            $new_stock  = isset( $custom_data['new_stock'] ) ? sanitize_text_field( $custom_data['new_stock'] ) : ''; // Keep as string for now, WC handles conversion

            if ( $product_id && '' !== $new_stock ) {
                // --- Core Override Logic ---
                // In a real-world scenario, you'd fetch related products here
                // and update their stock based on $new_stock.
                // For this example, we'll just log the action.

                $product = wc_get_product( $product_id );
                if ( $product ) {
                    // Example: Update the stock for the current product itself (for demonstration)
                    // In a real override, you'd find related products and update them.
                    $product->set_stock_quantity( $new_stock );
                    $product->save();

                    $response['my_custom_woo_data'] = array(
                        'message' => sprintf( 'Stock for product ID %d updated to %s. Related stock adjustments would occur here.', $product_id, $new_stock ),
                    );
                } else {
                    $response['my_custom_woo_data'] = array(
                        'error' => sprintf( 'Product with ID %d not found.', $product_id ),
                    );
                }
            } else {
                $response['my_custom_woo_data'] = array(
                    'error' => 'Missing product ID or new stock value.',
                );
            }
        }
    }
    return $response;
}
add_filter( 'heartbeat_received', 'mco_heartbeat_received', 10, 2 );

/**
 * Modify Heartbeat intervals.
 *
 * @param array $settings Heartbeat settings.
 * @return array Modified settings.
 */
function mco_heartbeat_settings( $settings ) {
    // Reduce interval for faster updates on the product edit screen.
    // Be cautious with very low intervals as it can increase server load.
    // Default is 60 seconds for non-admin, 15 seconds for admin.
    // We can set it lower if needed, but 15s is usually sufficient.
    // $settings['interval'] = 5; // Example: 5 seconds
    return $settings;
}
// Only apply custom interval to admin pages, or specific ones if needed.
// add_filter( 'heartbeat_settings', 'mco_heartbeat_settings' );

Explanation of the PHP Code

1. Plugin Setup: Standard WordPress plugin header and security check.

2. `mco_enqueue_admin_scripts`: This function hooks into `admin_enqueue_scripts`. It checks if the current page is a `post.php` or `post-new.php` and if the post type is `product`. If so, it enqueues our custom JavaScript file, ensuring it has `jquery` and `heartbeat` as dependencies.

3. `mco_heartbeat_received`: This is the core of our server-side logic. It hooks into the `heartbeat_received` filter. WordPress sends data from the client to this filter.

  • We check if our custom data key (`my_custom_woo_data`) exists in the incoming `$data`.
  • We then check for the specific action (`update_related_stock`).
  • We extract and sanitize `product_id` and `new_stock`.
  • Crucially, we use `wc_get_product()` to retrieve the product object and `set_stock_quantity()` and `save()` to update its stock. This is where you would implement your logic to find and update related products.
  • Finally, we add a response back to `$response` which will be sent to the client and can be handled by the `heartbeat-tick` event in our JavaScript.

4. `mco_heartbeat_settings` (Commented Out): This filter allows you to modify Heartbeat settings, such as the interval. For real-time updates, you might consider reducing the interval, but do so cautiously to avoid excessive server load. The default admin interval of 15 seconds is often sufficient.

Implementing the “Override” Logic

In the `mco_heartbeat_received` function, the section marked “--- Core Override Logic ---” is where you’d place your custom business logic. Instead of directly modifying WooCommerce’s `save_post` actions for products, we’re using the Heartbeat API as a trigger. This approach:

  • Decouples Logic: Your custom code is separate from WooCommerce core.
  • Real-time Feedback: Allows for near-instantaneous updates without full page reloads.
  • Controlled Execution: You decide precisely when and how the override logic runs, triggered by specific user interactions.
  • Maintainability: Significantly easier to manage during WooCommerce updates.

For the example of adjusting related product stock, you would typically:

  • Query for products related to the current `$product_id` (e.g., via product meta, custom tables, or predefined relationships).
  • Calculate the new stock for these related products based on the `$new_stock` value of the primary product.
  • Use `wc_get_product()` and `set_stock_quantity()`/`save()` for each related product.
  • Handle potential edge cases like out-of-stock thresholds or stock management settings.

Advanced Considerations and Best Practices

Security

Always sanitize and validate all data received from the client-side. Use WordPress nonces if you were to implement actions that modify critical data beyond simple stock updates, although Heartbeat’s AJAX requests are generally considered secure within the logged-in WordPress environment.

Performance

Be mindful of the Heartbeat interval. A very low interval (e.g., 1-5 seconds) can lead to increased server load, especially on busy sites or during peak editing times. Profile your Heartbeat requests and server performance. Avoid complex database queries or heavy processing within the `heartbeat_received` callback. If complex operations are needed, consider using WordPress Transients or background processing (like WP-Cron or dedicated job queues) triggered by the Heartbeat callback.

Error Handling and User Feedback

Provide clear feedback to the user. If an operation fails, use the response data to display an error message in the browser using JavaScript. The `heartbeat-tick` event is ideal for this.

Scope and Specificity

Ensure your JavaScript and PHP code are scoped correctly. The example limits the script to product edit screens. For PHP, use conditional checks (`is_admin()`, `get_current_screen()`, `current_user_can()`) to ensure your Heartbeat callbacks only execute when and where necessary.

Alternatives and When to Use Them

While Heartbeat is excellent for real-time, in-browser interactions, consider these alternatives:

  • AJAX Endpoints: For actions that don’t need to be tied to a regular interval, create custom REST API endpoints or standard AJAX handlers.
  • WP-Cron: For scheduled or deferred tasks.
  • `save_post` hook: For actions that must occur precisely when a post is saved, but be aware of potential complexities. Heartbeat can be used to *trigger* a `save_post` action if needed, but it’s often more direct to use `save_post` itself if the timing is critical and the logic is simple.

The Heartbeat API shines when you need to synchronize data or trigger actions based on user activity *while* they are interacting with a specific admin page, without requiring a manual save or refresh.

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

  • WordPress Development Recipe: Secure token-based API authentication for Shopify headless API in custom plugins
  • Advanced Diagnostics: Locating slow Action-hook Event Mediator query bottlenecks in WooCommerce custom checkout pipelines
  • WordPress Development Recipe: Leveraging Constructor Property Promotion to build type-safe, auto-wired hooks
  • How to design a modular Repository and Interface Structure architecture for enterprise-level custom plugins
  • Building secure B2B pricing grids with custom WP HTTP API endpoints and role overrides

Categories

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

Recent Posts

  • WordPress Development Recipe: Secure token-based API authentication for Shopify headless API in custom plugins
  • Advanced Diagnostics: Locating slow Action-hook Event Mediator query bottlenecks in WooCommerce custom checkout pipelines
  • WordPress Development Recipe: Leveraging Constructor Property Promotion to build type-safe, auto-wired hooks

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (872)
  • Debugging & Troubleshooting (658)
  • Security & Compliance (639)
  • 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