Javascript - Loading social plugins dynamically on the page after the page has loaded

The last couple of days saw page load times for my website increase significantly. As I checked my server logs for hints of potential issues, nothing seemed abnormal. The traffic was a notch higher but less than a fraction of server capacity, the server resource usage was perfectly normal and no signs of any other problem.

However I consistently noticed that the static resources (css, images etc) were taking longer to load which was increasing the actual and perceived render time for the pages impacting usability. As I contacted my hosting provider, I decided to see if there was something I can do to reduce page load times until the time my hosting provider can work (with me) to successfully locate the issue and resolve it.

Ultimately the issue was pointed out to "a bad hop outside the hosting provider's network and the solution from their side being to contact the hop location and working on routing traffic around the bad hop". This actually resolved the issue for me and I saw page load times improve after that but in the meantime, I had done something to improve the load times for the pages on my websites by reducing the number of resources loaded with the page.

It started with delaying the loading of Google Translate. I noticed that it was taking some time for the resources to be loaded from translate.googleapis.com domain (not sure what was causing this) and I decided to put Google Translate on the page after the page had loaded completely.

So instead of putting this on the page:

{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; }<script> function googleTranslateElementInit() { new google.translate.TranslateElement({ pageLanguage: 'en', gaTrack: true, gaId: 'UA-XXXXXXXX-1', floatPosition: google.translate.TranslateElement.FloatPosition.TOP_RIGHT }); } </script> <script src="http://translate.google.com/translate_a/element.js?cb=googleTranslateEle..."></script>{/syntaxhighlighter}

I changed it to:

{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; }<script> function googleTranslateElementInit() { new google.translate.TranslateElement({ pageLanguage: 'en', gaTrack: true, gaId: 'UA-XXXXXXXX-1', floatPosition: google.translate.TranslateElement.FloatPosition.TOP_RIGHT }); } jQuery(document).ready(function() { jQuery(document.head).append(decodeURIComponent('%3Cscript%20src%3D%22http%3A%2F%2Ftranslate.google.com%2Ftranslate_a%2Felement.js%3Fcb%3DgoogleTranslateElementInit%22%3E%3C%2Fscript%3E')); }); </script>{/syntaxhighlighter}

You would notice I simply hooked onto jQuery's document ready callback to dynamically insert the Google Translate script on the page after core components of my page were finished loading. The results were encouraging, I saw a perceived improvment in page load time.

Having done this, I looked further to see what other things can be delay loaded. The obvious candidates that surfaced were the social plugins for Twitter, Facebook and Google Plus. So I attacked them next one at a time, starting with Twitter.

The following code for Twitter's Tweet widget:

 

<div style="float: left; width: 60px">
<a href="http://twitter.com/share" class="twitter-share-button" data-count="vertical" data-via="rahuls_log">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script>
</div>

 

changed to:

{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; }<div id="custom-social-bookmarks-twitter" style="float: left; width: 60px"></div> <script type="text/javascript"> jQuery(document).ready(function() { jQuery('#custom-social-bookmarks-twitter').append(decodeURIComponent('%3Ca%20href%3D%22http%3A%2F%2Ftwitter.com%2Fshare%22%20class%3D%22twitter-share-button%22%20data-count%3D%22vertical%22%20data-via%3D%22rahuls_log%22%3ETweet%3C%2Fa%3E%3Cscript%20type%3D%22text%2Fjavascript%22%20src%3D%22http%3A%2F%2Fplatform.twitter.com%2Fwidgets.js%22%3E%3C%2Fscript%3E')); }); </script>{/syntaxhighlighter}

Voila Twitter did not had a problem with that and was happy to be delayed until the time more important components of my page were finished coming home to the browser.

Next in line are you Facebook my friend, I said to myself. But as it turned out, Facebook presented some resistance in being delay loaded. Here's the initial code that put the Facebook's Like button statically on the page:

 

<div style="float: left; width: 60px">
<div id="fb-root"></div><script src="http://connect.facebook.net/en_US/all.js#appId=224287964265938&amp;xfbml=1"></script><fb:like href="" send="true" layout="box_count" width="50" show_faces="false" font=""></fb:like>
</div>

 

The first attempt to load it dynamically was to append the entire <script> tag and the <fb:like> tag to the page when it was ready like this:

