• 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 » WordPress Development Recipe: Real-time custom event triggers using WebSockets and Block Patterns API

WordPress Development Recipe: Real-time custom event triggers using WebSockets and Block Patterns API

Leveraging WebSockets for Real-time WordPress Event Triggers

This recipe details a robust method for implementing real-time custom event triggers within WordPress, specifically targeting expert developers. We’ll combine the power of WebSockets for instantaneous communication with WordPress’s Block Patterns API for structured content generation. This approach is ideal for dynamic dashboards, collaborative editing features, or any scenario requiring immediate feedback to multiple connected clients without constant polling.

Prerequisites and Setup

Before diving into the code, ensure you have the following:

  • A WordPress installation (local or remote).
  • Composer installed for PHP dependency management.
  • Node.js and npm/yarn for JavaScript development.
  • A WebSocket server implementation. For this example, we’ll use Ratchet, a PHP WebSocket library.

First, let’s set up the Ratchet WebSocket server. Navigate to your WordPress root directory and create a new directory for your WebSocket server, e.g., ws-server. Inside this directory, initialize a Composer project:

  • cd ws-server
  • composer init (accept defaults or configure as needed)
  • composer require cboden/ratchet

Implementing the WebSocket Server

Create a file named server.php within the ws-server directory. This script will handle incoming WebSocket connections and broadcast messages.

clients = new \SplObjectStorage;
    }

    public function onOpen(ConnectionInterface $conn) {
        // Store the new connection to send messages to later
        $this->clients->attach($conn);
        echo "New connection! ({$conn->resourceId})\n";
    }

    public function onMessage(ConnectionInterface $from, $msg) {
        // In a real-world scenario, you'd parse $msg to determine event type and data.
        // For this example, we'll assume messages are broadcast directly.
        echo sprintf('Message received from %d: %s' . "\n", $from->resourceId, $msg);

        // Broadcast the message to all other clients
        foreach ($this->clients as $client) {
            if ($from !== $client) {
                // $client->send($msg); // Uncomment to broadcast to all *other* clients
                $client->send($msg); // Broadcast to all clients, including sender
            }
        }
    }

    public function onClose(ConnectionInterface $conn) {
        // The connection is closed, remove it, as we're not sending an open message
        $this->clients->detach($conn);
        echo "Connection {$conn->resourceId} has disconnected\n";
    }

    public function onError(ConnectionInterface $conn, \Exception $e) {
        echo "An error has occurred: {$e->getMessage()}\n";
        $conn->close();
    }

    /**
     * Custom method to trigger an event and broadcast it.
     * This method would be called from your WordPress plugin.
     */
    public function triggerEvent(string $eventName, array $eventData) {
        $message = json_encode(['event' => $eventName, 'data' => $eventData]);
        echo "Triggering event: {$eventName} with data: " . json_encode($eventData) . "\n";
        foreach ($this->clients as $client) {
            $client->send($message);
        }
    }
}

// Create a new WebSocket server instance
$server = IoServer::factory(
    new HttpServer(
        new WsServer(
            new EventBroadcaster()
        )
    ),
    8080 // Port to listen on
);

echo "WebSocket server started on port 8080...\n";
$server->run();

To run the server, execute the following command from the ws-server directory:

php server.php

Keep this terminal window open. The server will listen for connections on ws://localhost:8080.

WordPress Plugin Integration

Now, let’s create a WordPress plugin to interact with our WebSocket server. Create a new plugin directory, e.g., wp-content/plugins/realtime-events, and add a main plugin file, realtime-events.php.

 sprintf( 'ws://%s:%d', WEBSOCKET_SERVER_HOST, WEBSOCKET_SERVER_PORT ),
        )
    );

    // Enqueue Block Editor script for Block Patterns API integration
    wp_enqueue_script(
        'realtime-events-editor',
        plugin_dir_url( __FILE__ ) . 'js/editor.js',
        array( 'wp-blocks', 'wp-element', 'wp-editor', 'wp-components', 'wp-data' ),
        '1.0',
        true
    );

    // Localize script for editor-specific data if needed
    // wp_localize_script('realtime-events-editor', 'editorConfig', array(...));
}
add_action( 'enqueue_block_editor_assets', 'realtime_events_enqueue_scripts' );

/**
 * Register a custom block pattern.
 */
