• 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 » Step-by-Step Guide to building a custom automated performance diagnostic log block for Gutenberg using HTMX dynamic attributes

Step-by-Step Guide to building a custom automated performance diagnostic log block for Gutenberg using HTMX dynamic attributes

Gutenberg Block Structure and Initialization

We’ll begin by defining the fundamental structure of our Gutenberg block. This involves registering the block type in PHP and setting up its JavaScript components. The block will be designed to accept a URL as input, which will then be used to trigger an asynchronous performance diagnostic.

PHP Block Registration

The core registration logic resides in your plugin’s main PHP file or a dedicated block registration file. This ensures the block is recognized by WordPress.

<?php
/**
 * Plugin Name: Custom Performance Diagnostic Block
 * Description: Adds a Gutenberg block for automated performance diagnostics.
 * Version: 1.0.0
 * Author: Antigravity
 */

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

/**
 * Register the custom block.
 */
function antigravity_performance_diagnostic_block_register() {
    // Automatically load dependencies and version.
    $asset_file = include( plugin_dir_path( __FILE__ ) . 'build/index.asset.php');

    register_block_type( __DIR__, array(
        'editor_script' => 'antigravity-performance-diagnostic-block-editor-script',
        'editor_style'  => 'antigravity-performance-diagnostic-block-editor-style',
        'style'         => 'antigravity-performance-diagnostic-block-style',
        'script'        => 'antigravity-performance-diagnostic-block-script',
        'dependencies'  => $asset_file['dependencies'],
        'version'       => $asset_file['version'],
    ) );
}
add_action( 'init', 'antigravity_performance_diagnostic_block_register' );

/**
 * Enqueue block assets.
 */
function antigravity_performance_diagnostic_block_enqueue_assets() {
    wp_enqueue_script(
        'antigravity-performance-diagnostic-block-script',
        plugin_dir_url( __FILE__ ) . 'build/index.js',
        array( 'wp-element', 'wp-blocks', 'wp-components', 'wp-i18n', 'wp-editor', 'htmx' ), // Ensure htmx is enqueued
        filemtime( plugin_dir_path( __FILE__ ) . 'build/index.js' )
    );

    // Localize script for AJAX URL
    wp_localize_script( 'antigravity-performance-diagnostic-block-script', 'antigravity_performance_diagnostic_block_ajax_object', array(
        'ajax_url' => admin_url( 'admin-ajax.php' ),
        'nonce'    => wp_create_nonce( 'antigravity_performance_diagnostic_block_nonce' ),
    ) );
}
add_action( 'wp_enqueue_scripts', 'antigravity_performance_diagnostic_block_enqueue_assets' );

// Ensure HTMX is loaded. You might enqueue it here if not already present.
// For demonstration, assuming HTMX is available globally or enqueued by another plugin/theme.
// If not, add:
// wp_enqueue_script( 'htmx', 'https://unpkg.com/[email protected]', array(), '1.9.10', true );

JavaScript Block Registration and Editor Interface

The JavaScript side defines the block’s appearance and behavior within the Gutenberg editor. We’ll use the `registerBlockType` function from `@wordpress/blocks`.

// src/index.js
import { registerBlockType } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
import { TextControl, Button, PanelBody } from '@wordpress/components';
import { InspectorControls } from '@wordpress/block-editor';

import './style.scss'; // For frontend styles
import './editor.scss'; // For editor styles

const Edit = ( { attributes, setAttributes } ) => {
    const { targetUrl } = attributes;

    const onChangeTargetUrl = ( newUrl ) => {
        setAttributes( { targetUrl: newUrl } );
    };

    return (
        <>
            <InspectorControls>
                <PanelBody title={ __( 'Performance Settings', 'antigravity-performance-diagnostic-block' ) }>
                    <TextControl
                        label={ __( 'Target URL', 'antigravity-performance-diagnostic-block' ) }
                        value={ targetUrl }
                        onChange={ onChangeTargetUrl }
                        help={ __( 'Enter the URL to diagnose.', 'antigravity-performance-diagnostic-block' ) }
                    />
                </PanelBody>
            </InspectorControls>
            <div className="antigravity-performance-diagnostic-block-editor">
                <p>{ __( 'Performance Diagnostic Block', 'antigravity-performance-diagnostic-block' ) }</p>
                { targetUrl ? (
                    <p>{ __( 'Target URL: ', 'antigravity-performance-diagnostic-block' ) }{ targetUrl }</p>
                ) : (
                    <p>{ __( 'Configure a Target URL in the block settings.', 'antigravity-performance-diagnostic-block' ) }</p>
                ) }
            </div>
        </>
    );
};