{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; }<div id="custom-social-bookmarks-facebook" style="float: left; width: 60px"><div id="fb-root"></div></div> <script type="text/javascript"> jQuery(document).ready(function() { jQuery('#custom-social-bookmarks-facebook').append(decodeURIComponent('%3Cscript%20src%3D%22http%3A%2F%2Fconnect.facebook.net%2Fen_US%2Fall.js%23appId%3D224287964265938%26amp%3Bxfbml%3D1%22%3E%3C%2Fscript%3E%3Cfb%3Alike%20href%3D%22%22%20send%3D%22true%22%20layout%3D%22box_count%22%20width%3D%2250%22%20show_faces%3D%22false%22%20font%3D%22%22%3E%3C%2Ffb%3Alike%3E')); }); </script>{/syntaxhighlighter}

But the approach failed miserably and the Like button refused to show up on the page. I haven't researched much into this, but I think the reason for this might be the custom <fb:> namespace being used for the Like button, and the script might be needed for for the same.

So I updated my code to put the Facebook's script statically on the page but append the <fb:like> button dynamically which worked. So this code makes the Facebook Like button to delay load after the page is ready:

{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; }<div id="custom-social-bookmarks-facebook" style="float: left; width: 60px"><div id="fb-root"></div><script src="http://connect.facebook.net/en_US/all.js#appId=224287964265938&amp;xfbml=1"></script></div> <script type="text/javascript"> jQuery(document).ready(function() { jQuery('#custom-social-bookmarks-facebook').append(decodeURIComponent('%3Cfb%3Alike%20href%3D%22%22%20send%3D%22true%22%20layout%3D%22box_count%22%20width%3D%2250%22%20show_faces%3D%22false%22%20font%3D%22%22%3E%3C%2Ffb%3Alike%3E')); }); </script>{/syntaxhighlighter}

Google's PlusOne was the final frontier to conquer and it proved relatively simple by changing this code which loads it statically:

 

<div style="float: left; width: 60px;">
<script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>
<g:plusone size="tall"></g:plusone>
</div>

 

to the following which loads Google Plus dynamically:

{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; }<div id="custom-social-bookmarks-plusone" style="float: left; width: 60px;"></div> <script type="text/javascript"> jQuery(document).ready(function() { jQuery('#custom-social-bookmarks-plusone').append(decodeURIComponent('%3Cscript%20type%3D%22text%2Fjavascript%22%20src%3D%22https%3A%2F%2Fapis.google.com%2Fjs%2Fplusone.js%22%3E%3C%2Fscript%3E%3Cg%3Aplusone%20size%3D%22tall%22%3E%3C%2Fg%3Aplusone%3E')); }); </script>{/syntaxhighlighter}


And you can see the results on this blog post itself as you are reading it. On the first column to the immediate right, if you scroll up a little, you will see the social plugins for Twitter, Facebook and Google+ above the "Monthly Archives" block, where each of them has been put on the page dynamically after the page was ready. And Google Translate is on the top-right of the page, again put on page dynamically.

To consolidate the entire code in one place, the following combination of html and script would load Twitter's Tweet, Facebook's Like and Google's PlusOne and Translate plugins on the page after the core resources of your page are finished loading (this is the exact code being used on this site, you might want to adjust the html to suit yours).

Here's the html:

 

<div style="height: 100px;">

<div id="custom-social-bookmarks-twitter" style="float: left; width: 60px"></div>

<div id="custom-social-bookmarks-facebook" style="float: left; width: 60px"><div id="fb-root"></div><script src="http://connect.facebook.net/en_US/all.js#appId=224287964265938&amp;xfbml=1"></script></div>

<div id="custom-social-bookmarks-plusone" style="float: left; width: 60px;"></div>

</div>

 

And this is the script:

{syntaxhighlighter brush: as3;fontsize: 100; first-line: 1; }<script type="text/javascript"> function googleTranslateElementInit() { new google.translate.TranslateElement({ pageLanguage: 'en', gaTrack: true, gaId: 'UA-XXXXXXXX-1', floatPosition: google.translate.TranslateElement.FloatPosition.TOP_RIGHT }); } jQuery(document).ready(function() { jQuery('#custom-social-bookmarks-twitter').append(decodeURIComponent('%3Ca%20href%3D%22http%3A%2F%2Ftwitter.com%2Fshare%22%20class%3D%22twitter-share-button%22%20data-count%3D%22vertical%22%20data-via%3D%22rahuls_log%22%3ETweet%3C%2Fa%3E%3Cscript%20type%3D%22text%2Fjavascript%22%20src%3D%22http%3A%2F%2Fplatform.twitter.com%2Fwidgets.js%22%3E%3C%2Fscript%3E')); jQuery('#custom-social-bookmarks-facebook').append(decodeURIComponent('%3Cfb%3Alike%20href%3D%22%22%20send%3D%22true%22%20layout%3D%22box_count%22%20width%3D%2250%22%20show_faces%3D%22false%22%20font%3D%22%22%3E%3C%2Ffb%3Alike%3E')); jQuery('#custom-social-bookmarks-plusone').append(decodeURIComponent('%3Cscript%20type%3D%22text%2Fjavascript%22%20src%3D%22https%3A%2F%2Fapis.google.com%2Fjs%2Fplusone.js%22%3E%3C%2Fscript%3E%3Cg%3Aplusone%20size%3D%22tall%22%3E%3C%2Fg%3Aplusone%3E')); jQuery('#custom-social-bookmarks').parent().css('padding', '0px'); jQuery(document.head).append(decodeURIComponent('%3Cscript%20src%3D%22http%3A%2F%2Ftranslate.google.com%2Ftranslate_a%2Felement.js%3Fcb%3DgoogleTranslateElementInit%22%3E%3C%2Fscript%3E')); }); }); </script>{/syntaxhighlighter}


