It’s 2023, and we still have no simple way to insert Gutenberg blocks into WordPress using wp_insert_post. You’re out of luck if you want to pull content from an API and insert it dynamically with ease. There are methods like parse_blocks
and render_blocks
but they still require a lot of messing around to work with.
The way Gutenberg blocks work is strange. They’re not stored as an array or structured data in the database. They are stored in the HTML as HTML comments.
For a YouTube embed, it might look like this:
<!-- wp:core-embed/youtube {"url":"https://www.youtube.com/watch?v=VIDEOID","type":"video","providerNameSlug":"youtube","className":"wp-embed-aspect-16-9 wp-has-aspect-ratio"} --> <figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper"> https://www.youtube.com/watch?v=GF423423 </div></figure> <!-- /wp:core-embed/youtube -->
You can see how the blocks are handled by viewing the source of your page/post. I can understand why they did it this way for backward compatibility, but it means if you were previously inserting content into your posts, they wouldn’t be Gutenberg blocks by default.
Which is why I ended up creating something that works with the Gutenberg HTML comments. It’s a rather simple function that takes the name, attributes and some content.
function create_block( $block_name, $attributes = array(), $content = '' ) { $attributes_string = json_encode( $attributes ); $block_content = '<!-- wp:' . $block_name . ' ' . $attributes_string . ' -->' . $content . '<!-- /wp:' . $block_name . ' -->'; return $block_content; }
Going one step further, I also created a wrapper function called create_blocks
which allows you to pass in multiple Gutenberg blocks.
function create_blocks( $blocks = array() ) { $block_contents = ''; foreach ( $blocks as $block ) { $block_contents .= create_block( $block['name'], $block['attributes'], $block['content'] ); } return $block_contents; }
And here is how you use it.
$blocks = array(); $blocks[] = array( 'name' => 'paragraph', 'attributes' => array( 'align' => 'center' ), 'content' => '<p>Hello World!</p>', ); $blocks[] = array( 'name' => 'paragraph', 'attributes' => array( 'align' => 'left' ), 'content' => '<p>This is another paragraph.</p>', ); $blocks[] = array( 'name' => 'paragraph', 'attributes' => array( 'align' => 'right' ), 'content' => '<p>And this is yet another paragraph.</p>', ); $post_content = create_blocks( $blocks ); $post_id = wp_insert_post( array( 'post_title' => 'My post title', 'post_content' => $post_content, 'post_status' => 'publish', 'post_type' => 'post', ) );
Is this the best solution you could use? Probably not. Did it work for me? Yes. This saved me the hassle of coming up with a clever solution when all I needed was something that got me out of a pickle.
Thank you for this post, it’s hard to find good tutorials on these functions.
I noticed that render_block does not output the comments and attributes of a parsed block. I’m assuming this is why you wrote this code, but do you know of any WP functions that you can access to output the namespace and attributes?