I recently started a video series on lessons that I’ve learned in the Army. This was something I’ve wanted to do for a little while, and one of my goals was to make sure I was producing content consistently. My goal is to post a new video every Thursday morning. I’m not crazy though, I’m not going to wake up at 5AM just to click publish on my videos or the accompanying blog post. Instead, I’m embedding scheduled YouTube videos in scheduled WordPress posts.
WordPress makes it really simple to embed a YouTube video in your posts. All you have to do is copy the YouTube video’s URL and paste it into your post on it’s own line. Then WordPress does all the heavy lifting of reaching out to YouTube and getting the correct embed code so the video displays properly.
There’s a problem though.
YouTube doesn’t generate an embed code for videos that are scheduled (or otherwise not-public). At the time I write the blog post, the embed code won’t exist for that video. So when WordPress reaches out to YouTube, it gets an error and comes back empty handed. (Technically, I’m not sure if YouTube returns an error, or if it just returns nothing. Not super important for purposes of this post though).
WordPress saves whatever response it gets from YouTube in your post’s post meta. So if the video is public, it will save the embed code in the post’s post meta. If the video isn’t public, or is scheduled to be public, WordPress saves the value {{unknown}} with a key starting with _oembed_ and a hash of seemingly (but not really) random letters and numbers in the post meta.
This is a way to cache the response from YouTube. That way WordPress won’t have to retrieve the same embed code every time someone loads the page with the video.
The problem is, when WordPress saves the value {{unknown}}, that value is also cached. So instead of displaying your video in the post when it is published, it will just show the video’s URL.
How to Embed Scheduled YouTube Videos in Scheduled WordPress Posts
WordPress has an action hook called transition_post_status. Any time a post transitions from one status to another (draft to publish, future to publish, etc.) this hook fires.
We can use this to check when our scheduled post (post status would be future) changes to publish.
Once we do that we can delete the post meta with the value {{unknown}} for this post.
It will look something like this:
<?php function sd_future_to_publish_only( $new_status, $old_status, $post ) { // Check if post is transitioning from future (scheduled) to publish if ( ( 'publish' === $new_status && 'future' === $old_status ) ) { global $wpdb; $post_meta_table = $wpdb->prefix . "postmeta"; $wpdb->query( $wpdb->prepare( "DELETE FROM " . $post_meta_table . " WHERE post_id = '%d' AND meta_key LIKE '_oembed_%' AND meta_value LIKE '{{unknown}}';", absint( $post->ID ) ) ); } } add_action( 'transition_post_status', 'sd_future_to_publish_only', 10, 3 ); |
So, let’s look at the code.
First, it’s checking to see if the post is transitioning from future (a scheduled post) to publish. This will be true only when a scheduled post goes live. It will be false every other time, so we can safely put our code inside this check.
Next, we do a query on the database to delete from our site’s postmeta table where the:
- post_id is the same as the post that just transitioned from future to publish
- meta_key starts with _oembed_
- meta_value is {{unknown}}
The next time that post loads, WordPress will recognize that:
- There is a YouTube link in the post
- There is no _oembed_ cached for it (anymore)
- WordPress needs to retrieve the oEmbed code from YouTube
Essentially, we’re just clearing the cache on the oEmbed code.
Other tips to get this to work
If you want this to work correctly, you have to schedule your YouTube video to publish before your WordPress post is scheduled to be published. If your WordPress post publishes first, it will go out to YouTube and check for the embed code before it exists again. You’ll end up caching {{unknown}} all over again.
Also, I have only tested this with YouTube videos, but I believe it should work with any embedded content that works by pasting in a link to the content.
Ryan says
Thanks for this. I’ve got a handful of videos that I’m planning on scheduling this way and this looks like a perfect solution.