The reason I put them separately is because you would need to put the html at appropriate place where you want these social plugins to appear, but you can move the script to the end of your page just before the closing </body> tag to ensure they get the last treatment they deserve.

If you are having trouble understanding what the above script does, just try to decode the strings inside decodeURIComponent method call, and they would make sense. e.g. try running the following in your browser's script console:

 

decodeURIComponent('%3Cscript%20type%3D%22text%2Fjavascript%22%20src%3D%22https%3A%2F%2Fapis.google.com%2Fjs%2Fplusone.js%22%3E%3C%2Fscript%3E%3Cg%3Aplusone%20size%3D%22tall%22%3E%3C%2Fg%3Aplusone%3E')

 

It would turn out to be the following which you can see is harmless code for loading G+:

 

<script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script><g:plusone size="tall"></g:plusone>

 


One thing I would like to research when I get time is why G+ can live with its script being loaded dynamically while FB Like can't when both of them use custom namespaces for their plugin tags.

 

Web 2.0: 

Comments

Hy,

I want make the same solution of FACEBOOK Like Button for FACEBOOK Comments: http://developers.facebook.com/docs/reference/plugins/comments/ . I've tried a lot of tests but I can't embed dynamically comments on one ajax page.

Please, help me!

Thanks

Otavio 

rahul's picture

Hi Otavio, I do not have time for testing, but I believe the process for loading comments dynamically should be similar.

Here's what I would have tried:

{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; }<script> function addFBJsFile(d){ var js, id = 'facebook-jssdk'; if (d.getElementById(id)) {return;} js = d.createElement('script'); js.id = id; js.async = true; js.src = "//connect.facebook.net/en_US/all.js#xfbml=1"; d.getElementsByTagName('head')[0].appendChild(js); } </script> <script type="text/javascript"> jQuery(document).ready(function() { addFBJsFile(document); //The url below is http://www.rahulsingla.com, change as appropriate jQuery(document.body).append(decodeURIComponent("%3Cdiv%20class%3D%22fb-comments%22%20data-href%3D%22http%3A%2F%2Fwww.rahulsingla.com%22%20data-num-posts%3D%222%22%20data-width%3D%22500%...")); }); </script>{/syntaxhighlighter}

If the above did not work, then I would have added the FB js file to the page normally but appended the comment div dynamically. I am sure one of these 2 approaches would have worked.

Thanks, but don't work!

I tried this and work:

JS


// ======================== Facebook 

var xid = 1;

function addFBJsFile(d){
var js, id = 'facebook-jssdk'+xid; if (d.getElementById(id)) {return;}
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "https://connect.facebook.net/pt_BR/all.js#xfbml=1";
d.getElementsByTagName('head')[0].appendChild(js);
}

addFBJsFile(document);


HTML


<div id="fb-root"></div>
<div class="fb-comments" data-href="example.com" data-num-posts="25" data-width="300"></div>


Everytime you make one AJAX that have one Facebook DIV execute this:

JS


xid++;

addFBJsFile(document);


 

rahul's picture

Hi Otavio, I don;t know why the code from the blog post did not work for you, but you can see it in action and working fine on this page itself, the social plugins in the second column are loaded dynamically (including FB plugin).

I don´t embed script code itself when loanding the page and the DOM is ready. I appended DIV conteiner with AJAX request many diferent times, deppending on user interact on the page, because my main page use AJAX method to navegation instead classic request methods.

Other kind of script execute if no problem. But I don´t know why Facebook Coments have this problem. The solution, if you see my code, is read diferent IDs and put in page head a facebook js script. This is, I my opinion, the herd way to solve this problem, because you need force loading script every time you need put the same kind of conteiner.

In this part of code you can see that I wrote above:

var js, id = 'facebook-jssdk'+xid; if (d.getElementById(id)) {return;}

See, every time I execute the function I need pass xid incremented to solve this problem.

I think it occurs only in Facebook Coments, in Like button can make correct.

Thanks for your attetion.

Otavio

rahul's picture

Thanks Otavio for the explanation. I have not tried loading FB comments dynamically on the page, but if I do, I would try to find a way to not have to add the FB js file multiple times to the same page. But if nothing else work, then your approach can certainly be used, thanks for sharing it.

HI
My task is
For Example:NDTV.com website is there in that we have facebook,Twitter,Google+.
When i click the facebook button in NDTV it shows us  facebook.com/ndtv  profile and login buttons
and when i login into facebook it takes me to NDTV page.
In the same way i have to integrate in my website.
Please tell how to write code for this using javascript or jquery and please suggest me any links or if you have code please write for me please

Please check this link http://www.ndtv.com/news/

by clicking Facbook icon at the bottom of the site you will understand clearly in the same way i want to integrate in my website please help me

Thanks
karthik

HI

In your blog when i click the facebook icon it redirects me to facebook with your profile in the same way i want to integrate these three icons in my website.please help me how to write code for this for facebook,linkedin,twitter please.

Thanks
Karthik

rahul's picture

Hi Kartik, why don't you view the page source of this page and copy the desired sections of code :)

Hi

I copied this code from your blog is this correct?

   <div class="blockcontent"><div id="custom-social-bookmarks">

    <div style="text-align: center">
        <a href="http://twitter.com/rahuls_log" target="_blank"><img src="/rs/images/twitter.png" /></a>
        <a href="http://www.facebook.com/singla.rahul" target="_blank"><img src="/rs/images/facebook.png" /></a>
        <a href="http://in.linkedin.com/in/rahulsingla" target="_blank"><img src="/rs/images/linkedin.png" /></a>
        <a href="http://www.rahulsingla.com/blogs/rahul/feed" target="_blank"><img src="/rs/images/rss.png" /></a>
    </div>
<div style="height: 100px;">         <div id="custom-social-bookmarks-twitter" style="float: left; width: 60px"></div>         <div id="custom-social-bookmarks-facebook" style="float: left; width: 60px">             <div id="fb-root"></div>             <script src="http://connect.facebook.net/en_US/all.js#appId=224287964265938&amp;xfbml=1"></script>         </div>         <div id="custom-social-bookmarks-plusone" style="float: left; width: 60px;"></div>     </div>
I didn't understand this statement can you ellaborate this statement
<script src="http://connect.facebook.net/en_US/all.js#appId=224287964265938&amp;xfbml=1"></script>  and why you are not used like this script for Linkedin and Twitter..
what happens when i comment this statement can you please explain for me

I copied this code from your blog is this correct?

<div class="blockcontent"><div id="custom-social-bookmarks"> <div style="text-align: center"> <a href="http://twitter.com/rahuls_log" target="_blank"><img src="/rs/images/twitter.png" /></a> <a href="http://www.facebook.com/singla.rahul" target="_blank"><img src="/rs/images/facebook.png" /></a> <a href="http://in.linkedin.com/in/rahulsingla" target="_blank"><img src="/rs/images/linkedin.png" /></a> <a href="http://www.rahulsingla.com/blogs/rahul/feed" target="_blank"><img src="/rs/images/rss.png" /></a> </div> <div style="height: 100px;">

<div id="custom-social-bookmarks-twitter" style="float: left; width: 60px"></div>         <div id="custom-social-bookmarks-facebook" style="float: left; width: 60px">             <div id="fb-root"></div>             <script src="http://connect.facebook.net/en_US/all.js#appId=224287964265938&amp;xfbml=1"></script>         </div>         <div id="custom-social-bookmarks-plusone" style="float: left; width: 60px;"></div>     </div>
<script src="http://connect.facebook.net/en_US/all.js#appId=224287964265938&amp;xfbml=1">
</script>  

I didn't understand the above script statement can you please ellaborate this statement
and why you are not used like this script for Linkedin and twitter
Thanks
karthik
rahul's picture

Hi kartik, yes that script seems to be correct. You will need to replace <img /> sources and links to your profiles.

As for the fb script, please consult Facebook's developer documentation, it would provide better answers. There is no point in comparing API for one site with another site, each has its own architecture and way of doing things.