function realtime_events_register_block_pattern() {
    if ( ! function_exists( 'register_block_pattern' ) ) {
        return;
    }

    register_block_pattern(
        'realtime-events/dynamic-message',
        array(
            'title'       => __( 'Dynamic Realtime Message', 'realtime-events' ),
            'description' => __( 'Displays a message updated in real-time via WebSocket.', 'realtime-events' ),
            'categories'  => array( 'realtime' ),
            'content'     => '

Waiting for real-time update...

', 'keywords' => array( 'realtime', 'dynamic', 'websocket', 'message' ), ) ); } add_action( 'init', 'realtime_events_register_block_pattern' ); /** * Add a custom category for block patterns. */ function realtime_events_register_block_pattern_category( $categories ) { $categories = array_merge( $categories, array( array( 'name' => 'realtime', 'label' => __( 'Realtime', 'realtime-events' ), ), ) ); return $categories; } add_filter( 'block_pattern_categories', 'realtime_events_register_block_pattern_category', 10, 1 ); /** * Example of triggering a WebSocket event from the backend. * This could be hooked to any WordPress action or filter. */ function trigger_example_websocket_event() { // In a real plugin, you'd need a way to access the running WebSocket server instance. // This is a simplified example. A more robust solution might involve a REST API endpoint // that communicates with the WebSocket server, or a persistent connection manager. // For demonstration, we'll simulate sending a message. // In a production environment, you'd likely have a dedicated service or // a mechanism to communicate with your running WebSocket server process. // Example: Hooking into post save // add_action('save_post', 'trigger_websocket_on_post_save', 10, 3); } // add_action('plugins_loaded', 'trigger_example_websocket_event'); // Uncomment to run example setup /** * Example function to trigger WebSocket event on post save. * This requires a mechanism to communicate with the running WebSocket server. * For simplicity, this example assumes a hypothetical function `send_websocket_message`. */ function trigger_websocket_on_post_save( $post_id, $post, $update ) { if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { return; } if ( wp_is_post_revision( $post_id ) ) { return; } // Hypothetical function to send message to WebSocket server. // In a real application, this would involve making an HTTP request to a // dedicated API endpoint on your server that then forwards the message // to the WebSocket server, or using a message queue. // For this example, we'll just log it. $message_data = array( 'post_id' => $post_id, 'title' => $post->post_title, 'status' => $post->post_status, 'event' => 'post_updated', ); // Simulate sending the message. Replace with actual communication method. error_log( 'Simulating WebSocket message send: ' . json_encode( $message_data ) ); // If you had a direct PHP connection to the WebSocket server (not recommended for production due to blocking): /* try { $context = new ZMQContext(); $socket = $context->getTransport('tcp://127.0.0.1:5555'); // Example ZeroMQ port $socket->send(json_encode($message_data)); } catch (Exception $e) { error_log('Failed to send WebSocket message: ' . $e->getMessage()); } */ } // add_action( 'save_post', 'trigger_websocket_on_post_save', 10, 3 ); ?>

Client-Side JavaScript for WebSocket Connection

Create a js directory inside your plugin folder and add a file named client.js. This script will establish the WebSocket connection and handle incoming messages.

 {
    const websocketUrl = realtimeEventsConfig.websocketUrl;
    let websocket;

    function connectWebSocket() {
        websocket = new WebSocket(websocketUrl);

        websocket.onopen = () => {
            console.log('WebSocket connection established.');
            // Optionally send a message to the server upon connection
            // websocket.send('Hello Server!');
        };

        websocket.onmessage = (event) => {
            console.log('Message from server: ', event.data);
            try {
                const data = JSON.parse(event.data);
                if (data.event === 'post_updated' && data.data && data.data.post_id) {
                    // Update a specific element, e.g., a paragraph with a real-time message
                    const messageDisplay = document.getElementById('realtime-message-display');
                    if (messageDisplay) {
                        messageDisplay.textContent = `Post ${data.data.post_id} (${data.data.title}) was updated. Status: ${data.data.status}`;
                    }
                } else if (data.event && data.data) {
                    // Handle other custom events
                    console.log(`Received custom event: ${data.event}`, data.data);
                    // You could trigger custom DOM events or update other UI elements here
                    // Example: document.dispatchEvent(new CustomEvent(data.event, { detail: data.data }));
                }
            } catch (e) {
                console.error('Failed to parse message or update UI:', e);
            }
        };

        websocket.onclose = (event) => {
            console.log('WebSocket connection closed:', event.code, event.reason);
            // Attempt to reconnect after a delay
            setTimeout(connectWebSocket, 5000); // Reconnect every 5 seconds
        };

        websocket.onerror = (error) => {
            console.error('WebSocket error:', error);
            websocket.close(); // Ensure close is called to trigger onclose
        };
    }

    connectWebSocket();
});

Block Editor Integration with Block Patterns API

The Block Patterns API allows us to pre-define reusable content structures. We’ve already registered a basic pattern in realtime-events.php. The JavaScript in client.js targets an element within this pattern (#realtime-message-display) to update it dynamically.

For more advanced dynamic content within blocks, you would typically use dynamic blocks or server-side rendering. However, for real-time updates driven by external events, client-side JavaScript is the most efficient. The Block Patterns API serves as the entry point for placing these dynamic elements into content.

Create a file named editor.js in your plugin’s js directory. This script can be used to register custom block styles, attributes, or even custom blocks that might interact with real-time data, though for this specific recipe, client.js handles the dynamic updates.

 {
    // Example: Registering a custom block style for paragraphs
    wp.blocks.registerBlockStyle('core/paragraph', {
        name: 'realtime-highlight',
        label: 'Realtime Highlight',
    });

    // Example: Adding a custom attribute to a block (requires a custom block)
    // wp.hooks.addFilter(
    //     'blocks.registerBlockType',
    //     'realtime-events/add-custom-attribute',
    //     (settings, name) => {
    //         if (name === 'core/paragraph') { // Apply to paragraphs
    //             return {
    //                 ...settings,
    //                 attributes: {
    //                     ...settings.attributes,
    //                     realtimeId: {
    //                         type: 'string',
    //                         default: '',
    //                     },
    //                 },
    //             };
    //         }
    //         return settings;
    //     }
    // );

    // Example: Modifying block save function to include custom attribute
    // wp.hooks.addFilter(
    //     'blocks.getSaveContent.extraProps',
    //     'realtime-events/add-realtime-id-attribute',
    //     (extraProps, blockType, attributes) => {
    //         if (blockType.name === 'core/paragraph' && attributes.realtimeId) {
    //             return { ...extraProps, 'data-realtime-id': attributes.realtimeId };
    //         }
    //         return extraProps;
    //     }
    // );

    console.log('Realtime Events editor script loaded.');
});

Triggering Events from WordPress Backend

The most challenging part of integrating a separate WebSocket server with WordPress is reliably triggering events from the PHP backend. Since the WebSocket server runs as a separate process, direct PHP calls are not feasible without complex inter-process communication (IPC) mechanisms.

Here are common strategies:

  • REST API Endpoint: Create a custom WordPress REST API endpoint. Your PHP code triggers an event by making an HTTP request (e.g., POST) to this endpoint. The endpoint handler then communicates with the WebSocket server. This is a clean, decoupled approach.
  • Message Queue (e.g., Redis, RabbitMQ): Your WordPress plugin publishes messages to a queue. A separate worker process (or the WebSocket server itself, if it supports listening to queues) consumes these messages and broadcasts them via WebSockets. This is highly scalable and resilient.
  • Direct IPC (Advanced): If your WebSocket server is running on the same machine and you control its startup, you might use mechanisms like ZeroMQ or sockets directly from PHP. This requires careful management of the WebSocket server process and is generally less robust for typical WordPress hosting environments.

For the realtime-events.php example, we’ve included a commented-out hook for save_post and a placeholder function trigger_websocket_on_post_save. To make this functional, you would implement one of the above strategies. For instance, using the REST API:

 'POST',
        'callback' => 'handle_rest_api_trigger',
        'permission_callback' => '__return_true', // Adjust permissions as needed
    ) );
} );

