How To Create An Embeddable Content Plugin For WordPress

Advertisement

WordPress is one of the most deployed content management systems around. One of the main reasons is the number of plugins available and the ease with which we can use the system. It is not uncommon to find websites using tens of plugins to accomplish various tasks and functions. Wouldn’t it be nice if you could share your site content with other websites!

You may have a need to share advertisements, product information or, if you are a designer, your photo gallery. Whatever the reason, this article will show you a way to create an embeddable content plugin to share your WordPress content with other websites.

Share WordPress content via widgets.1

Ways Of Sharing Content

There are various ways with which one can share content across websites — RSS and Atom feeds, APIs and embeddable widgets. RSS feeds on WordPress are usually restricted to posts, while APIs are not easy to integrate on other websites without adding some extra code. This leaves us with embeddable widgets — like the ones used by Google AdSense to display advertisements on websites or Facebook “Share” and “Like” buttons — all of these rely on embeddable JavaScript code to display specific content on a website. The idea mentioned in this article is certainly not new, but in the context of WordPress it opens up many possibilities. The advantages of the technique mentioned here compared with others is that it will enable you to share almost any content, even content from other plugins on your blog, with other websites.

Our goal in this article is to create widget code that a user could insert in their website to display a list of recent posts from the parent website. Of course, this can also be easily accomplished using RSS, but this is just an example to show the technique. In reality, you would use it for more interesting purposes, like sharing popular product images if you are running a WordPress e-commerce website.

The Widget Code

The embeddable code will look something like the following. This is the code the user will insert into their webpage, which will allow them to display the content from the parent website. The crucial element of this widget is the wp-widget.js file, which calls the remote WordPress website, gets the content and embeds it as an iframe in the calling page.

<script type="text/javascript">
  var widget_embed = 'posts';
</script>
<script src="http://www.example.com/widget/wp-widget.js"
type="text/javascript">
</script>
<div id="embed-widget-container"></div>

Adding this block of code to any website page will display the list of recent posts from example.com. The content can be anything besides posts — images, comments, tags, data from other plugins — anything you as a WordPress website owner would like to share with other people. For this example, I’ve limited the content to a simple posts list, as this is a common denominator across all WordPress websites and will be easy to start with. Of course, you will need to add some extra code to share other content, but the base plugin skeleton will remain the same.

Creating The Plugin

The fist step in creating an embeddable widget is to design a small WordPress plugin that will intercept the widget calls from another website and return the required data. You may be thinking that this will be a knotty job, but nothing could be easier. Just a few lines of code and our plugin is ready. The complete code for the plugin is shown below. I’ll explain how this works as we proceed along.

To get the content from the plugin, we will need to pass a query parameter of what content we would like from the remote server in the em_embed variable. This query parameter will then be intercepted by the plugin and the corresponding content returned. We will also pass along implicitly the domain URL of the calling page, so we can later use it for analytics purposes or for restricting the websites which can embed our widget.

For example, to get the list of recent posts, we need to send a GET query to the main WordPress website as shown below. Of course this query will be created by our JavaScript widget, wp-widget.js.

http://www.example.com/?em_embed=posts

The complete code for the plugin is given below.

<?php

/**
 * Plugin Name: WordPress Widget Embed
 * Description: Allow people to embed WordPress content in an iframe on other websites
 * Version: 1.0
 * Author: Sameer Borate
 * Author URI: http://www.codediesel.com
 */

class WPWidgetEmbed  
{
    public function __construct()
    {
        add_action('template_redirect', array($this, 'catch_widget_query'));
        add_action('init', array($this, 'widget_add_vars'));
    }
    
    /**
     * Adds our widget query variable to WordPress $vars
     */
    public function widget_add_vars() 
    { 
        global $wp; 
        $wp->add_query_var('em_embed'); 
        $wp->add_query_var('em_domain'); 
    }
    
    private function export_posts()
    {
        $outstring  = '<html>';
        $outstring .= '<head><style>';
        $outstring .= 'ul {
                padding:0;
                margin:0;
              }
              li {
                 list-style-type:none;
               }';
        $outstring .= '</style></head><body>';
         
