• 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 Shortcode API

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

Leveraging WebSockets for Real-time WordPress Event Triggers via Shortcode

This recipe details a robust method for implementing real-time event triggers within WordPress, specifically by integrating WebSockets with the Shortcode API. This approach is ideal for dynamic content updates, live notifications, or interactive elements that require immediate feedback without constant page reloads. We’ll focus on a server-side PHP implementation for the WebSocket server and a client-side JavaScript integration for the WordPress frontend.

Prerequisites and Setup

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

  • A working WordPress installation.
  • PHP 7.4+ with the pcntl and sockets extensions enabled for the WebSocket server.
  • Composer for managing PHP dependencies.
  • Basic understanding of WebSockets, PHP, JavaScript, and the WordPress Shortcode API.

WebSocket Server Implementation (PHP)

We’ll use a simple, non-blocking WebSocket server implemented in PHP. For production environments, consider a more mature library like Ratchet or Swoole, but this example illustrates the core concepts.

First, set up a new PHP project for your WebSocket server. Navigate to a directory outside your WordPress root (e.g., /var/www/websocket-server) and initialize Composer:

cd /var/www/websocket-server
composer init

Now, install the necessary dependencies. We’ll use the cboden/ratchet library for a more structured WebSocket implementation, which simplifies handling connections and messages.

composer require cboden/ratchet

Create a file named server.php in your WebSocket server directory:

<?php
require dirname(__DIR__) . '/vendor/autoload.php';

use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;

class WordPressEventComponent implements MessageComponentInterface {
    protected $clients;

    public function __construct() {
        $this->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) {
        echo "Message received: {$msg}\n";

        // In a real application, you'd parse $msg to identify event types
        // and potentially interact with your WordPress backend.
        // For this example, we'll just broadcast back.

        $data = json_decode($msg, true);
        if ($data && isset($data['event'])) {
            $response = json_encode(['status' => 'received', 'event' => $data['event'], 'message' => 'Event acknowledged']);
            $from->send($response); // Acknowledge receipt to sender

            // Broadcast to all other clients
            foreach ($this->clients as $client) {
                if ($from !== $client) {
                    // You might want to filter which clients receive which events
                    // based on subscriptions or user roles.
                    $client->send(json_encode(['type' => 'event_trigger', 'event' => $data['event'], 'payload' => $data['payload'] ?? null]));
                }
            }
        } else {
            $from->send(json_encode(['status' => 'error', 'message' => 'Invalid message format. Expected JSON with an "event" key.']));
        }
    }

    public function onClose(ConnectionInterface $conn) {
        // The connection is closed, remove it, as we're not sending an echo
        $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();
    }

    // Method to trigger an event from the server-side (e.g., from a WP hook)
    public function triggerEvent($event, $payload = null) {
        $message = json_encode(['type' => 'event_trigger', 'event' => $event, 'payload' => $payload]);
        echo "Broadcasting event: {$event}\n";
        foreach ($this->clients as $client) {
            $client->send($message);
        }
    }
}

// Start the WebSocket server
$server = IoServer::factory(
    new HttpServer(
        new WsServer(
            new WordPressEventComponent()
        )
    ),
    8080 // Port to listen on
);

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

To run the server, execute:

php server.php

Keep this terminal window open. For production, you’ll need to run this process as a service (e.g., using systemd or supervisor) and ensure it’s accessible from your WordPress frontend.

WordPress Plugin for Shortcode Integration

Now, let’s create a WordPress plugin to manage the WebSocket connection and expose a shortcode. Create a new directory realtime-events in your wp-content/plugins/ directory. Inside it, create a main plugin file, e.g., realtime-events.php.

<?php
/**
 * Plugin Name: Realtime Events
 * Description: Integrates WebSockets for real-time event triggers via shortcode.
 * Version: 1.0
 * Author: Your Name
 */

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

class Realtime_Events_Plugin {

    private $websocket_server_url = 'ws://localhost:8080'; // Change if your server is elsewhere

