Deferred lazy loading of Facebook widgets

Posted on August 13, 2011
by

Facebook Like BoxIf you use social widgets on your web pages, you must be aware of the extra kilobytes of data your visitors are going to load for this, and how it’s going to affect the loading time of your pages. It can be difficult to figure the weight of those widgets, but sometimes they’re worth considering them.

You can use Firefox and the plugin YSlow to measure how those social widgets overweight your pages (see total size of the page, loading time, and number of external JS/CSS/image files loaded).

In this post, I will consider the case of the Facebook Like Box, which is a quite fat widget actually (almost 200kB of data amongst 6 external JS scripts, 4 CSS sheets, 2 CSS image sprites and as much images as there are fans of your page) and how I can manage to load it ONLY IF NEEDED.

Defer loading of the widget

First, it’s good to defer the loading of the widget so that it loads when the rest of the page is already loaded (because the page itself should have higher priority on the optional widgets). To do so, we will use jQuery, add this piece of code anywhere on your page:

$(document).ready(function() {
$('#facebookHolder').append('<div id="fb-root"></div>');
$('#facebookHolder').append('<fb:like-box href="http://www.facebook.com/forexagone" width="300" show_faces="true" stream="false" header="false"></fb:like-box>');
 
jQuery.getScript('http://connect.facebook.net/en_US/all.js#xfbml=1', function() {
FB.init({status: true, cookie: true, xfbml: true});
});
});

You also need a place holder somewhere on your page to hold the widget, such as:

<div id="facebookHolder"></div>

Now, the widget will start loading only ONCE the page itself is loaded.

Lazy load the widget

It can happen that your social widget is embedded in a long page and the user needs to scroll to see it on his screen. Then, there is obviously no interest in loading 200 extra kilobytes of data as long as the widget is not in the browser’s viewport (is not visible on the screen). That’s what we call lazy loading: we only load what we need to load. You’ve probably seen this technique on websites such as TechCrunch, that load the images on the page as you are scrolling it down (see the jquery plugin Lazy Load by Mika Tuupola — deprecated though, since it’s not supported anymore for latest browsers). Mika also wrote the Viewport selectors for jQuery that I’m going to use for lazy loading my social widget.

So the idea is to not load the social widget when your page is loading, and if the user ever happens to scroll down enough to make the social widget placeholder to appear in the browser’s viewport, then we eventually load the widget.

Here is the JavaScript you need to load (but well, it’s very likely that you already use jQuery, isn’t it?)

<script src="jquery.js"></script>
<script src="jquery.viewport.js"></script>

Here is the HTML code for the placeholder of your social widget:

<div id="facebookHolder"></div>