        /* Here we get recent posts for the blog */
        $args = array(
            'numberposts' => 6,
            'offset' => 0,
            'category' => 0,
            'orderby' => 'post_date',
            'order' => 'DESC',
            'post_type' => 'post',
            'post_status' => 'publish',
            'suppress_filters' => true
        );
        
        $recent_posts = wp_get_recent_posts($args);
        
        $outstring .= '<div class="widget-posts"><ul>';
        foreach($recent_posts as $recent)
        {
            $outstring .= '<li><a target="_blank" href="' . get_permalink($recent["ID"]) . '">' . $recent["post_title"]. '</a></li>';
        }
        
        $outstring .= '</ul></div>';
        $outstring .= '</body></html>';
        
        return $outstring;
    }

    /**
     * Catches our query variable. If it's there, we'll stop the
     * rest of WordPress from loading and do our thing, whatever 
     * that may be. 
     */
    public function catch_widget_query()
    {
        /* If no 'embed' parameter found, return */
        if(!get_query_var('em_embed')) return;
        
        /* 'embed' variable is set, export any content you like */
        
        if(get_query_var('em_embed') == 'posts')
        { 
            $data_to_embed = $this->export_posts();
            echo $data_to_embed;
        }
        
        exit();
    }
}
 
$widget = new WPWidgetEmbed();

?>

To successfully intercept calls from another website, we need to first add the em_embed and em_domain parameters to our WordPress query_var variable. This will be used later to see what kind of data needs to be sent to the remote website. This is done by the following function.

public function widget_add_vars() 
{ 
    global $wp; 
    $wp->add_query_var('em_embed'); 
    $wp->add_query_var('em_domain');
}

Next, we will need to catch the query variable on the template_redirect hook and process any data if the em_embed variable is set in the global variable.

public function catch_widget_query()
{
    /* If no 'embed' parameter found, return */
    if(!get_query_var('em_embed')) return;
    
    /* 'embed' variable is set, export any content you like */
    
    if(get_query_var('em_embed') == 'posts')
    { 
        $data_to_embed = $this->export_posts();
        echo $data_to_embed;
    }
    
    exit();
}

In our example, we will be exporting a list of recent post titles, so our export_posts function will look like below.

private function export_posts()
{
    $outstring  = '<html>';
    $outstring .= '<head><style>';
    $outstring .= 'ul {
             padding-left:10px;
             margin:0;
          }
          
          li > a {
             text-decoration: none;
             font-family: Arial, Helvetica, Sans-serif;
             font-size:12px;
             
          }
           
          li {
             border-bottom: 1px solid #c0c0c0;
             padding: 3px 0 3px 0;
          }
    
          .widget-posts {
             width: 250px;
             border: 1px solid #c0c0c0;
             padding: 12px;
             margin-left: 3px;
          }';
    $outstring .= '</style></head><body>';
     
    /* Here we get recent posts for the blog */
    $args = array(
        'numberposts' => 6,
        'offset' => 0,
        'category' => 0,
        'orderby' => 'post_date',
        'order' => 'DESC',
        'post_type' => 'post',
        'post_status' => 'publish',
        'suppress_filters' => true
    );
    
    $recent_posts = wp_get_recent_posts($args);
    
    $outstring .= '<div id="widget-posts"><ul>';
    foreach($recent_posts as $recent)
    {
        $outstring .= '<li><a target="_blank" href="' . get_permalink($recent["ID"]) . '">' . $recent["post_title"]. '</a></li>';
    }
    
    $outstring .= '</ul></div>';
    $outstring .= '</body></html>';
    
    return $outstring;
}

This is all there is to the plugin. If you need to export any other data, you will need to replace the code for getting posts with code for getting the data you like.

Writing The Embeddable Widget Code

We have now completed only the part for the WordPress plugin. We still have to write the JavaScript embed code which will remotely access our website and insert the appropriate content into the calling page. The easiest way to display content from another website into your Web page is by using an iframe. The code needed to embed the content on a website is shown below.

