Embed YouTube Videos in WordPress with Custom Fields and the Query Loop Block

While working on a recent project, we needed to create a custom post type for video posts. Our stack was WordPress, BlocksyPro theme, ACF (free version) and WPCodebox 2. We created a custom field called ‘video_url’ with the oEmbed field type, where the client can paste in the link to their YouTube video. The description of the video will be in the custom post type content field.

Next we had to output all the videos on a custom page, not the default Archive page. For this we used the Generateblocks Query Loop block to display the videos. Setting this up was easy, but we encountered an unexpected issue – while the “video_url” custom field was correctly storing the YouTube video links, the videos were not rendering as embedded players on the front-end.

The Problem

After some initial troubleshooting, we discovered that the “video_url” custom field was only outputting the link itself, rather than the necessary HTML code to render the embedded video player. We needed a solution that would take the video URL and dynamically generate the appropriate oEmbed code to display the video within the GenerateBlocks Query Loop block.

Where we started

We started with a code snippet shared by Jonathan Jernigan, which creates a custom WordPress shortcode to handle the video embedding.

This shortcode works well for standalone video instances, but when we tried to implement it within the GenerateBlocks Query Loop block, the videos still did not render correctly. As per the GenerateBlocks team, shortcodes won’t render inside a Query Loop. It requires using the render_block filter to replace a blocks content instead.

The Solution

We reached out to the GenerateBlocks support team, who patiently troubleshooted with us and provided us with a custom code snippet that seamlessly integrated the video embedding into the block’s functionality:

  1. Add a GenerateBlocks Headline block in the query loop as the placeholder.
  2. You can add static text to the Headline block so you know it’s a placeholder.
  3. Add a custom CSS class to the Headline block, eg. ytvideo-placeholder.
  4. Add the above PHP code to your theme’s functions.php file or a code snippet plugin.

The key to this solution was the addition of the “ytvideo-placeholder” class to the “Additional Classes” section of the GenerateBlocks Headline block. This allowed the custom code to identify the specific block where the video should be embedded and replace the content with the appropriate oEmbed code.

Lessons Learned

At first we tried replacing the GenerateBlocks Headline content with the shortcode. The final iteration removed the shortcode entirely and replaced the Headline block content with the oEmbed code.

Initially we had incorrectly placed the “ytvideo-placeholder” class in the new GenerateBlocks class section. Even though the class was being attached to the block, the code snippet was not able to identify the block. One of the GenerateBlocks team members, identified that this was the issue and this was the key to the final working solution. The custom class needed to be added in the default Additional Classes section of the block.

additional class field in the wordpress block editor

A Breakdown of the code step by step:

  1. add_filter('render_block_generateblocks/headline', function($block_content, $block) {
    • This line sets up a WordPress filter that hooks into the render_block_generateblocks/headline action.
    • The render_block_generateblocks/headline action is triggered when the “GenerateBlocks/Headline” block is being rendered on the front-end of the website.
    • The function takes two parameters: $block_content (the original content of the block) and $block (an array containing the block’s attributes).
  2. if (!is_admin() && !empty($block['attrs']['className']) && strpos($block['attrs']['className'], 'ytvideo-placeholder') !== false) {
    • This if statement checks three conditions:
      1. !is_admin(): Ensures the code only runs on the front-end, not the WordPress admin area.
      2. !empty($block['attrs']['className']): Checks if the block has a CSS class name set.
      3. strpos($block['attrs']['className'], 'ytvideo-placeholder') !== false: Checks if the block’s CSS class name contains the string “ytvideo-placeholder”.
    • If all these conditions are met, the code inside the if block will execute.
  3. $video_url = get_field('video_url', get_the_ID());
    • This line retrieves the value of the “video_url” custom field for the current post, using the get_field() function from the Advanced Custom Fields (ACF) plugin.
    • The get_the_ID() function is used to get the ID of the current post.
  4. if (!empty($video_url)) {
    • This if statement checks if the $video_url variable is not empty (i.e., if a valid video URL was retrieved).
  5. $block_content = wp_oembed_get($video_url);
    • If the $video_url is not empty, this line uses the wp_oembed_get() function to generate the HTML code for the embedded video player.
    • The generated HTML code is then assigned to the $block_content variable, effectively replacing the original content of the “GenerateBlocks/Headline” block.
    • This closes the inner if statement that checks if the $video_url is not empty.}
    • This closes the outer if statement that checks the conditions for the “ytvideo-placeholder” class name.
  6. return $block_content;
    • Finally, the modified $block_content is returned, which will be used to render the “GenerateBlocks/Headline” block on the front-end.

This code snippet is a WordPress filter that modifies the output of the “GenerateBlocks/Headline” block on the front-end. It checks if the GenerateBlocks/Headline block has a CSS class name of “ytvideo-placeholder”, and if so, it retrieves the video URL from a custom field and uses the wp_oembed_get() function to generate the HTML code for the embedded video player, replacing the original block content.

This allows you to easily embed YouTube (or other oEmbed-compatible) videos within the “GenerateBlocks/Headline” block by adding the “ytvideo-placeholder” class to the block.

Additional Notes:

During my testing I found an issue that was quite frustrating to figure out. I set up a staging site on InstaWP for the purposes of a video walkthrough to accompany this blog post. While I configured the ACF “video_url” field and the query loop the same way as the project site, the code snippet I had been using still did not render the videos on the front-end.

After further troubleshooting, I suspect that the issue is related to the version of the GenerateBlocks plugin I was using. On the project site, I was using the beta versions of the free GenerateBlocks plugin and the GenerateBlocks Pro plugin. However, on the staging site used in this walkthrough, I was using the stable version 1.8.3 of the free GenerateBlocks plugin.

To work around the issue on the staging site in the video, I had to change the ACF “video_url” field type from oEmbed to URL. This allowed the code snippet to still function correctly and render the embedded videos on the staging site.

This experience highlights the importance of ensuring that all the components of your WordPress stack, including plugins and their versions, are aligned across your development and production environments. It also demonstrates the value of thorough testing, as issues can sometimes arise due to subtle differences in plugin versions or functionality.

If you encounter a similar problem, be sure to check the versions of GenerateBlocks (or any other relevant plugins) you’re using, and consider adjusting the custom field type if necessary to ensure the code snippet works as expected.

Sherissa R

You may also like