• 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 WordPress Settings API

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

Leveraging WordPress Settings API for WebSocket Event Configuration

To enable real-time custom event triggers in WordPress via WebSockets, we first need a robust mechanism for administrators to configure WebSocket server endpoints and authentication credentials. The WordPress Settings API provides a structured and secure way to achieve this, ensuring that sensitive information is handled correctly and that the user interface is integrated seamlessly into the WordPress admin dashboard.

We’ll define a new top-level menu page for our plugin and register settings fields for the WebSocket server URL and an API key. This approach keeps our settings organized and prevents conflicts with other plugins or themes.

Registering Settings and Menu Page

The core of our configuration setup lies in the `add_action` calls to `admin_menu` and `admin_init`. The `admin_menu` hook is used to add our custom menu page, while `admin_init` is crucial for registering our settings, sections, and fields.

<?php
/*
Plugin Name: Real-time Event Trigger
Description: Enables real-time custom event triggers using WebSockets.
Version: 1.0
Author: Antigravity
*/

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

// Add menu page
function rtet_add_admin_menu() {
    add_menu_page(
        __( 'Real-time Events', 'real-time-event-trigger' ),
        __( 'Real-time Events', 'real-time-event-trigger' ),
        'manage_options',
        'real-time-events',
        'rtet_options_page_html',
        'dashicons-admin-generic',
        80
    );
}
add_action( 'admin_menu', 'rtet_add_admin_menu' );

// Register settings
function rtet_settings_init() {
    // Register settings group
    register_setting( 'rtet_options_group', 'rtet_settings' );

    // Add settings section
    add_settings_section(
        'rtet_section_main',
        __( 'WebSocket Configuration', 'real-time-event-trigger' ),
        'rtet_section_main_callback',
        'real-time-events'
    );

    // Add WebSocket Server URL field
    add_settings_field(
        'rtet_websocket_server_url',
        __( 'WebSocket Server URL', 'real-time-event-trigger' ),
        'rtet_websocket_server_url_callback',
        'real-time-events',
        'rtet_section_main'
    );

    // Add API Key field
    add_settings_field(
        'rtet_api_key',
        __( 'API Key', 'real-time-event-trigger' ),
        'rtet_api_key_callback',
        'real-time-events',
        'rtet_section_main'
    );
}
add_action( 'admin_init', 'rtet_settings_init' );

// Section callback
function rtet_section_main_callback() {
    echo '<p>' . __( 'Configure your WebSocket server details below.', 'real-time-event-trigger' ) . '</p>';
}

// WebSocket Server URL field callback
function rtet_websocket_server_url_callback() {
    $settings = get_option( 'rtet_settings' );
    $url = isset( $settings['websocket_server_url'] ) ? $settings['websocket_server_url'] : '';
    echo '<input type="url" name="rtet_settings[websocket_server_url]" value="' . esc_url( $url ) . '" class="regular-text" placeholder="ws://your-websocket-server.com" required />';
}

// API Key field callback
function rtet_api_key_callback() {
    $settings = get_option( 'rtet_settings' );
    $api_key = isset( $settings['api_key'] ) ? $settings['api_key'] : '';
    echo '<input type="text" name="rtet_settings[api_key]" value="' . esc_attr( $api_key ) . '" class="regular-text" placeholder="YourSecretAPIKey" required />';
}

// Render the options page HTML
function rtet_options_page_html() {
    // Check user capabilities
    if ( ! current_user_can( 'manage_options' ) ) {
        return;
    }
    ?>
    <div class="wrap">
        <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
        <form action="options.php" method="post">
            <?php
            // Output security fields for the registered setting group
            settings_fields( 'rtet_options_group' );
            // Output setting sections and their fields
            do_settings_sections( 'real-time-events' );
            // Output save settings button
            submit_button( __( 'Save Settings', 'real-time-event-trigger' ) );
            ?>
        </form>
    </div>
    <?php
}

In this code:

  • `rtet_add_admin_menu` registers a new top-level menu item under “Dashboard” with the slug `real-time-events`.
  • `rtet_settings_init` is the heart of the Settings API integration. It registers a settings group (`rtet_options_group`), a settings section (`rtet_section_main`), and two fields: `rtet_websocket_server_url` and `rtet_api_key`.
  • The callback functions (`rtet_websocket_server_url_callback`, `rtet_api_key_callback`) define how each input field is rendered in the HTML form, including input types, names, and default values retrieved from the database using `get_option(‘rtet_settings’)`.
  • `rtet_options_page_html` generates the actual HTML for the settings page, including the form, security fields (`settings_fields`), and the rendering of sections and fields (`do_settings_sections`).
  • `register_setting(‘rtet_options_group’, ‘rtet_settings’)` tells WordPress to save the data from the fields associated with `rtet_options_group` into an option named `rtet_settings` in the `wp_options` table. This option will store an array of our settings.