function handle_rest_api_trigger( WP_REST_Request $request ) {
    $event_name = $request->get_param( 'event' );
    $event_data = $request->get_param( 'data' );

    if ( ! $event_name || ! is_array( $event_data ) ) {
        return new WP_Error( 'invalid_params', 'Event name and data array are required.', array( 'status' => 400 ) );
    }

    // --- Communication with WebSocket Server ---
    // Option 1: HTTP request to a dedicated API on your WS server
    // $ws_server_api_url = 'http://localhost:8081/broadcast'; // Assuming WS server has a broadcast API
    // $response = wp_remote_post( $ws_server_api_url, array(
    //     'body' => json_encode( array( 'event' => $event_name, 'data' => $event_data ) ),
    //     'headers' => array( 'Content-Type' => 'application/json' ),
    // ) );
    // if ( is_wp_error( $response ) ) {
    //     return new WP_Error( 'ws_communication_error', 'Failed to communicate with WebSocket server.', array( 'status' => 500 ) );
    // }
    // --- End Option 1 ---

    // Option 2: Direct socket connection (less recommended for general WP hosting)
    // This requires the WebSocket server to be listening on a specific port for commands.
    $socket = @fsockopen( WEBSOCKET_SERVER_HOST, WEBSOCKET_SERVER_PORT + 1 ); // Assuming a separate command port
    if ( $socket ) {
        $message = json_encode( array( 'event' => $event_name, 'data' => $event_data ) );
        fwrite( $socket, $message . "\n" );
        fclose( $socket );
    } else {
        // Fallback or error handling if direct connection fails
        error_log( 'Failed to connect to WebSocket server command port.' );
        // You might want to return an error or log this failure.
    }
    // --- End Option 2 ---

    return new WP_REST_Response( array( 'message' => 'Event triggered successfully.' ), 200 );
}