    public function __construct() {
        add_shortcode( 'realtime_trigger', array( $this, 'render_shortcode' ) );
        add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
        // Example: Hook into a WordPress action to trigger an event
        // add_action('save_post', array($this, 'trigger_post_save_event'), 10, 3);
    }

    public function enqueue_scripts() {
        wp_enqueue_script(
            'realtime-events-js',
            plugin_dir_url( __FILE__ ) . 'js/realtime-events.js',
            array( 'jquery' ), // Dependency on jQuery
            '1.0',
            true // Load in footer
        );

        // Pass WebSocket server URL to the JavaScript
        wp_localize_script(
            'realtime-events-js',
            'realtimeEventsConfig',
            array(
                'websocket_url' => $this->websocket_server_url,
            )
        );
    }

    public function render_shortcode( $atts ) {
        // Shortcode attributes can be used to customize event names or payloads
        $atts = shortcode_atts( array(
            'event' => 'generic_event',
            'payload' => '',
        ), $atts, 'realtime_trigger' );

        // We'll use this shortcode primarily to enqueue the JS and establish the connection.
        // The actual triggering will be handled by JS or server-side hooks.
        // For demonstration, we can output a placeholder or a button.
        ob_start();
        ?>
        <div id="realtime-event-listener" data-event="" data-payload="">
            
            

Real-time events listener initialized.

Client-Side JavaScript for WebSocket Communication

Create a JavaScript file at realtime-events/js/realtime-events.js:

jQuery(document).ready(function($) {
    var websocket = null;
    var wsUrl = realtimeEventsConfig.websocket_url;
    var reconnectInterval = 5000; // milliseconds

    function connectWebSocket() {
        console.log('Attempting to connect to WebSocket server at: ' + wsUrl);
        websocket = new WebSocket(wsUrl);

        websocket.onopen = function(event) {
            console.log('WebSocket connection opened.');
            // Send a message to the server to identify the client or subscribe to events
            // For example, you could send user ID, page ID, etc.
            // websocket.send(JSON.stringify({ type: 'identify', userId: 'some_user_id' }));
        };

        websocket.onmessage = function(event) {
            console.log('Message from server: ', event.data);
            try {
                var data = JSON.parse(event.data);

                // Handle incoming event triggers
                if (data.type === 'event_trigger') {
                    console.log('Received event trigger:', data.event);
                    // Example: Update a specific DOM element based on the event
                    if (data.event === 'post_saved') {
                        // Find elements that are listening for this event
                        $('[data-event="post_saved"]').each(function() {
                            var $element = $(this);
                            var payload = data.payload;
                            if (payload && payload.post_id) {
                                // Example: Update content, show a notification, etc.
                                $element.html('

Post ' + payload.post_id + ' was just saved! Payload: ' + JSON.stringify(payload) + '

'); } else { $element.html('

A post was saved (details unavailable).

'); } }); } else if (data.event === 'generic_event') { // Handle generic events defined in shortcode attributes $('[data-event="' + data.event + '"]').each(function() { var $element = $(this); var payload = data.payload; var message = 'Received generic event.'; if (payload) { message += ' Payload: ' + JSON.stringify(payload); } $element.append('

' + message + '

'); }); } // Add more event handling logic here for different event types } else if (data.status === 'received') { console.log('Server acknowledged message:', data.message); } else if (data.status === 'error') { console.error('Server error:', data.message); } } catch (e) { console.error('Failed to parse JSON message:', e); } }; websocket.onerror = function(event) { console.error('WebSocket error observed:', event); // Attempt to reconnect reconnect(); }; websocket.onclose = function(event) { console.log('WebSocket connection closed. Code:', event.code, 'Reason:', event.reason); // Attempt to reconnect reconnect(); }; } function reconnect() { console.log('Attempting to reconnect in ' + reconnectInterval / 1000 + ' seconds...'); setTimeout(connectWebSocket, reconnectInterval); } // Initial connection attempt connectWebSocket(); // Example: Sending a message from the client (e.g., on a button click) // This would typically be triggered by user interaction or other JS events. // For demonstration, let's say we have a button with id="send_test_event" // $(document).on('click', '#send_test_event', function() { // if (websocket && websocket.readyState === WebSocket.OPEN) { // var message = JSON.stringify({ // event: 'user_interaction', // payload: { button: 'send_test_event', timestamp: Date.now() } // }); // websocket.send(message); // console.log('Sent message:', message); // } else { // console.error('WebSocket is not connected.'); // } // }); });

Integrating and Triggering Events

To use the shortcode, simply place it in any WordPress post or page content:

[realtime_trigger event="user_login" payload='{"username": "admin"}']

When this page loads, the realtime-events.js script will be enqueued. It will attempt to establish a WebSocket connection to your server. Any messages of type event_trigger received from the server will be processed by the JavaScript handler.

Server-Side Event Triggering from WordPress

Triggering events from the WordPress backend (e.g., on post save, user registration) requires a mechanism for the PHP process running WordPress to communicate with the separate PHP WebSocket server process. Direct method calls are not feasible across different processes.

Here are common strategies:

  • API Endpoint: Create a WordPress REST API endpoint that, when called, sends a message to the WebSocket server. The WebSocket server would need to be configured to listen for these API calls (e.g., via a simple HTTP server or by having the WebSocket server poll an API endpoint).
  • Message Queue: Use a message queue system (like Redis Pub/Sub, RabbitMQ, or Kafka). The WordPress backend publishes events to the queue, and the WebSocket server subscribes to these events and forwards them to connected clients. This is the most scalable and robust solution.
  • Direct Socket Connection (Advanced): The WordPress PHP process could attempt to establish a direct socket connection to the WebSocket server (if configured to accept such connections, which is non-standard for WebSockets) or a separate TCP port. This is complex and often less reliable than message queues.

For simplicity in this recipe, let's outline the API endpoint approach. You would add a new endpoint to your WordPress plugin:

// Add this to your Realtime_Events_Plugin class

public function __construct() {
    // ... existing hooks ...
    add_action( 'rest_api_init', array( $this, 'register_rest_routes' ) );
}

public function register_rest_routes() {
    register_rest_route( 'realtime-events/v1', '/trigger', array(
        'methods' => 'POST',
        'callback' => array( $this, 'handle_rest_trigger' ),
        'permission_callback' => array( $this, 'check_rest_permission' ),
    ) );
}

public function check_rest_permission() {
    // Implement proper authentication/authorization here.
    // For example, check user capabilities or use an API key.
    // For simplicity, we'll allow logged-in users.
    return current_user_can( 'edit_posts' );
}

public function handle_rest_trigger( WP_REST_Request $request ) {
    $event = $request->get_param( 'event' );
    $payload = $request->get_param( 'payload' );

    if ( ! $event ) {
        return new WP_Error( 'missing_param', 'Event name is required.', array( 'status' => 400 ) );
    }

    // Now, send this event to the WebSocket server.
    // This requires an HTTP client to make a request to your WebSocket server's API endpoint,
    // or a direct socket connection if your WS server exposes one for this purpose.
    // For demonstration, let's assume a function `send_to_websocket_server` exists.

    // Example using WordPress HTTP API to call a hypothetical API endpoint on the WS server
    $ws_server_api_url = 'http://localhost:8080/api/trigger'; // Assuming WS server has an HTTP API
    $response = wp_remote_post( $ws_server_api_url, array(
        'body' => json_encode( array( 'event' => $event, 'payload' => $payload ) ),
        '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, 'wp_error' => $response->get_error_message() ) );
    }

    $body = wp_remote_retrieve_body( $response );
    $status_code = wp_remote_retrieve_response_code( $response );

    if ( $status_code !== 200 ) {
         return new WP_Error( 'ws_server_error', 'WebSocket server returned an error.', array( 'status' => $status_code, 'response' => $body ) );
    }

    return new WP_REST_Response( array( 'message' => 'Event triggered successfully', 'response' => json_decode($body, true) ), 200 );
}

// Example of triggering the REST API from a WordPress hook:
public function trigger_post_save_event($post_id, $post, $update) {
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
    if (wp_is_post_revision($post_id)) return;
    if ( $post->post_type === 'attachment' ) return; // Skip attachments

    // Prepare data for the REST API call
    $event_data = array(
        'event' => 'post_saved',
        'payload' => array(
            'post_id' => $post_id,
            'title' => $post->post_title,
            'status' => $post->post_status,
            'type' => $post->post_type,
            'modified' => current_time('mysql'),
        ),
    );

    // Construct the URL for the REST API endpoint
    $rest_url = rest_url( 'realtime-events/v1/trigger' );

    // Make the POST request to the WordPress REST API
    $response = wp_remote_post( $rest_url, array(
        'body' => json_encode( $event_data ),
        'headers' => array( 'Content-Type' => 'application/json' ),
        // Add authentication if needed, e.g., using an API key or nonce
        // 'headers' => array_merge( $headers, array( 'Authorization' => 'Bearer YOUR_API_KEY' ) ),
    ) );

    if ( is_wp_error( $response ) ) {
        error_log( 'Error triggering post save event via REST API: ' . $response->get_error_message() );
    } else {
        $status_code = wp_remote_retrieve_response_code( $response );
        if ( $status_code !== 200 ) {
            error_log( 'Failed to trigger post save event via REST API. Status: ' . $status_code . ' Response: ' . wp_remote_retrieve_body( $response ) );
        } else {
            // Success logged by the REST API callback itself
        }
    }
}

Note that the handle_rest_trigger function in WordPress makes an HTTP request to the WebSocket server. This implies your WebSocket server needs to expose an HTTP endpoint (e.g., on port 8080 or another port) to receive these trigger requests. The server.php would need modification to handle these HTTP requests and forward them to the WebSocket component.

Production Considerations

  • Scalability: For high-traffic sites, a single PHP WebSocket server might become a bottleneck. Consider using a distributed system with multiple WebSocket servers behind a load balancer, or leverage managed WebSocket services.
  • Reliability: Implement robust reconnection logic in the client. Ensure the WebSocket server process is managed by a process supervisor (like systemd or supervisor) to automatically restart if it crashes.
  • Security:
    • Secure the WebSocket connection using WSS (WebSocket Secure) by running your WebSocket server behind a reverse proxy (like Nginx or Caddy) that handles SSL termination.
    • Implement proper authentication and authorization for both incoming WebSocket connections and for triggering events via the REST API.
    • Sanitize all data received from clients and sent to clients.
  • Error Handling: Implement comprehensive logging on both the server and client sides.
  • State Management: For complex applications, managing client subscriptions to specific events on the server-side becomes crucial.

This recipe provides a foundational structure for real-time event handling in WordPress using WebSockets and the Shortcode API. By extending the server-side logic and client-side event handlers, you can build highly interactive and dynamic WordPress experiences.

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

  • Reducing database query bloat in Sage Roots modern environments layouts using custom lazy loaders
  • Performance Optimization: Tuning PHP-FPM and opcache pools for high-concurrency Firebase Realtime DB handlers
  • Reducing Largest Contentful Paint (LCP) by optimizing custom script enqueuing structures in legacy plugins
  • How to implement native Redis caching layers for high-volume custom taxonomy queries in Carbon Fields custom wrappers
  • Building secure B2B pricing grids with custom REST API Controllers 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 (182)
  • WordPress Plugin Development (197)
  • WordPress Plugin Development (330)
  • WordPress Theme Development (357)

Recent Posts

  • Reducing database query bloat in Sage Roots modern environments layouts using custom lazy loaders
  • Performance Optimization: Tuning PHP-FPM and opcache pools for high-concurrency Firebase Realtime DB handlers
  • Reducing Largest Contentful Paint (LCP) by optimizing custom script enqueuing structures in legacy plugins

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