<script type="text/javascript">
  var widget_embed = 'posts';
</script>
<script src="http://www.example.com/widget/wp-widget.js"
type="text/javascript">
</script>
<div id="embed-widget-container"></div>

If you are going to use the widget for returning only a single type of data,you can do away with the widget_embed variable. So you will have something like the following.

<script src="http://www.example.com/widget/wp-widget.js"
type="text/javascript">
</script>
<div id="embed-widget-container"></div>

wp-widget.js is the JavaScript that does all the work of calling the remote WordPress website and adding the content to the iframe. You need to place the wp-widget.js file in a subdirectory on your WordPress website; the exact name and location does not matter.

The complete code for the wp-widget.js is shown below, and is self-explanatory.

/**
  * wp-widget.js
  *
  * Inserts an iframe into the DOM and calls the remote embed plugin
  * via a get parameter:
  * e.g http://www.example.com/?embed=posts
  * This is intercepted by the remote 'WordPress Widget Embed' plugin
  *
  */

(function() {

// Localize jQuery variable
var jQuery;

/* Load jQuery if not present */
if (window.jQuery === undefined || window.jQuery.fn.jquery !== '1.7.2') 
{
    var script_tag = document.createElement('script');
    script_tag.setAttribute("type","text/javascript");
    script_tag.setAttribute("src",
        "http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js");
    if (script_tag.readyState) 
    {
      script_tag.onreadystatechange = function () 
      { // For old versions of IE
          if (this.readyState == 'complete' || this.readyState == 'loaded') 
          {
              scriptLoadHandler();
          }
      };
    } 
    else 
    {
      script_tag.onload = scriptLoadHandler;
    }
    
    (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag);
} 
else 
{
    // The jQuery version on the window is the one we want to use
    jQuery = window.jQuery;
    main();
}


/* Called once jQuery has loaded */
function scriptLoadHandler() 
{
    jQuery = window.jQuery.noConflict(true);
    main(); 
}

/* Our Start function */
function main() 
{ 
    jQuery(document).ready(function($) 
    { 
        /* Get 'embed' parameter from the query */
        var widget = window.widget_embed;
        var domain = encodeURIComponent(window.document.location);
    
        /* Set 'height' and 'width' according to the content type */
        var iframeContent = '<iframe style="overflow-y: hidden;" 
                             height="550" width="400" frameborder="0" 
                             border="0" cellspacing="0" scrolling="no" 
                             src="http://www.example.com/?em_embed=' + widget + '&em_domain=' + domain + '"></iframe>';
                             
        $("#embed-widget-container").html(iframeContent);
    });
}

})();

The task of inserting the iframe and the WordPress content in the DOM is accomplished by the main() function. The iframe size needs to be changed depending on your requirements or created dynamically by letting the user pass additional parameters along with the widget_embed variable in the main widget code.

Adding Custom CSS To The Content

You can also add custom CSS to the displayed content through the plugin. Sample CSS to go with the above plugin is given below. You can also specify a style sheet URL if needed.

private function export_posts()
{
    $outstring  = '<html>';
    $outstring .= '<head><style>';
    $outstring .= 'ul {
             padding-left:10px;
             margin:0;
          }
          
          li > a {
             text-decoration: none;
             font-family: Arial, Helvetica, Sans-serif;
             font-size:12px;
          }
           
          li {
             border-bottom: 1px solid #c0c0c0;
             padding: 3px 0 3px 0;
          }
          
          .widget-posts {
             width: 250px;
             border: 1px solid #c0c0c0;
             padding: 12px;
             margin-left: 3px;
          }';
    $outstring .= '</style></head><body>';
    .
    .

The type of CSS you add to the content will depend on what content you are displaying. With a little creative coding, you can also allow the user to add certain display options to the widget with which they can control the display style of the embedded widget.

Restricting Display To Certain Domains

You may want to allow only certain domains to be able to display your content using the widget. This can easily be made possible, as we already have the calling website’s url in the em_domain variable. All we have to do is check the domain and selectively allow the content to be displayed.

