Deferred lazy loading of Facebook widgets

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 :)

Like it? Share it!

16 Responses to “Deferred lazy loading of Facebook widgets”

  1. Posted September 2, 2011 at 2:45 am
    Permalink
    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. Posted September 6, 2011 at 2:50 am
    Permalink
    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. Posted December 1, 2011 at 6:23 am
    Permalink
    Merci pour cet article très intéressant! Joli PageSpeed sur forexagone.com :)
  4. asdf
    Posted January 19, 2012 at 10:31 am
    Permalink
    Im getting in Chrome some error in javascript.

    Uncaught SyntaxError: Unexpected identifier.

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

    ¿Where is checkScrollOnForumPage function?
  5. Posted January 19, 2012 at 2:03 pm
    Permalink
    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. Posted May 16, 2012 at 8:54 am
    Permalink
    hi,

    many thanks for sharing this great information.
    I've just used it on a site and it works like a charm.
  7. silversurfer
    Posted May 16, 2012 at 2:29 pm
    Permalink
    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. Posted May 18, 2012 at 5:00 am
    Permalink
    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
    Posted May 18, 2012 at 7:19 pm
    Permalink
    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. Posted May 22, 2012 at 6:26 am
    Permalink
    Silversurfer, tu peux me copier/coller le code en entier que tu utilises stp?
  11. silversurfer
    Posted May 22, 2012 at 8:49 am
    Permalink
    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. Posted May 22, 2012 at 8:58 am
    Permalink
    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
    Posted May 22, 2012 at 2:22 pm
    Permalink
    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. Posted May 24, 2012 at 2:09 am
    Permalink
    Cool que ça fonctionne au final pour toi ;-)

Leave a Reply