And here is the JavaScript code to defer and lazy load the widget:
/**
* check if facebookHolder is in viewport, and then load Like Box widget
*/
$(document).ready(function() {
function checkScrollingForWidget(event) {
$('#facebookHolder:in-viewport').each(function() {
$('#facebookHolder').append('<div id="fb-root"></div>');
$('#facebookHolder').append('<fb:like-box href="http://www.facebook.com/forexagone" width="300" show_faces="true" stream="false" header="false"></fb:like-box>');
 
jQuery.getScript('http://connect.facebook.net/en_US/all.js#xfbml=1', function() {
FB.init({status: true, cookie: true, xfbml: true});
});
 
$(window).unbind('scroll', checkScrollingForWidget);
}
 
$(window).bind('scroll', checkScrollingForWidget);
});

This works well for all the Facebook widgets. You will have to adapt the code to the other social widgets you’re using, but the idea remains the same.

Practical example

In Forexagone.com (website I co-founded), we embed a Facebook Like Box at the bottom of the forum page. It’s a long page, and not everybody is likely to scroll down enough and see the widget on the screen. Therefore, I applied the lazy loading behaviour to the Facebook Like Box widget, and I was very happy  to see that I improved by a factor 2 the loading time of my page, and decreased its total size by 200kB.

Lazy Loading Forexagone

That will save some time and bandwidth. I think Google (and the visitors) will appreciate 🙂

About the author

Cyril Mazur is a serial web entrepreneur with experience in various fields: online dating, forex & finance, blogging, online advertising... who enjoys building things that people like to use.

19 comments

  1. Eric
    on September 2, 2011
    Not sure if my last comment was filtered because of the code, so I'm posting it again and replaced the brackets:

    Nice code, thanks!

    I'm using it with Wordpress and added the code to the sidebar file of the theme. But although Wordpress includes a minified version of Jquery in the header*, it doesn't work unless I add [script src="http://code.jquery.com/jquery-1.6.1.js"][/script] right above your code (in the sidebar).

    Any idea why this is?

    * [script type='text/javascript' src='http://www.myblog.com/wp-includes/js/jquery/jquery.js?ver=1.6.1'][/script]
  2. Cyril
    on September 6, 2011
    Hi Eric,

    You haven't been put to the trash, I was just away from the Internet for one week recently (Burning Man YEY).

    Can you check if putting "$(function(){" instead of "$(document).ready(function() {" solves the problem? I'm afraid that the Javascript code for the lazyloading feature is executed BEFORE the jQuery library is loaded.

    Also, I tested my code with jQuery 1.4.4, so maybe it's a problem related to jQuery's version...

    Regards.
  3. Julien
    on December 1, 2011
    Merci pour cet article très intéressant! Joli PageSpeed sur forexagone.com :)
  4. asdf
    on January 19, 2012
    Im getting in Chrome some error in javascript.

    Uncaught SyntaxError: Unexpected identifier.

    Here: $(window).bind('scroll', checkScrollOnForumPage);

    ¿Where is checkScrollOnForumPage function?
  5. Cyril
    on January 19, 2012
    Hi asdf,

    This is my mistake, the correct function name is well "checkScrollingForWidget" and not "checkScrollOnForumPage" (wrong copy/paste from my testing environment). I corrected the code example. Thanks!
  6. andrei victor
    on May 16, 2012
    hi,

    many thanks for sharing this great information.
    I've just used it on a site and it works like a charm.
  7. silversurfer
    on May 16, 2012
    Bonjour Cyril,

    Le code ne fonctionne pas du tout avec mon site web. Il ne se passe rien. Existe-il un moyen en utilisant le code facebook mais en html5?
    A noter que mon site est fait avec joomla 2.5
  8. Cyril
    on May 18, 2012
    Silversurfer, as-tu regardé dans la console JS s'il y a une erreur lancée? Il est possible de le faire en HTML5 aussi mais il faut adapter le code un petit peu, rien de méchant :)
  9. silversurfer
    on May 18, 2012
    Bonjour Cyril,

    Alors oui la console me donne ce message:
    missing ) after argument list
    $(window).bind('scroll', checkScrollingForWidget);

    Avec une petite fleche qui pointe sur le "$"

    Pour le faire en HTML5, malheuresement je ne connais pas suffisament le javascript. :-(

    Merci pour tout
  10. Cyril
    on May 22, 2012
    Silversurfer, tu peux me copier/coller le code en entier que tu utilises stp?
  11. silversurfer
    on May 22, 2012
    Bien sur et merci à toi:




    &lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; xml:lang=&quot;language; ?&gt;" lang="language; ?&gt;" dir="direction; ?&gt;" &gt;




    &lt;link rel=&quot;stylesheet&quot; href=&quot;baseurl ?&gt;/templates/template ?&gt;/css/style.css" type="text/css"&gt;





    /**
    * check if facebookHolder is in viewport, and then load Like Box widget
    */
    $(document).ready(function() {
    function checkScrollingForWidget(event) {
    $('#facebookHolder:in-viewport').each(function() {
    $('#facebookHolder').append('');
    $('#facebookHolder').append('');

    jQuery.getScript('http://connect.facebook.net/en_US/all.js#xfbml=1', function() {
    FB.init({status: true, cookie: true, xfbml: true});
    });

    $(window).unbind('scroll', checkScrollingForWidget);
    }

    $(window).bind('scroll', checkScrollingForWidget);
    });





    <a href="http://www.destockforum.com" rel="nofollow"> </a>















    id == 0){ ?&gt;
















    Copyright &amp;copy 2012 Destockforum. Tous droits réservés.




    var _gaq = _gaq || [];
    _gaq.push(['_setAccount', 'UA-31444402-1']);
    _gaq.push(['_trackPageview']);
    (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
    })();




    par contre bizarrement en utilisant le code de forexagone cela fonctionne. Tu peux jeter un oeil sur mon site web: destockforum.com

    merci de ton aide et a bientot
  12. Cyril
    on May 22, 2012
    Pour ce que je vois c'est une erreur de syntaxe, je vois une accolade et une parenthèse qui ne se ferment pas... Indente ton code et vois par toi-même ;-) Au pire utilises le code de Forexagone et change simplement l'URL de la fan page de Forexagone par l'URL de ta fan page à toi.
  13. silversurfer
    on May 22, 2012
    Bonjour Cyril,

    J'ai effectivement trouver une accolade et une parenthèse manquante, mais malheureusement ça ne fonctionne toujours pas. Peux être un conflit javascript.
    De toute manière je vais suivre ton conseil et utiliser le code de forexagone. Celui-ci fonctionne avec moi. ;-)
  14. Cyril
    on May 24, 2012
    Cool que ça fonctionne au final pour toi ;-)
  15. Yves
    on July 10, 2013
    Love this script.

    But what if you have multiple facebook widgets? (I have a list of articles with the thumbs widget)
  16. Cyril
    on July 14, 2013
    Hi Yves, the script as it is only works for one widget, though it wouldn't be difficult to adapt it for many widgets (using a loop and an array).

    Code is old fashioned, it's not really jquery oriented (I would code it way better nowadays), but it gets the job done :)
  17. Namlun
    on September 9, 2013
    Nice tip. Thanks a lot!

Leave a Reply