WordPress’ integration with oEmbed is an amazing feature and allows us to easily embed third-party content such as interlinked documentation, YouTube videos, or even BlueSky posts.
The problem is that the embedded content is largely controlled by the third party, which can cause a lot of unnecessary scripts and files (such as tracking scripts) to load on any page with embedded content. Nowhere is this more common than with embedding YouTube videos on your WordPress page.
Luckily, WordPress provides us with a way to create our own markup for embedded content, and in this article I will go over how to create a static version of a YouTube embed that will greatly speed up page speed times, while also adding an additional layer of security for your users. Just note that you can change the provided code to update any oEmbed that you want, not just YouTube.
Detecting when oEmbed happens, and returning our custom content
The first thing we need to do is detect when embedded content is loading from the oEmbed spec. To do this, we can use WordPress’ embed_oembed_html filter. This filter will run anytime WordPress creates the HTML for oEmbed content, so we will be using it to instead return our custom markup.
function hdplugins_custom_youtube_oembed($html, $url, $attr)
{
// only run on the frontend
if (is_admin()) {
return $html;
}
// only run if the URL contains youtube.com
if (strpos($url, 'youtube.com') == false) {
return $html;
}
// get the Video ID
$query_string = parse_url($url, PHP_URL_QUERY);
parse_str($query_string, $query_params);
$v_value = $query_params['v'];
// create thumbnail URL
$image_url = "https://img.youtube.com/vi/$v_value/sddefault.jpg";
// This is the same play button icon that the real YT player uses
$playbutton = '<svg class = "hdt_yt_play_button" version="1.1" viewBox="0 0 68 48"><path d="M66.52,7.74c-0.78-2.93-2.49-5.41-5.42-6.19C55.79,.13,34,0,34,0S12.21,.13,6.9,1.55 C3.97,2.33,2.27,4.81,1.48,7.74C0.06,13.05,0,24,0,24s0.06,10.95,1.48,16.26c0.78,2.93,2.49,5.41,5.42,6.19 C12.21,47.87,34,48,34,48s21.79-0.13,27.1-1.55c2.93-0.78,4.64-3.26,5.42-6.19C67.94,34.95,68,24,68,24S67.94,13.05,66.52,7.74z" fill="#f03"></path><path d="M 45,24 27,14 27,34" fill="#fff"></path></svg>';
// The actual return HTML
$html = '<div class = "hdt_yt_embed">
<a href = "' . $url . '" class = "hdt_yt_link" target = "_blank"></a>
<div class = "hdt_yt_button_wrapper">' . $playbutton . '</div>
<div class = "hdt_yt_thumbnail_wrapper"><img class = "hdt_yt_thumbnail" src = "' . $image_url . '" alt = "Youtube thumbnail"/></div>
</div>';
return $html;
}
add_filter('embed_oembed_html', 'hdplugins_custom_youtube_oembed', 10, 3);And some CSS to go along with it
.hdt_yt_embed {
display: inline-block;
position: relative;
background-color: #000;
border-radius: 12px;
box-shadow: 0 0 17px -8px #00749c;
overflow: hidden;
}
.hdt_yt_thumbnail_wrapper {
display: flex;
}
.hdt_yt_play_button {
height: 20%;
z-index: 1;
opacity: 0.8;
}
.hdt_yt_button_wrapper {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: grid;
place-items: center;
}
.hdt_yt_embed:hover .hdt_yt_play_button {
opacity: 1;
}
.hdt_yt_thumbnail {
display: block;
aspect-ratio: 16/9;
object-fit: cover;
opacity: 0.6;
}
.hdt_yt_embed .hdt_yt_link {
position: absolute;
z-index: 2;
width: 100%;
height: 100%;
left: 0;
top: 0;
text-decoration: none;
}If all went well, your final result should look something like this:
The explanation
The first thing we do is check is_admin to see if we are on the backend admin area of the site or not. We do not want to change the oEmbeds in the admin area simply because we’d then need to also enqueue our custom styles or scripts to the editors as well. This just makes things a little simpler, but feel free to do so if you feel it’s best for your use case.
Next we check the $url to see make sure it contains the domain we are looking for, which in this case is YouTube.
Next you can do any custom work that you want. In my case, I wanted to automatically grab the YouTube thumbnail, which thankfully, is very easy to do. So I start by getting the Video ID, and then use that to create the thumbnail link. Unfortunately, it is not possible to also grab the video title with just the ID anymore, unless you signup for an API key.
Lastly, I create the actual new HTML for the embed, which is a nice simple thumbnail with the real YouTube play button over it. It’s now just a simple link that opens the video in a new tab, but if you wanted to add some JavaScript, you could easily make it so that clicking it opens a lightbox with the video, or have it auto convert to the original oEmbedded content if you wanted.