const Save = ( { attributes } ) => {
    const { targetUrl } = attributes;

    if ( ! targetUrl ) {
        return null; // Don't render anything if no URL is set
    }

    // HTMX attributes for dynamic loading and swapping
    const htmxAttributes = {
        'hx-get': `/wp-admin/admin-ajax.php?action=antigravity_diagnose_performance&url=${ encodeURIComponent( targetUrl ) }&_ajax_nonce=${ antigravity_performance_diagnostic_block_ajax_object.nonce }`,
        'hx-trigger': 'load', // Trigger on page load
        'hx-swap': 'innerHTML', // Replace the content of this element
        'hx-target': '.antigravity-performance-diagnostic-block-output', // Target a specific element for output
    };

    return (
        <div className="antigravity-performance-diagnostic-block-frontend">
            <p>{ __( 'Performance Diagnostic for: ', 'antigravity-performance-diagnostic-block' ) }{ targetUrl }</p>
            <div className="antigravity-performance-diagnostic-block-output" { ...htmxAttributes }>
                { __( 'Loading performance data...', 'antigravity-performance-diagnostic-block' ) }
            </div>
        </div>
    );
};

registerBlockType( 'antigravity/performance-diagnostic', {
    title: __( 'Performance Diagnostic', 'antigravity-performance-diagnostic-block' ),
    icon: 'performance', // WordPress Dashicon
    category: 'widgets',
    attributes: {
        targetUrl: {
            type: 'string',
            default: '',
        },
    },
    edit: Edit,
    save: Save,
} );

AJAX Handler for Performance Diagnostics

This PHP function will handle the AJAX request, perform the diagnostic, and return the results. For this example, we’ll simulate a diagnostic by fetching basic HTTP headers and response time. In a production environment, you would integrate with tools like GTmetrix, WebPageTest, or use PHP libraries for more in-depth analysis (e.g., cURL for timing, DOM parsing for content analysis).

 'URL parameter is missing.' ), 400 );
    }

    $url = sanitize_url( $_GET['url'] );

    // Basic validation to ensure it's a valid URL format
    if ( ! filter_var( $url, FILTER_VALIDATE_URL ) ) {
        wp_send_json_error( array( 'message' => 'Invalid URL format.' ), 400 );
    }

    // --- Performance Diagnostic Logic ---
    $start_time = microtime( true );
    $ch = curl_init();

    curl_setopt( $ch, CURLOPT_URL, $url );
    curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
    curl_setopt( $ch, CURLOPT_HEADER, true ); // Get headers
    curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true ); // Follow redirects
    curl_setopt( $ch, CURLOPT_TIMEOUT, 10 ); // Timeout in seconds
    curl_setopt( $ch, CURLOPT_USERAGENT, 'AntigravityPerformanceBot/1.0' ); // Set a user agent

    $response = curl_exec( $ch );
    $http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
    $curl_error = curl_error( $ch );
    $end_time = microtime( true );
    curl_close( $ch );

    $response_time = ( $end_time - $start_time ) * 1000; // in milliseconds

    if ( $curl_error ) {
        wp_send_json_error( array( 'message' => 'cURL Error: ' . $curl_error ), 500 );
    }

    // Parse headers
    list( $headers, $body ) = explode( "\r\n\r\n", $response, 2 );
    $headers_array = preg_split( '/\r\n|\\r|\\n/', $headers );

    // --- Format Output for HTMX ---
    // This output will be directly inserted into the DOM by HTMX.
    echo '<h4>Diagnostic Results for: ' . esc_html( $url ) . '</h4>';
    echo '<p><strong>HTTP Status Code:</strong> ' . esc_html( $http_code ) . '</p>';
    echo '<p><strong>Response Time:</strong> ' . esc_html( round( $response_time, 2 ) ) . ' ms</p>';
    echo '<h5>Response Headers:</h5>';
    echo '<ul>';
    foreach ( $headers_array as $header ) {
        if ( ! empty( $header ) ) {
            echo '<li>' . esc_html( $header ) . '</li>';
        }
    }
    echo '</ul>';

    // In a real-world scenario, you'd add more sophisticated checks:
    // - Content-Length, Content-Type
    // - Cache-Control headers
    // - Server response time (if available in headers)
    // - Page load time (requires browser automation or more advanced JS execution simulation)
    // - Lighthouse/PageSpeed Insights integration (via API)

    wp_die(); // This is required to terminate immediately and return a proper response
}
?>

Frontend Integration and HTMX Attributes

