• 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 custom charts dashboard block for Gutenberg using PHP block-render callbacks

Step-by-Step Guide to building a custom custom charts dashboard block for Gutenberg using PHP block-render callbacks

Leveraging PHP Block-Render Callbacks for Dynamic Gutenberg Charts

For e-commerce platforms and businesses reliant on data visualization, a custom Gutenberg block that renders dynamic charts directly within the WordPress editor offers significant advantages. This approach bypasses the need for client-side JavaScript rendering for initial data display, improving perceived performance and simplifying content management. We’ll explore building such a block using PHP block-render callbacks, focusing on a practical example of displaying sales data.

Prerequisites and Project Setup

Before diving into the code, ensure you have a local WordPress development environment set up. This guide assumes familiarity with PHP, JavaScript (for potential client-side enhancements, though not strictly required for the render callback), and the WordPress plugin development structure. We’ll be creating a simple plugin to house our custom block.

Create a new directory for your plugin, e.g., wp-content/plugins/ecommerce-charts-dashboard. Inside this directory, create a main plugin file, e.g., ecommerce-charts-dashboard.php, and a subdirectory for your block’s assets, e.g., blocks/sales-chart.

Registering the Gutenberg Block with PHP

The core of our custom block registration will happen in the main plugin file. We’ll use the register_block_type function, specifying a render_callback. This callback function will be responsible for generating the HTML output for our block on both the front-end and within the editor.

`ecommerce-charts-dashboard.php` – Plugin Entry Point

This file contains the plugin header and the block registration logic.

<?php
/**
 * Plugin Name: E-commerce Charts Dashboard
 * Description: Custom Gutenberg block for displaying sales charts.
 * Version: 1.0.0
 * Author: Your Name
 * License: GPL-2.0-or-later
 * Text Domain: ecommerce-charts-dashboard
 */

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

/**
 * Registers the block using the metadata loaded from the `block.json` file.
 * Behind the scenes, it registers also all assets so they can be enqueued
 * through the block editor in the corresponding context.
 *
 * @see https://developer.wordpress.org/reference/functions/register_block_type/
 */
function ecommerce_charts_dashboard_register_block() {
    register_block_type( __DIR__ . '/blocks/sales-chart' );
}
add_action( 'init', 'ecommerce_charts_dashboard_register_block' );
?>

Defining Block Metadata (`block.json`)

The block.json file is crucial for defining the block’s properties, including its name, title, icon, attributes, and importantly, the path to our render callback file.

`blocks/sales-chart/block.json` – Block Configuration

{
    "apiVersion": 2,
    "name": "ecommerce-charts-dashboard/sales-chart",
    "version": "0.1.0",
    "title": "Sales Chart",
    "category": "widgets",
    "icon": "chart-bar",
    "description": "Displays a dynamic sales chart.",
    "attributes": {
        "chartType": {
            "type": "string",
            "default": "bar"
        },
        "numberOfDays": {
            "type": "number",
            "default": 30
        }
    },
    "editorScript": "file:./index.js",
    "editorStyle": "file:./index.css",
    "style": "file:./style-index.css",
    "render": "file:./render.php"
}

Key elements here:

  • name: Unique identifier for the block.
  • attributes: Defines the data that the block will store and manage. We’ve added chartType and numberOfDays as examples.
  • render: This is the critical property. It points to the PHP file that will handle the server-side rendering of our block.

Implementing the PHP Render Callback

The render.php file will contain the PHP logic to fetch data and generate the HTML for our sales chart. This function receives the block’s attributes as an argument.

`blocks/sales-chart/render.php` – Dynamic Chart Rendering

<?php
/**
 * Sales Chart Block Render Callback.
 *
 * @param array $attributes The block attributes.
 * @return string Rendered HTML.
 */

// Ensure attributes are properly sanitized.
$chart_type = isset( $attributes['chartType'] ) ? sanitize_text_field( $attributes['chartType'] ) : 'bar';
$number_of_days = isset( $attributes['numberOfDays'] ) ? absint( $attributes['numberOfDays'] ) : 30;