public function catch_widget_query()
{
    /* If no 'embed' parameter found, return */
    if(!get_query_var('em_embed')) return;
    
    /* 'embed' variable is set, export any content you like */
    
    if(get_query_var('em_embed') == 'posts')
    { 
        $allowed_domains = array('site1.com',
                                 'site2.com',
                                 'site3.com');
                                 
        $calling_host = parse_url(get_query_var('em_domain'));
        
        /* Check if the calling domain is in the allowed domains list */
        if(in_array($calling_host['host'], $allowed_domains))
        {
            $data_to_embed = $this->export_posts();
            echo $data_to_embed;
        }
        else
        {
            echo "Domain not registered!";
        }
    }
    
    exit();
}

Performance Concerns

Allowing other websites to access your content via widgets means additional load on your servers. A few hundred websites using your widget could easily slow down your server, so take this factor into consideration when promoting widgets. However, plugins like WP Super Cache can be used to cache widget data and reduce server load. If you are not using WP Super Cache or any other cache plugin, you can try using the WordPress Transients API 2 to save the results into the database.

The WordPress Transients API offers a simple and standardized way of storing cached data in the database temporarily by giving it a custom name and a time frame, after which it will expire and be deleted. The catch_widget_query() function after adding the WP Transient API code is shown below.

public function catch_widget_query()
{
    /* If no 'embed' parameter found, return */
    if(!get_query_var('em_embed')) return;
    
    /* 'embed' variable is set, export any content you like */
    
    if(get_query_var('em_embed') == 'posts')
    { 
        /* Here we are now using the 'WP Transient API'. 
           See if we have any saved data for the 'ewidget' key.
         */
        $cached = get_transient('ewidget');
        
        /* Oops!, the cache is empty */
        if(empty($cached))
        {
            /* Get some fresh data */
            $data_to_embed = $this->export_posts();
            
            /* Save it using the 'WP Transient API' using the 'ewidget' key,
               set it to expire after 12 hours.
             */
            set_transient('ewidget', $data_to_embed, 60 * 60 * 12);
            echo $data_to_embed;
        }
        /* Yes we found some, so we return that to the user */
        else
        {
            echo $cached;
        }
    }
    
    exit();
}

In Conclusion

Sharing your content across different websites is a nice way to market your services and create brand awareness. With millions of WordPress websites around, there is a huge amount of content out there that can be profitably shared among users. Not just text, but also images, videos, advertisements, etc. This article is just a simple implementation of an embeddable widget. You can customize it in various ways to include security, analytics code to track widget usage and other functionality.

(cp)

Footnotes

  1. 1 http://www.smashingmagazine.com/wp-content/uploads/2012/10/wordpress-embed.png
  2. 2 http://codex.wordpress.org/Transients_API

↑ Back to topShare on Twitter

Sameer Borate is a freelance web developer, working primarily in PHP and MySQL. He blogs about his various interests and web topics at www.codediesel.com. When away from blogging or writing code, he spends his free time reading non-fiction books. He is of the staunch opinion that the Semantic Web is the next frontier of the Internet and would like to make some time to delve into its mysteries.

Advertising