Client-Side WebSocket Connection and Event Handling

Once the server configuration is in place, we need to establish a WebSocket connection from the client-side (the user’s browser) to the configured WebSocket server. This involves enqueuing a JavaScript file that handles the connection logic and listens for incoming messages. We’ll also need to pass the configured WebSocket URL and API key to this script securely.

Enqueuing the JavaScript and Localizing Data

We’ll use the `wp_enqueue_script` action to load our JavaScript file. Crucially, we’ll use `wp_localize_script` to pass PHP variables (our WebSocket settings) to the JavaScript, making them accessible within the script without exposing them directly in the HTML source.

<?php
// ... (previous plugin code) ...

// Enqueue JavaScript for WebSocket connection
function rtet_enqueue_scripts() {
    // Only enqueue on the front-end
    if ( ! is_admin() ) {
        wp_enqueue_script(
            'rtet-websocket-client',
            plugin_dir_url( __FILE__ ) . 'js/websocket-client.js',
            array(), // Dependencies
            '1.0',
            true // Load in footer
        );

        // Localize script with WebSocket settings
        $settings = get_option( 'rtet_settings' );
        $websocket_url = isset( $settings['websocket_server_url'] ) ? $settings['websocket_server_url'] : '';
        $api_key = isset( $settings['api_key'] ) ? $settings['api_key'] : '';

        wp_localize_script(
            'rtet-websocket-client',
            'rtet_ws_config',
            array(
                'websocket_url' => esc_url_raw( $websocket_url ),
                'api_key'       => sanitize_text_field( $api_key ),
            )
        );
    }
}
add_action( 'wp_enqueue_scripts', 'rtet_enqueue_scripts' );

The `rtet_enqueue_scripts` function:

  • Checks if the current page is the front-end using `!is_admin()`.
  • Enqueues `js/websocket-client.js`. Ensure this file exists in your plugin’s directory.
  • Uses `wp_localize_script` to create a JavaScript object named `rtet_ws_config` containing the `websocket_url` and `api_key`. These values are retrieved from the WordPress options and sanitized appropriately.

JavaScript WebSocket Client Implementation

The `websocket-client.js` file will contain the logic to establish and maintain the WebSocket connection. It will also define how to handle incoming messages and potentially send messages back to the server.

document.addEventListener('DOMContentLoaded', function() {
    // Check if configuration is available
    if (typeof rtet_ws_config === 'undefined' || !rtet_ws_config.websocket_url) {
        console.error('WebSocket configuration not found or invalid.');
        return;
    }

    const websocketUrl = rtet_ws_config.websocket_url;
    const apiKey = rtet_ws_config.api_key;
    let websocket;

    function connectWebSocket() {
        // Ensure we don't create multiple connections
        if (websocket && websocket.readyState !== WebSocket.CLOSED) {
            return;
        }

        websocket = new WebSocket(websocketUrl);

        websocket.onopen = function(event) {
            console.log('WebSocket connection opened:', event);
            // Authenticate or send initial message
            websocket.send(JSON.stringify({
                type: 'authenticate',
                apiKey: apiKey,
                // Include any other necessary initial data, e.g., user ID
                userId: typeof wpApiSettings !== 'undefined' ? wpApiSettings.currentUser.id : null
            }));
        };

        websocket.onmessage = function(event) {
            console.log('WebSocket message received:', event.data);
            try {
                const message = JSON.parse(event.data);
                // Handle different message types from the server
                handleWebSocketMessage(message);
            } catch (e) {
                console.error('Failed to parse WebSocket message:', e);
            }
        };

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

        websocket.onerror = function(event) {
            console.error('WebSocket error:', event);
            // The onclose event will be fired after an error
        };
    }

    function handleWebSocketMessage(message) {
        // Example: Listen for a 'new_post_published' event
        if (message.type === 'new_post_published' && message.data) {
            console.log('New post published:', message.data);
            // Trigger a UI update, show a notification, etc.
            // Example: Display a toast notification
            if (typeof toastr !== 'undefined') {
                toastr.success('A new post has been published: ' + message.data.title);
            } else {
                alert('New Post: ' + message.data.title);
            }
        }
        // Add more message handlers for other event types
    }

    // Initial connection
    connectWebSocket();
});