// --- Data Fetching Logic ---
// In a real-world scenario, this would query your e-commerce database
// (e.g., WooCommerce orders, custom sales tables).
// For demonstration, we'll simulate data.

$sales_data = array();
$end_date = current_time( 'mysql' );
$start_date = date( 'Y-m-d H:i:s', strtotime( "-{$number_of_days} days" ) );

// Simulate fetching sales data for the last N days.
// Replace this with your actual data retrieval.
for ( $i = 0; $i < $number_of_days; $i++ ) {
    $date = date( 'Y-m-d', strtotime( "-{$i} days" ) );
    $sales_data[] = array(
        'date'  => $date,
        'sales' => rand( 50, 500 ), // Simulated sales figures
    );
}
// Reverse to have chronological order
$sales_data = array_reverse( $sales_data );

// --- Chart HTML Generation ---
// This is a basic HTML structure. For actual charting, you'd integrate a JS library
// like Chart.js, ApexCharts, etc., and pass this data to it.
// The render callback primarily provides the data structure or initial HTML.

$output = '<div class="wp-block-ecommerce-charts-dashboard-sales-chart">';
$output .= '<h3>Sales Data (' . esc_html( $chart_type ) . ' chart for last ' . esc_html( $number_of_days ) . ' days)</h3>';

if ( ! empty( $sales_data ) ) {
    $output .= '<div class="sales-chart-container">';
    // Basic representation: a table. In a real app, this would be a canvas or SVG.
    $output .= '<table><thead><tr><th>Date</th><th>Sales</th></tr></thead><tbody>';
    foreach ( $sales_data as $day_data ) {
        $output .= '<tr>';
        $output .= '<td>' . esc_html( $day_data['date'] ) . '</td>';
        $output .= '<td>' . esc_html( $day_data['sales'] ) . '</td>';
        $output .= '</tr>';
    }
    $output .= '</tbody></table>';
    $output .= '</div>';

    // --- Client-side Charting Integration (Optional but Recommended) ---
    // To make this a true chart, you'd enqueue a script and pass data.
    // The render callback can output a data attribute or a script tag.
    $output .= '<script type="application/json" class="sales-chart-data">' . wp_json_encode( $sales_data ) . '</script>';
    $output .= '<script type="application/json" class="sales-chart-config">' . wp_json_encode( array( 'chartType' => $chart_type ) ) . '</script>';

} else {
    $output .= '<p>No sales data available for the selected period.</p>';
}

$output .= '</div>';

echo $output;
?>

Explanation:

  • Attribute Sanitization: We retrieve and sanitize the chartType and numberOfDays attributes. This is crucial for security and data integrity.
  • Data Fetching: The commented-out section highlights where you’d integrate your actual data retrieval logic. For e-commerce, this might involve querying the wp_posts and wp_postmeta tables for WooCommerce orders, or directly accessing custom sales tables if you have them.
  • Simulated Data: For this example, we generate random sales data for the specified number of days.
  • HTML Output: The code constructs a basic HTML structure. A <div> with a specific class is generated, along with a heading and a table representing the data.
  • Client-side Data Embedding: Crucially, we embed the fetched $sales_data and configuration (like $chart_type) into JSON script tags within the output. This data can then be picked up by a JavaScript file enqueued for the front-end to render an interactive chart using a library like Chart.js.

Editor and Front-end Experience

When the block is used in the Gutenberg editor, WordPress will call the render.php file to display a preview. Because the render property in block.json points to a PHP file, the output is generated server-side. This means the block appears with its data already populated in the editor, offering a WYSIWYG experience.

On the front-end, the same render.php file is executed, ensuring consistency. The embedded JSON data within the script tags can then be utilized by a JavaScript file (enqueued via editorScript and style in block.json) to initialize a charting library and draw the actual visual chart.

Enqueuing JavaScript for Interactive Charts

While the render callback handles the initial HTML and data, a JavaScript file is necessary to transform that data into an interactive chart. This script needs to be enqueued for both the editor and the front-end.