// Example usage: Triggering from save_post hook
function trigger_websocket_on_post_save_via_rest( $post_id, $post, $update ) {
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
    if ( wp_is_post_revision( $post_id ) ) return;

    $message_data = array(
        'post_id' => $post_id,
        'title'   => $post->post_post_title,
        'status'  => $post->post_status,
        'event'   => 'post_updated',
    );

    // Use wp_remote_post to call our custom REST API endpoint
    $rest_url = rest_url( 'realtime-events/v1/trigger' );
    $response = wp_remote_post( $rest_url, array(
        'body' => json_encode( array( 'event' => 'post_updated', 'data' => $message_data ) ),
        'headers' => array( 'Content-Type' => 'application/json' ),
    ) );

    if ( is_wp_error( $response ) ) {
        error_log( 'Failed to trigger WebSocket event via REST API: ' . $response->get_error_message() );
    } else {
        error_log( 'Successfully triggered WebSocket event via REST API. Response: ' . wp_remote_retrieve_body( $response ) );
    }
}
add_action( 'save_post', 'trigger_websocket_on_post_save_via_rest', 10, 3 );

?>

Deployment Considerations

Running a persistent WebSocket server requires careful consideration for production environments:

  • Process Management: Use tools like systemd, supervisor, or Docker to ensure your WebSocket server process runs continuously and restarts automatically if it crashes.
  • Scalability: For high traffic, a single WebSocket server instance might not be sufficient. Consider load balancing WebSocket connections across multiple server instances. This often involves a reverse proxy (like Nginx or HAProxy) that supports WebSocket proxying.
  • Security: Implement authentication and authorization for WebSocket connections. Ensure your server uses WSS (WebSocket Secure) over TLS/SSL.
  • Error Handling and Logging: Robust logging on both the server and client sides is crucial for debugging.

Conclusion

By integrating WebSockets with WordPress’s Block Patterns API, you can create highly dynamic and responsive user experiences. This recipe provides a foundational structure for real-time event triggering, from setting up a PHP WebSocket server to client-side JavaScript handling and WordPress plugin integration. Remember to adapt the backend communication strategy to your specific hosting environment and scalability needs.

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

  • Optimizing p99 database query response latency in multi-site Singleton Registry Pattern custom tables
  • Step-by-Step Guide to building a custom Elasticsearch search bar block for Gutenberg using React components
  • Troubleshooting guide: Resolving memory leak spikes caused by unclosed custom database loops in customer support tickets
  • Optimizing p99 database query response latency in multi-site Domain-driven architecture (DDD) blocks custom tables
  • How to design a modular Action-hook Event Mediator architecture for enterprise-level custom plugins

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 (41)
  • 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 (68)
  • WordPress Plugin Development (73)
  • WordPress Plugin Development (330)
  • WordPress Theme Development (357)

Recent Posts

  • Optimizing p99 database query response latency in multi-site Singleton Registry Pattern custom tables
  • Step-by-Step Guide to building a custom Elasticsearch search bar block for Gutenberg using React components
  • Troubleshooting guide: Resolving memory leak spikes caused by unclosed custom database loops in customer support tickets

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