Key aspects of the JavaScript client:

  • The script waits for the DOM to be fully loaded.
  • It accesses the configuration passed via `wp_localize_script` through the `rtet_ws_config` object.
  • The `connectWebSocket` function creates a new `WebSocket` instance. It includes basic error handling and a retry mechanism with a 5-second delay.
  • Upon successful connection (`onopen`), it sends an authentication message containing the API key and potentially the current user’s ID (if `wpApiSettings` is available, common in REST API contexts).
  • The `onmessage` handler parses incoming JSON messages and dispatches them to `handleWebSocketMessage`.
  • `handleWebSocketMessage` contains logic to react to specific event types, such as `new_post_published`. This is where you’d integrate UI updates or notifications.
  • `onerror` and `onclose` handle connection issues, with `onclose` initiating a reconnection attempt.

Server-Side Event Triggering and WebSocket Message Dispatch

The final piece of the puzzle is triggering custom events on the WordPress backend and sending these events through the WebSocket connection. This typically involves hooking into WordPress actions or filters and then dispatching messages to connected clients. For this, we’ll assume a separate WebSocket server application (e.g., Node.js with Socket.IO, or a PHP-based solution like Ratchet) is running and accessible via the configured URL.

Dispatching Events from WordPress Actions

We can hook into actions like `save_post` to detect when a post is published or updated. When such an event occurs, we’ll retrieve the WebSocket configuration and send a message to our WebSocket server.

<?php
// ... (previous plugin code) ...

// Function to send data to WebSocket server
function rtet_send_to_websocket_server( $event_type, $data = array() ) {
    $settings = get_option( 'rtet_settings' );
    $websocket_url = isset( $settings['websocket_server_url'] ) ? $settings['websocket_server_url'] : '';
    $api_key = isset( $settings['api_key'] ) ? $settings['api_key'] : '';

    if ( empty( $websocket_url ) || empty( $api_key ) ) {
        error_log( 'RTEvents: WebSocket server URL or API key not configured.' );
        return false;
    }

    // Prepare the message payload
    $message = array(
        'type' => $event_type,
        'apiKey' => $api_key, // Server-side authentication/authorization
        'data' => $data,
        'timestamp' => current_time( 'mysql' ),
    );

    // Use WordPress HTTP API to send a POST request to a REST endpoint on the WebSocket server
    // This assumes your WebSocket server has a corresponding REST API endpoint to receive messages.
    // Alternatively, if your WebSocket server is accessible directly for sending messages (less common for direct HTTP requests),
    // you might need a more complex setup or a dedicated microservice.
    // For simplicity, we'll simulate sending a message via a hypothetical REST endpoint.

    $api_endpoint = rtrim( $websocket_url, '/' ) . '/api/send-event'; // Example endpoint

    $response = wp_remote_post( $api_endpoint, array(
        'method'    => 'POST',
        'timeout'   => 45,
        'headers'   => array(
            'Content-Type' => 'application/json',
        ),
        'body'      => json_encode( $message ),
    ) );

    if ( is_wp_error( $response ) ) {
        error_log( 'RTEvents: Failed to send message to WebSocket server: ' . $response->get_error_message() );
        return false;
    }

    $response_code = wp_remote_retrieve_response_code( $response );
    if ( $response_code !== 200 ) {
        error_log( 'RTEvents: WebSocket server responded with error code: ' . $response_code );
        return false;
    }

    error_log( 'RTEvents: Successfully sent event "' . $event_type . '" to WebSocket server.' );
    return true;
}

// Hook into post save event
function rtet_handle_post_save( $post_id, $post, $update ) {
    // Only trigger for published posts and not during autosave or revisions
    if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) {
        return;
    }

    if ( $post->post_status == 'publish' ) {
        $event_type = $update ? 'post_updated' : 'post_published';
        $data = array(
            'id' => $post_id,
            'title' => $post->post_title,
            'status' => $post->post_status,
            'type' => $post->post_type,
            'link' => get_permalink( $post_id ),
        );
        rtet_send_to_websocket_server( $event_type, $data );
    }
}
add_action( 'save_post', 'rtet_handle_post_save', 10, 3 );