`blocks/sales-chart/index.js` – Editor JavaScript

/**
 * WordPress dependencies
 */
import { registerBlockType } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';

/**
 * Internal dependencies
 */
import './style.scss'; // For editor-only styles
import './editor.scss'; // For editor-only styles

// Import your chart rendering component (e.g., using Chart.js)
// import SalesChartComponent from './SalesChartComponent';

const blockName = 'ecommerce-charts-dashboard/sales-chart';

registerBlockType( blockName, {
    title: __( 'Sales Chart', 'ecommerce-charts-dashboard' ),
    icon: 'chart-bar',
    category: 'widgets',
    attributes: {
        chartType: {
            type: 'string',
            default: 'bar',
        },
        numberOfDays: {
            type: 'number',
            default: 30,
        },
    },
    edit: ( { attributes, setAttributes } ) => {
        // In the editor, you might render a placeholder or a simplified view.
        // For a true WYSIWYG, you'd ideally render the chart here too,
        // but this requires more complex setup with client-side data fetching
        // or passing data from PHP to the editor script.
        // For simplicity, we'll show a placeholder and controls.

        const { chartType, numberOfDays } = attributes;

        // Placeholder for the chart in the editor
        return (
            <div className="wp-block-ecommerce-charts-dashboard-sales-chart editor-placeholder">
                <h3>Sales Chart (Editor Preview)</h3>
                <p>This is a preview. The actual chart will render on the front-end.</p>
                { /* Add controls here to change chartType and numberOfDays */ }
                <div>
                    <label>Chart Type: </label>
                    <select value={ chartType } onChange={ ( e ) => setAttributes( { chartType: e.target.value } ) }>
                        <option value="bar">Bar</option>
                        <option value="line">Line</option>
                    </select>
                </div>
                <div>
                    <label>Number of Days: </label>
                    <input type="number" value={ numberOfDays } onChange={ ( e ) => setAttributes( { numberOfDays: parseInt( e.target.value, 10 ) } ) } />
                </div>
            </div>
        );
    },
    save: () => {
        // The save function should return null for dynamic blocks.
        // The content is handled by the PHP render_callback.
        return null;
    },
} );

Note: For a truly dynamic editor experience where the chart renders within the editor itself, you would need to:

  • Enqueue a separate script for the editor that includes the charting library.
  • Pass the data generated by the PHP render callback to this editor script. This can be done by outputting the data in a data- attribute on the block’s wrapper element, or by using wp_add_inline_script.
  • Use a JavaScript component to render the chart within the edit function.

The save function must return null for blocks that use a render_callback, as the rendering is entirely handled by PHP.

Styling the Block

You’ll likely want to style your chart container and potentially the table representation. Create style-index.css for front-end styles and editor.scss (or index.css) for editor-specific styles.

`blocks/sales-chart/style-index.css` – Front-end Styles

.wp-block-ecommerce-charts-dashboard-sales-chart {
    border: 1px solid #eee;
    padding: 15px;
    margin-bottom: 20px;
    background-color: #fff;
    box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}

.wp-block-ecommerce-charts-dashboard-sales-chart h3 {
    margin-top: 0;
    color: #333;
}

.sales-chart-container table {
    width: 100%;
    border-collapse: collapse;
    margin-top: 10px;
}

.sales-chart-container th,
.sales-chart-container td {
    border: 1px solid #ddd;
    padding: 8px;
    text-align: left;
}

.sales-chart-container th {
    background-color: #f2f2f2;
}

`blocks/sales-chart/editor.scss` – Editor Styles

.wp-block-ecommerce-charts-dashboard-sales-chart.editor-placeholder {
    background-color: #f9f9f9;
    border: 1px dashed #ccc;
    text-align: center;
    padding: 20px;
}

.wp-block-ecommerce-charts-dashboard-sales-chart.editor-placeholder h3 {
    color: #666;
}

.wp-block-ecommerce-charts-dashboard-sales-chart.editor-placeholder div {
    margin-top: 10px;
}

