WordPress
Article

How to Create a YouTube Embed Plugin for WordPress

By Narayan Prusty

YouTube is the most popular video sharing platform. As everyone knows, they also lets us embed its videos on our websites. But just taking the embed code and pasting in our site is not enough. It’s not responsive and adds a lot of unnecessary weight to our pages. Due to these issues, users are unlikely to play the videos and we risk them leaving our site.

In this tutorial I’ll show you how to create a YouTube embed plugin which provides a shortcode to add YouTube videos responsively without increasing the weight of the page.

WordPress Default Embeds

WordPress by default, converts YouTube URLs into embed code (using oEmbed) in the post editor.

For example:

Check out this video:

http://www.youtube.com/watch?v=dQw4w9WgXcQ

..is converted to:

Check out this video:

<iframe width="560" height="315" src="http://www.youtube.com/watch?v=dQw4w9WgXcQ" frameborder="0" allowfullscreen></iframe>

WordPress doesn’t apply any other optimization to our video display, such as making it responsive, or dynamically loading the video to decrease page size. With a little work, we can make some significant improvements to the way WordPress handles YouTube videos by default.

How Does YouTube Embed Increase Page Size?

YouTube let’s us embed videos on our website using the standard iframe tag. This embed code downloads ~1MB of resources to just render the video when page loads. And again, ~500KB of extra resources are downloaded when we click the play button to play the video!

This image shows the resources that are downloaded just to render a video:

Default YouTube Page Speed Report

This increases the loading time of your page, thus affecting your ‘pagespeed’ score, which as we know is bad news (further reading here and here).

Responsiveness of YouTube Embedded Videos

The default YouTube embed code is not responsive. The width of the video is 560px and the height is 315px. Therefore, if your website is responsive, then users viewing your website with a screen size less than 560px will likely to have a bad user experience.

Let’s Build Our Plugin!

Let’s create a plugin which tackles these issues. Before we start coding let’s create the plugin directory and its files. Here’s our directory and file structure:

--youtube-embed
    -youtube-embed.php
    -mce.js
    -youtube-embed.js
    -youtube-embed.css

To make the plugin installable, we put the following code in the youtube-embed.php file:

<?php
/**
 * Plugin Name: SitePoint YouTube Embed
 * Plugin URI: http://sitepoint.com/
 * Description: An plugin to embed YouTube videos responsively.
 * Version: 1.0
 * Author: Narayan Prusty
 */

Creating the Shortcode

Let’s create a shortcode named youtube which takes a YouTube video ID and generates the HTML code to display the video when viewed on the frontend.

Here’s the code to create the shortcode. Place this code in youtube-embed.php file:

function youtube_embed_callback($atts=null, $content=null)
{
	extract($atts);

	return "<div class='youtube-container-parent'><div class='youtube-container-child'><div class='youtube-video' data-id='". $id ."'></div></div></div>";
}

add_shortcode("youtube", "youtube_embed_callback");

This is how you’ll be able to embed shortcodes in your post editor:

YouTube Default Post Editor

When you view the post you won’t see anything, because instead of returning the iframe embed code, we’re just displaying a div with ID of the video. We’ll dynamically load the embed code only when the user wants to play the video, therefore decreasing the page load time.

Dynamically Loading YouTube Videos

We want to render the video only when a user clicks to play the video. At present, we don’t have any interface to tell the users that a video exists on this page. Therefore, let’s write some code to just fetch the thumbnail of the video when the page loads and attach a click event listener to it, to play the video.

Place this code in the youtube-embed.js file to display the placeholder image of the video:

window.addEventListener("load", function(){
    var v = document.getElementsByClassName("youtube-video");
    for (var n = 0; n < v.length; n++) {
        var p = document.createElement("div");
        p.innerHTML = '<img class="youtube-thumb" src="//i.ytimg.com/vi/' + v[n].dataset.id + '/hqdefault.jpg"><div class="play-button"></div>';
        p.onclick = youtube_video_clicked;
        v[n].appendChild(p);
    }
}, false);

In the above video, we find all the DOM elements with class name youtube-video and retrieve the data-id attribute value. Then we add an img tag inside the youtube-video class named div tag pointing to the placeholder image of the video.

To enqueue this script, place the following code in your youtube-embed.php file:

function register_youtube_embed_plugin_scripts() 
{
	wp_register_script("youtube-embed-js", plugins_url("youtube-embed/youtube-embed.js"));
	wp_enqueue_script("youtube-embed-js");
}

add_action("wp_enqueue_scripts", "register_youtube_embed_plugin_scripts");

Now, when you view the post using your shortcode, you’ll see something like this:

YouTube Plugin Preview

We also want to load the iframe when a user clicks on the placeholder image to play the video. To do this, place the following code in the youtube-embed.js file:

function youtube_video_clicked() {
    var iframe = document.createElement("iframe");
    iframe.setAttribute("src", "//www.youtube.com/embed/" + this.parentNode.dataset.id + "?autoplay=1&autohide=2&border=0&wmode=opaque&enablejsapi=1&controls=0&showinfo=0");
    iframe.setAttribute("frameborder", "0");
    iframe.setAttribute("id", "youtube-iframe");
    this.parentNode.replaceChild(iframe, this);
}

When a user clicks on the placeholder image, the iframe tag is embedded with the autoplay attribute set to true. Now, clicking on the placeholder image will play the video.

Making the Video Responsive

To make the video responsive, place this CSS code in the youtube-embed.css file:

.youtube-container-child
{
	position: relative;
	padding-bottom: 56.25%; /* 16:9 */
	padding-top: 25px;
	height: 0;
}

.youtube-container-child iframe, .youtube-container-child img
{
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
}

To enqueue the script, place the following code in the youtube-embed.php file:

function register_youtube_embed_plugin_styles() 
{
    wp_register_style("youtube-embed-css", plugins_url("youtube-embed/youtube-embed.css"));
    wp_enqueue_style("youtube-embed-css");
}

add_action("wp_enqueue_scripts", "register_youtube_embed_plugin_styles");

Now, our video should look like this:

YouTube Plugin Preview - Improved

Creating a Shortcode Button

Typing the shortcode to add a video is cumbersome, so let’s create a text editor button that will display a prompt to enter the video ID and add the shortcode to the post editor.

Firstly, to add a button to the WordPress text editor, we need to use Quicktags API.

Place this code in youtube-embed.php file to display the button:

function youtube_shortcode_text_editor_script() 
{
    if(wp_script_is("quicktags"))
    {
        ?>
            <script type="text/javascript">

                QTags.addButton( 
                    "youtube_shortcode", 
                    "Youtube Embed", 
                    youtube_callback
                );

                function youtube_callback()
                {
                	var id = prompt("Please enter your video id");

					if (id != null) 
					{
						QTags.insertContent('
'); } } </script> <?php } } add_action("admin_print_footer_scripts", "youtube_shortcode_text_editor_script");

Here, we’re adding a button named youtube_shortcode. When a user clicks the button, youtube_callback is fired to take the user input and add the shortcode.

Here’s what it looks like in the text editor:

YouTube Shortcode Button

Creating a Visual Editor Button to Add a Shortcode

Similarly, we can add a button to the visual editor. For this we need to create a TinyMCE plugin.

Place this code in the youtube-embed.php file to register a TinyMCE plugin:

function enqueue_mce_plugin_scripts($plugin_array)
{
    //enqueue TinyMCE plugin script with its ID.
    $plugin_array["youtube_button_plugin"] =  plugin_dir_url(__FILE__) . "mce.js";
    return $plugin_array;
}

add_filter("mce_external_plugins", "enqueue_mce_plugin_scripts");

function register_mce_buttons_editor($buttons)
{
    //register buttons with their id.
    array_push($buttons, "youtube");
    return $buttons;
}

add_filter("mce_buttons", "register_mce_buttons_editor");

Next, we need to write the JavaScript functionality to display a prompt to take the ID as input and add our shortcode. To do this, place the following code in the mce.js file:

(function() {
    tinymce.create("tinymce.plugins.youtube_button_plugin", {

        init : function(ed, url) {

            //add new button     
            ed.addButton("youtube", {
                title : "Youtube Embed",
                cmd : "youtube_command",
                image : "https://cdn3.iconfinder.com/data/icons/free-social-icons/67/youtube_square_color-32.png"
            });

            //button functionality.
            ed.addCommand("youtube_command", function() {
                var id = prompt("Please enter your video id");
                if (id != null) 
                {
                    ed.execCommand("mceInsertContent", 0, '
'); } }); }, createControl : function(n, cm) { return null; }, getInfo : function() { return { longname : "Extra Buttons", author : "Narayan Prusty", version : "1" }; } }); tinymce.PluginManager.add("youtube_button_plugin", tinymce.plugins.youtube_button_plugin); })();

We now add a button named youtube, when user clicks on the button we execute the youtube_command callback.

Here’s how it looks:

YouTube Shortcode Button in the Visual Editor

Conclusion

In this tutorial, we saw how to create a YouTube embed plugin that can embed YouTube videos without increasing page size and also making our videos responsive. This is a small, but very useful plugin.

Comments
Tomas_Kapler

Dislike - you are copying native wordpress functionality, with much worse experience for editor (no preview, need for useless shortcode ...) and why? Just because you want your youtube to be responsive? This can be FAR more easier - simply use embed_oembed_html or oembed_result filter, and modify the HTML produced by the native wordpress oembed. It is generaly one row formula. E.g. if you are using twitter bootstrap and are preparing 16 by 9 videos, you can simply enclosed the produced embed code to div with class "embed-responsive embed-responsive-16by9" and it will automagicaly fit available place.

narayanprusty

@Tomas_Kapler If you read the tutorial then you must have seen how youtube impacts page speed. This plugin address both these problems. You cannot load videos dynamically using the filter. WordPress filters just provide some level of customization. You can further extend the plugin to customize the attributes of the player.

You can see this plugin https://wordpress.org/plugins/embedplus-for-wordpress/screenshots/ how it has a lot of other functionalities. Here we are trying to achieve customization without touching WordPress default behaviour.

If you still think there is a better way to load youtube videos dynamically then leave your comment.

teighlorre

Thank you! Is this applicable to Facebook video embed codes as well?

narayanprusty

@teighlorre No this plugin is only for youtube videos.

Facebook videos are by default responsive. Facebook embed code takes care of it. To load facebook videos dynamically you can tweak the facebook embed code instead of creating a plugin.

collizo4sky

@Tomas_Kapler You are right with what you said.

More often than not, we miss the aim of tutorials of this nature. Although they seems to reinvent a wheel, but they are written to show us how things can be done and in this case, how a peculiar kind of plugin can be developed in WordPress.

More grease to your elbow @narayanprusty.

Recommended
Sponsors
Because We Like You
Free Ebooks!

Grab SitePoint's top 10 web dev and design ebooks, completely free!

Get the latest in WordPress, once a week, for free.