// Example: Hook for user registration
function rtet_handle_user_register( $user_id ) {
    $user_info = get_userdata( $user_id );
    if ( $user_info ) {
        $data = array(
            'id' => $user_id,
            'username' => $user_info->user_login,
            'email' => $user_info->user_email,
            'registered_date' => $user_info->user_registered,
        );
        rtet_send_to_websocket_server( 'user_registered', $data );
    }
}
add_action( 'user_register', 'rtet_handle_user_register' );

In this server-side logic:

  • `rtet_send_to_websocket_server` is a utility function that retrieves the WebSocket configuration from `rtet_settings`.
  • It constructs a JSON message containing the event type, API key, event data, and a timestamp.
  • Crucially, it uses `wp_remote_post` to send this message to a hypothetical REST endpoint (`/api/send-event`) on the WebSocket server. This is a common pattern: the WordPress site acts as a client to a separate WebSocket server application. The WebSocket server would then broadcast this message to all connected clients.
  • The `save_post` hook triggers `rtet_handle_post_save` when a post is saved. It checks if the post is published and not an autosave/revision, then formats data and calls `rtet_send_to_websocket_server` with `post_published` or `post_updated` event types.
  • An example for `user_register` demonstrates how to hook into other WordPress events to dispatch custom real-time notifications.

Important Consideration: The `rtet_send_to_websocket_server` function as written assumes your WebSocket server exposes a REST API endpoint to receive messages. If your WebSocket server is designed to only accept direct WebSocket connections for sending messages, you would need a different approach. This might involve a dedicated microservice that maintains a WebSocket connection to your server and accepts HTTP requests from WordPress, or a more complex direct integration if your WebSocket server library supports it from PHP (e.g., using libraries like Ratchet). The `wp_remote_post` method is generally the most straightforward for integrating with external services.

Deployment and Security Considerations

Deploying a real-time system requires careful attention to security and scalability. The API key stored in WordPress settings should be treated as a secret and protected accordingly. The WebSocket server itself must be secured against unauthorized access and denial-of-service attacks.

API Key Management

The API key used for authentication between WordPress and the WebSocket server should be:

  • Generated with sufficient entropy and complexity.
  • Stored securely in the WordPress database (handled by the Settings API).
  • Transmitted over HTTPS for the initial configuration save and potentially over WSS (WebSocket Secure) for the WebSocket connection itself.
  • Revocable and auditable.

WebSocket Server Security

The dedicated WebSocket server application is critical:

  • Authentication: Implement robust authentication on the WebSocket server. The API key sent from WordPress is a first layer; the server should verify it. For user-specific events, ensure the server can map authenticated WebSocket connections to WordPress users.
  • Authorization: Ensure that only authorized events can be dispatched and that clients only receive events they are permitted to see.
  • Rate Limiting: Protect against abuse by implementing rate limiting on message sending and connection attempts.
  • TLS/SSL (WSS): Always use WSS for encrypted WebSocket connections, especially if sensitive data is being transmitted.
  • Scalability: Design the WebSocket server to handle a large number of concurrent connections. This might involve load balancing, horizontal scaling, and efficient message broadcasting.
  • Input Validation: Sanitize and validate all incoming messages on the WebSocket server to prevent injection attacks or malformed data.

WordPress Security Best Practices

Ensure your WordPress installation is secure:

  • Keep WordPress core, themes, and plugins updated.
  • Use strong passwords and implement two-factor authentication.
  • Regularly back up your site.
  • Consider a Web Application Firewall (WAF).

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

  • How to securely integrate Firebase Realtime DB endpoints into WordPress custom plugins using WordPress Database Class ($wpdb)
  • Debugging and Resolving complex broken WP-Cron schedules issues during heavy concurrent database traffic
  • WordPress Development Recipe: High-efficiency server-side rendering for Gutenberg blocks using Union and Intersection Types
  • Building custom automated PDF financial reports and invoices for WooCommerce using native PHP ZipArchive streams
  • Advanced Diagnostics: Locating slow Command Query Responsibility Segregation (CQRS) query bottlenecks in WooCommerce custom checkout pipelines

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 (44)
  • 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 (138)
  • WordPress Plugin Development (151)
  • WordPress Plugin Development (330)
  • WordPress Theme Development (357)

Recent Posts

  • How to securely integrate Firebase Realtime DB endpoints into WordPress custom plugins using WordPress Database Class ($wpdb)
  • Debugging and Resolving complex broken WP-Cron schedules issues during heavy concurrent database traffic
  • WordPress Development Recipe: High-efficiency server-side rendering for Gutenberg blocks using Union and Intersection Types

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