Build Process and Asset Enqueuing

To compile your JavaScript and SCSS files (if using SCSS), you’ll need a build process. WordPress’s official block development tools (@wordpress/scripts) are highly recommended. Add a package.json file to your plugin’s root directory:

`package.json` – Build Configuration

{
    "name": "ecommerce-charts-dashboard",
    "version": "1.0.0",
    "description": "E-commerce Charts Dashboard Block",
    "main": "ecommerce-charts-dashboard.php",
    "scripts": {
        "build": "wp-scripts build",
        "start": "wp-scripts start"
    },
    "keywords": ["wordpress", "gutenberg", "block"],
    "author": "Your Name",
    "license": "GPL-2.0-or-later",
    "devDependencies": {
        "@wordpress/scripts": "^26.0.0"
    }
}

After creating this file, navigate to your plugin’s root directory in your terminal and run:

npm install
npm run build

This will compile your index.js and SCSS files into the build directory, which WordPress will automatically enqueue based on the paths defined in block.json.

Advanced Considerations and Next Steps

Data Security: Always sanitize and validate any data fetched from the database or user inputs. Use WordPress’s built-in sanitization functions (e.g., sanitize_text_field, absint, esc_html) liberally.

Performance: For very large datasets, consider pagination or server-side aggregation within your PHP callback. Avoid fetching excessive amounts of data that could slow down page loads.

Charting Libraries: Integrate robust charting libraries like Chart.js, ApexCharts, or Highcharts. The PHP render callback provides the data; JavaScript brings the visualization to life.

Editor Interactivity: To achieve a fully interactive chart preview in the editor, you’ll need to pass the data from PHP to your JavaScript editor script and use a charting library there. This often involves using wp_add_inline_script or data attributes.

Error Handling: Implement robust error handling in your PHP data fetching logic and provide user-friendly messages if data cannot be retrieved.

By utilizing PHP block-render callbacks, you can create powerful, data-driven Gutenberg blocks that enhance your WordPress site’s functionality, especially for dashboards and reporting needs in e-commerce environments.

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

  • Leveraging PHP 9’s JIT Compiler and Concurrent Execution for High-Performance Laravel Microservices
  • Leveraging PHP 8.3 JIT and Vectorization for High-Throughput Microservices in a Laravel Ecosystem
  • Leveraging Laravel Octane and Docker Swarm for High-Performance, Scalable WordPress Headless Deployments
  • Migrating Legacy WordPress to Headless with Laravel: A Performance and Security Deep Dive
  • Leveraging PHP 8’s JIT Compiler and Vector APIs for Extreme Web Application Performance

Categories

  • apache (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (664)
  • Desktop Applications (14)
  • DevOps (11)
  • DevOps & Cloud Scaling (962)
  • Django (1)
  • Laravel (6)
  • Migration & Architecture (192)
  • Mobile Applications (24)
  • MySQL (1)
  • Performance & Optimization (873)
  • PHP (17)
  • PHP Development (49)
  • Plugins & Themes (244)
  • Programming Languages (10)
  • Python (20)
  • Ruby on Rails (1)
  • Security & Compliance (650)
  • SEO & Growth (492)
  • Server (118)
  • Softwares (1)
  • Ubuntu (9)
  • Uncategorized (22)
  • VB6 & VB.NET (8)
  • Web Applications & Frontend (19)
  • Web Assembly (Wasm) (2)
  • WordPress (26)
  • WordPress Plugin Development (728)
  • WordPress Theme Development (357)

Recent Posts

  • Leveraging PHP 9's JIT Compiler and Concurrent Execution for High-Performance Laravel Microservices
  • Leveraging PHP 8.3 JIT and Vectorization for High-Throughput Microservices in a Laravel Ecosystem
  • Leveraging Laravel Octane and Docker Swarm for High-Performance, Scalable WordPress Headless Deployments

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (873)
  • WordPress Plugin Development (728)
  • Debugging & Troubleshooting (664)
  • Security & Compliance (650)
  • SEO & Growth (492)

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