The magic of dynamic updates without full page reloads is handled by HTMX. We’ve already added the necessary attributes in the `Save` function of our JavaScript block. The `hx-get` attribute points to our AJAX endpoint, `hx-trigger=”load”` ensures the request fires when the block is rendered on the frontend, and `hx-swap=”innerHTML”` dictates that the response from the AJAX call will replace the content within the target element.

<div class="antigravity-performance-diagnostic-block-frontend">
    <p>Performance Diagnostic for: https://example.com</p>
    <div class="antigravity-performance-diagnostic-block-output"
         hx-get="/wp-admin/admin-ajax.php?action=antigravity_diagnose_performance&url=https%3A%2F%2Fexample.com&_ajax_nonce=YOUR_NONCE_HERE"
         hx-trigger="load"
         hx-swap="innerHTML"
         hx-target=".antigravity-performance-diagnostic-block-output">
        Loading performance data...
    </div>
</div>

When a user views a page containing this block, HTMX will intercept the `load` event for the `.antigravity-performance-diagnostic-block-output` div. It will then make a GET request to the specified `hx-get` URL. The response from the `antigravity_diagnose_performance_callback` function (which contains the formatted HTML results) will then replace the “Loading performance data…” text within that same div.

Build Process and Dependencies

To compile the JavaScript and SCSS files, you’ll need a build process. WordPress development typically uses `@wordpress/scripts` which leverages Webpack. Ensure you have Node.js and npm/yarn installed.

# Navigate to your plugin directory
cd /path/to/your/wordpress/plugins/custom-performance-diagnostic-block

# Install dependencies
npm install

# Build for development (watches for changes)
npm run start

# Build for production
npm run build

The `build/index.asset.php` file is automatically generated by `@wordpress/scripts` and contains the block’s dependencies and version, which is crucial for WordPress to correctly load scripts.

Security Considerations

Sanitization and validation are paramount. We’ve used `sanitize_url()` and `filter_var()` for the URL. The AJAX request is protected by a nonce (`check_ajax_referer`) to prevent Cross-Site Request Forgery (CSRF) attacks. Ensure that any external API calls or data processing within the AJAX handler are also secured against injection vulnerabilities.

Advanced Enhancements and Enterprise Use Cases

For enterprise-level applications, consider these extensions:

  • Integration with Monitoring Services: Instead of basic cURL, use APIs for services like GTmetrix, Pingdom, or Google PageSpeed Insights to fetch detailed performance reports.
  • Caching: Implement transient API caching for diagnostic results to avoid repeated external API calls and speed up frontend rendering.
  • Scheduled Diagnostics: Use WordPress Cron (`wp_schedule_event`) to periodically run diagnostics on key pages and store results for historical trend analysis.
  • Threshold Alerts: Define performance thresholds (e.g., load time > 3 seconds) and trigger notifications (email, Slack via webhook) when these are breached.
  • User Role Permissions: Restrict who can configure or view the diagnostic block using WordPress capabilities.
  • Data Visualization: Store diagnostic data in a custom database table and use JavaScript charting libraries (e.g., Chart.js) to visualize performance trends over time within the WordPress admin area.
  • Multi-site Support: Ensure the plugin functions correctly across a WordPress multi-site network, potentially with network-activated settings.
  • Internationalization: Properly internationalize all strings using `__()` and `_x()` for translation.

By leveraging Gutenberg’s extensibility and HTMX for dynamic client-side interactions, we can create powerful, non-intrusive diagnostic tools directly within the WordPress content management interface, providing valuable insights for CTOs and architects without requiring separate monitoring dashboards for basic checks.

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

  • Upgrading Apache HTTP Server from version 2.4.57 to the latest security patch on openSUSE Leap 15.5 without breaking virtual hosts
  • Upgrading a multi-node Redis replication cluster on RHEL 9: Pre-flight failover validation runbooks
  • Upgrading Nginx from mainline repository to the latest stable branch on Ubuntu 24.04 LTS: Zero-downtime configuration validations
  • Upgrading a high-traffic production PostgreSQL database cluster from version 15 to 16 using pg_upgrade link mode on Debian 12
  • Upgrading PHP 8.2 to 8.3 on Rocky Linux 9: Re-compiling APCu, Imagick, and Memcached extensions safely

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 (59)
  • 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

  • Upgrading Apache HTTP Server from version 2.4.57 to the latest security patch on openSUSE Leap 15.5 without breaking virtual hosts
  • Upgrading a multi-node Redis replication cluster on RHEL 9: Pre-flight failover validation runbooks
  • Upgrading Nginx from mainline repository to the latest stable branch on Ubuntu 24.04 LTS: Zero-downtime configuration validations

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