Note: Our rating-system has caused errors, so it's disabled at the moment. It will be back the moment the problem has been resolved. We're very sorry. Happy Holidays!

  1. 1

    Great idea and presentation! Thanks!

  2. 2

    Wonderful article, thanks! :)

  3. 3

    Interesting post Sameer, definitely learned a thing or two from your post! Thanks :)

    I’ve got one remark though; at line 59 where you output the title using $recent[“post_title”], wouldn’t it be a lot better to escape the output of this variable using something like: htmlspecialchars($recent[‘post_title’], ENT_QUOTES). Otherwise, you could easily insert HTML or Javascript into the post title (whether intentional or not) and potentially do things it should not be able to do at all on other websites that use the plugin to embed content on their websites.

    • 4

      While the sample code didn’t use it, the best option would probably be esc_html() and esc_attr(). Both are utility functions that WordPress provides for just that purpose.

  4. 5

    Why bother with JS at all?

    Keep the plugin simple and just give the iframe code to embed in the remote site

    • 6

      Besides the iframe code being unwieldy, using JavaScript offers us the flexibility to process the iframe content after displaying.

  5. 7

    This article’s use of the term “widget” in the context of WordPress is very misleading. This subject matter has absolutely nothing to do with the WordPress Widgets API. “Embeddable content” is an awkward phrase but would probably be less confusing.

  6. 8

    Great article. I’ve got need of this type of embedded content in a current project and you just showed me a fairly easy way to do it!

    Have to agree with the other comments that properly ensuring you don’t return anything that could break another site is SUPER important.

  7. 9

    This is a very handy plugin, thanks so much. I often have a need to pull in RSS feed info into WordPress client sites, so I’ll add this option to the mix now.

  8. 10

    can anyone help me to get wp theme or plugin licence

  9. 11

    This is a very nice technique. And I think it can be better if we use a custom template file (using “template_include”). That way, we can enqueue scripts and styles, no need to out put them directly in the code, which breaks the rule of separating HTML & PHP.

  10. 12

    Such creativity, i wonder why i always discover such simple methods after I’ve already gone the long route, thanks for sharing, am going to have to modify some sites…

  11. 13

    Daniel from Design Quotes

    November 16, 2012 8:49 am

    It’s a great idea. Part of why WordPress is so widely adopted is because it allows non coders to create high functionality websites.

    I think this kind of plugin could really help viral focused content like infographics spread plus provide SEO value. Imagine an embeddable infographic that includes a link back to the source? That could produce some serious SEO value for the original creator.

  12. 14

    Great!!
    Thanks for such type of help..I am going to implement it.

  13. 15

    Though I used Drupal Development but now I m going to use WordPress ,your content gave me better idea about WP.

  14. 16

    I’m not an experienced widget developer but I followed your instructions and I’m getting Error 403 forbidden (see below).

    I’d love to get this working. Any suggestions would be appreciated!

    Error 403: Forbidden
    Your PHP settings have been disabled by an H-Sphere administrator.
    Your current PHP configuration:
    –>
    This configuration was changed:

    Please bring your PHP configuration in compliance with admin settings or request your administrator to re-enable support of your settings.

    You don’t have permissions to access this page. This usually means one of the following:

    this file and directory permissions make them unavailable from the Internet.
    .htaccess contains instructions that prevent public access to this file or directory.

    Please check file and directory permissions and .htaccess configuration if you are able to do this. Otherwise, request your webmaster to grant you access.

  15. 18

    It is nice think to have knowledge of anything but sharing knowledge is far more better than to have ! Thank you so beautiful tutorial.

  16. 19

    Thanks for this artikel.Overzichtelijk and interesting. Make yourself here now use in my WordPress websites.The content can thus be read to multiple websites.
    My thanks for this.

  17. 20

    Missing doctype for that outstring btw

  18. 21

    your code is too good. thanks for sharing…!

  19. 22

    Hi,
    I’m looking for something similar that would show the “Embed code” for the single post at the end of each post or even better in a widget….
    The embedded code should show this post only on other sites in “iframe” or anything like that.

    Any help?

    thanks!

    btw. Is there a downloadable version for this plugin?

  20. 23

    Thanks for the nice article. How could I modify this to show the content of a specific page instead?

  21. 24

    Thanks! Excellent tutorial

  22. 25

    the gods of WP are crying, just use the RSS feed system already in place and tell the user: embed this iframe

  23. 26

    dear sir
    is it possible to create Embeddable Content Plugin For WordPress slider and slides?
    thanx

Leave a Comment

Yay! You've decided to leave a comment. That's fantastic! Please keep in mind that comments are moderated and rel="nofollow" is in use. So, please do not use a spammy keyword or a domain as your name, or else it will be deleted. Let's have a personal and meaningful conversation instead. Thanks for dropping by!

↑ Back to top