The Gutenberg block editor in WordPress has revolutionized content creation and management. One powerful feature of Gutenberg is the ability to create custom blocks that display dynamic data. In this article, we will walk through the process of creating a Dynamic Gutenberg Block that fetches and displays dynamic data from an external API. We will cover everything from registering the block to handling authentication, caching, and rendering the data.
Understanding Gutenberg Blocks
The initial part of this discussion focuses on Gutenberg blocks. Gutenberg is the block-based editor introduced in WordPress 5.0. It creates content using a modular approach. Each piece of content is a block, which can be a paragraph, image, video, or custom block created by developers.
Why Create a Dynamic Block?
Creating a dynamic block allows you to display content that can change based on external data sources. It is particularly useful for displaying information such as:
- Latest posts from a blog
- Weather data
- Stock prices
- User-generated content
By fetching data from an external API, you can ensure that your block always displays the most up-to-date information.
Step 1: Setting Up Your Plugin
To create a custom Gutenberg block, you first need to set up a WordPress plugin. Here’s how to do it:
- Create a Plugin Folder: You need to create a new plugin folder named dynamic-api-block inside wp-content/plugins/ of your WordPress site.
- Create a Plugin File: Inside the dynamic-api-block folder, create a file named dynamic-api-block.php.
- Add Plugin Header: Open the dynamic-api-block.php file and add the following header information:
<?php
/**
* Plugin Name: Dynamic API Block
* Description: A custom Gutenberg block that fetches data from an external API.
* Version: 1.0
* Author: Your Name
*/
// Exit if accessed directly
if (!defined('ABSPATH')) {
  exit;
}
- Enqueue Block Scripts: You will need to enqueue the recommended JavaScript and CSS files for your block. Add the following code inside your plugin file:
function dynamic_api_block_enqueue() {
  wp_enqueue_script(
    'dynamic-api-block-editor',
    plugins_url('block.js', __FILE__),
    array('wp-blocks', 'wp-element', 'wp-editor', 'wp-components'),
    filemtime(plugin_dir_path(__FILE__) . 'block.js')
  );
}
9add_action('enqueue_block_editor_assets', 'dynamic_api_block_enqueue');
- Create the JavaScript File: Start by creating a file named block.js, which should reside in the same folder. Your block JavaScript code will be inside the block.js file located within the same directory.
Step 2: Registering the Block
Now that you have set up your plugin, the next step is to register your Gutenberg block. In the block.js file, add the following code:
const { registerBlockType } = wp.blocks;
const { useBlockProps } = wp.blockEditor;
registerBlockType('dynamic-api/block', {
  title: 'Dynamic API Block',
  category: 'widgets',
  icon: 'cloud',
  edit: () => {
    return (
      <div {...useBlockProps()}>
        <p>Loading data...</p>
      </div>
    );
  },
  save: () => {
    return null; // Dynamic blocks do not save content in the post
  },
});
Explanation of the Code:
- registerBlockType: This function registers your block with WordPress.
- title: The name of your block as it will appear in the block editor.
- category: The category under which your block will be listed.
- icon: An icon representing your block.
- edit: The function that renders the block in the editor. Here, we display a loading message.
- save: Since this block will render dynamically, we return null to indicate that no static content should be saved.
Step 3: Handling Dynamic Rendering
To fetch data from an external API, you need to specify a render_callback in your block registration. This callback will fetch the data and render the block’s HTML.
Update the Plugin File
Add the following code to your dynamic-api-block.php file to register the block with a render callback:
function dynamic_api_block_register() {
  register_block_type('dynamic-api/block', array(
    'render_callback' => 'dynamic_api_block_render',
  ));
}
add_action('init', 'dynamic_api_block_register');
function dynamic_api_block_render($attributes) {
  // Fetch data $api_url = 'https://api.example.com/data'; // Replace with your API URL
  $response = wp_remote_get($api_url, array(
    'headers' => array(
      'Authorization' => 'Bearer ' . getenv('API_TOKEN'), // Use environment variable for security
    ),
  ));
  if (is_wp_error($response)) {
    return '<p>Error fetching data.</p>';
  }
  $data = json_decode(wp_remote_retrieve_body($response), true);
  if (empty($data)) {
    return '<p>No data available.</p>';
  }
  // Build the block's HTML
  $output = '<div class="dynamic-api-block">';
  foreach ($data as $item) {
    $output .= '<h2>' . esc_html($item['title']) . '</h2>'; // Adjust according to your API response structure
    $output .= '<p>' . esc_html($item['description']) . '</p>';
  }
  $output .= '</div>';
  return $output;
}
Explanation of the Code:
- wp_remote_get: This function fetches data from the specified API URL.
- Authorization Header: The API token is retrieved from an environment variable for security.
- Error Handling: Checks if the response is an error and returns an appropriate message.
- Data Processing: Decodes the JSON response and builds the HTML output for the block.
Step 4: Implementing Caching
Implement WordPress transients to effectively cache data as part of your optimization plan. This will enhance system speed while minimizing API requests. WordPress transients allow you to temporarily store the API response.
Update the Render Callback
Modify the dynamic_api_block_render function to include caching:
function dynamic_api_block_render($attributes) {
  $transient_key = 'dynamic_api_block_data';
  $data = get_transient($transient_key);
  if (false === $data) {
    $api_url = 'https://api.example.com/data'; // Replace with your API URL
    $response = wp_remote_get($api_url, array(
      'headers' => array(
        'Authorization' => 'Bearer ' . getenv('API_TOKEN'),
      ),
    ));
    if (is_wp_error($response)) {
      return '<p>Error fetching data.</p>';
    }
    $data = json_decode(wp_remote_retrieve_body($response), true);
    if (empty($data)) {
      return '<p>No data available.</p>';
    }
    // Store the data in a transient for 1 hour
    set_transient($transient_key, $data, HOUR_IN_SECONDS);
  }
  // Build the block's HTML
  $output = '<div class="dynamic-api-block">';
  foreach ($data as $item) {
    $output .= '<h2>' . esc_html($item['title']) . '</h2>';
    $output .= '<p>' . esc_html($item['description']) . '</p>';
  }
  $output .= '</div>';
  return $output;
}
Explanation of the Caching Code:
- get_transient: Checks if cached data exists.
- set_transient: Stores the fetched data in a transient for one hour, reducing the number of API calls.
Step 5: Handling Authentication
When working with APIs, authentication is often required. In this example, we used a Bearer token for authentication. Here’s how to securely manage your API credentials:
- Environment Variables: Instead of hardcoding sensitive information like API tokens in your plugin, store them in environment variables. The server configuration lets you establish environment variables, or you can use a .env file with a library like Lucas/phpdotenv.
- Using wp_localize_script: If you need to pass any data to your JavaScript file, you can use wp_localize_script to safely pass variables.
Example of wp_localize_script:
In your dynamic_api_block_enqueue function, you can add:
1function dynamic_api_block_enqueue() {
2Â Â wp_enqueue_script(
3Â Â Â Â 'dynamic-api-block-editor',
4Â Â Â Â plugins_url('block.js', __FILE__),
5Â Â Â Â array('wp-blocks', 'wp-element', 'wp-editor', 'wp-components'),
6Â Â Â Â filemtime(plugin_dir_path(__FILE__) . 'block.js')
7Â Â );
8
9Â Â wp_localize_script('dynamic-api-block-editor', 'dynamicApiBlock', array(
10Â Â Â Â 'apiToken' => getenv('API_TOKEN'),
11Â Â ));
12}
In your block.js, you can access the token using dynamicApiBlock.apiToken.
Step 6: Testing Your Block
After implementing the above steps, it’s time to test your block:
- Activate Your Plugin: Go to the WordPress admin area, navigate to Plugins, and activate your Dynamic API Block plugin.
- Add the Block to a Post: Create a new post or edit an existing one. In the Gutenberg editor, search for your “Dynamic API Block” and add it to the post.
- Check the Output: Publish or preview the post to see if the block fetches and displays data correctly from the external API. Ensure that the loading message appears while the data is being fetched.
Step 7: Enhancing User Experience
To improve the user experience, consider adding loading indicators or error messages directly in the block. You can modify the edit function in your block.js to show a loading spinner or a message when the block is being rendered.
Example of Loading State:
const { registerBlockType } = wp.blocks;
const { useBlockProps } = wp.blockEditor;
const { useEffect, useState } = wp.element;
registerBlockType('dynamic-api/block', {
  title: 'Dynamic API Block',
  category: 'widgets',
  icon: 'cloud',
  edit: () => {
    const [loading, setLoading] = useState(true);
    const [data, setData] = useState(null);
    useEffect(() => {
      fetch('https://api.example.com/data') // Replace with your API URL
        .then(response => response.json())
        .then(data => {
          setData(data);
          setLoading(false);
        })
        .catch(() => {
          setLoading(false);
        });
    }, []);
    return (
      <div {...useBlockProps()}>
        {loading ? (
          <p>Loading data...</p>
        ) : (
          data && data.map(item => (
            <div key={item.id}>
              <h2>{item.title}</h2>
              <p>{item.description}</p>
            </div>
          ))
        )}
      </div>
    );
  },
  save: () => {
    return null; // Dynamic blocks do not save content in the post
  },
});
Explanation of the Loading State Code:
- useState: Manages the loading state and fetches data.
- useEffect: Fetches data when the block is rendered in the editor.
- Conditional Rendering: Displays a loading message or the fetched data based on the loading state.
Step 8: Final Considerations
Security Best Practices
- Always sanitize and validate any data fetched from external APIs before displaying it.
- Ensure that your API token is stored securely and not exposed in the client-side code.
Performance Optimization
- Consider implementing additional caching strategies, such as object caching, if your site experiences high traffic or if the API calls are resource-intensive.
- Optimize the API calls to minimize load times and consistently monitor the performance of your block.
FAQs
Conclusion
Creating a dynamic Gutenberg block that fetches data from an external API is a powerful way to enhance your WordPress site. By following the guidelines in this article, you can build a block that not only displays dynamic content but also effectively handles authentication and caching.
With the knowledge gained from this guide, you can explore further possibilities, such as integrating multiple APIs, adding more complex data handling, or even creating a settings page for your block to allow users to customize the API endpoint or other parameters. The flexibility of Gutenberg and the WordPress ecosystem opens up a world of opportunities for developers looking to create engaging and dynamic content.
About the writer
Hassan Tahir wrote this article, drawing on his experience to clarify WordPress concepts and enhance developer understanding. Through his work, he aims to help both beginners and professionals refine their skills and tackle WordPress projects with greater confidence.