W3 EDGE

Menu
  • Home
  • Blog
  • 2011
  • February
  • Optimize the Performance of Widgets, Buttons & More

Blog

Optimize the Performance of Widgets, Buttons & More

Posted by Frederick Townes, , 79 Comments

A recent post by web site performance thought leader (and user experience expert as a result) Steve Souders reminds me of a vital nuance that’s not even clearly expressed in the popular Yahoo! performance rules; namely render the page first, THEN add JavaScript. One of the largest challenges with this objective is addressing the performance of 3rd party resources. With social media demanding more widgets, plugins, badges and buttons etc available every day and a lack of awareness on the part of developers about how to make sure that their buttons are as effective and valuable as possible, sometimes performance concerns are overlooked.

Ask yourself, what is the value of lost visitors due to a slow loading web site? There are literally page views “locked” away in those slow loading pages of your web site that can be “unlocked” with a few quick changes. Simply put, having numerous 3rd party elements in your site can ultimately be its downfall.

For example, simply adding the Facebook fan box will dramatically slow a page in many cases, slow down the browsers due to large memory usage and usually lots of additional download time making the page “not ready” until everything is downloaded. So if your goal is to optimize your site for social media and make sure that your bounce rates are low, time on site is high, page views per visit grows and Google has 1 less reason to rank your site poorly, keep reading.

So, let’s take a look at the implementations you need for your site that make sure your visitors see your content before your widgets. From an idealistic point of view the “start render time,” or when the browser actually starts to paint the page, these tips will not bring this value as close to zero as I would like, however they will definitely improve user experience. Keep in mind that there are numerous other steps to be taken or possibilities, but we’re focusing on reducing the negative impact of widgets characterized above. What follows is HTML5 code for various cases:

Digg:
After working with Digg on some their latest improvements, I’m happy to share an implementation that is much more user-centric; if you have multiple buttons per page, this is especially valuable:

[html] <a class="DiggThisButton DiggThisButtonMedium" class="digg.com/submit?url=domain.com/&amp;title=Post%20Title" rel="nofollow external"><img src="/img/spacer.gif">

Then, before </body> embed the following only once and multiple buttons will still work in a single page:

[html] <script src="/img/spacer.gif">

This implementation allows the page to render and then draws the buttons later.

StumbleUpon:
SU, has recently updated their buttons, which is good, but what follows is not truly asynchronous and definitely not as optimal as the Digg button above because of the multiple JS embeddings per page, at least this implementation won’t block the page render. First position the button with a unique ID wherever you wish:

[html] <div id="id"></div> [/html]

Then for each button make sure that an embedding exists above </body> so the button will be rendered in the location:

[html] <script src="/img/spacer.gif">

LinkedIn:
The LinkedIn button implementation is also not perfect, but a carries a smaller total payload than the StumbleUpon buttons when there are multiple buttons per page:

[html] <script type="in/share" data-counter="top"></script> [/html]

Then at the bottom of the page a single JS embedding with power all of the buttons:

[html] <script src="/img/spacer.gif">

Tweetmeme:
I still recommend this service because it also generates a usable button for feeds you may syndicate, while the official twitter button still does not. The best way to use this widget is via <br> as brs do not block the render of a page, too many though can still slow down a page render or cause other anomalies in some browsers. Anyway, here’s what that implementation looks like:

[html] <br scrolling="no" "61" "50" frameborder="0" src="/img/spacer.gif">

Twitter:
The official twitter button works pretty well, it doesn’t have retweet data for everything ever shared on your site as they only started gathering that data when they launched the button (so use tweetmeme for those older stories if you can), but it does have a reliable sharing experience for users, just make sure that if you use the following implementation:

[html] <br class="twitter-share-button" allowtransparency="true" frameborder="0" scrolling="no" src="/img/spacer.gif">

You can of course use a technique similar to LinkedIn or Digg, but the JS will actually create an <br> anyway, so this approach is more performance as it won’t block the page render and yields the same net result. For those using @anywhere to add hovercards and other twitter functionality to their sites, the technique that apples for Diff of LinkedIn can be applied.

ShareThis:
Among the most popular buttons available, their implementation has dramatically improved as the total payload for JavaScript has been reduced, although the script loads synchronously still unfortunately. On the positive side, the buttons are decoupled from the scripts that embed them. The instructions recommend adding the scripts to the <head>, but I recommend adding them before </body> or after <body> if you’re having any problems.

[html] <span class="st_sharethis"></span> <script> var __st_loadLate=true; // if __st_loadLate is defined then the widget will not load on domcontent ready stLight.options({ publisher:’12345′, tracking:’google’, embeds:’true’ }); </script> [/html]

And of course, activate the button after the content is displayed by placing the script that powers the widgets on the page as shown:

[html] <script src="/img/spacer.gif">

Google Buzz:
Implementing the Buzz button like many others that are reasonably well done allow for a single JS embed to support multiple button instances in a single page:

[html] <a class="www.google.com/buzz/post" class="google-buzz-button" title="Google Buzz" data-message="Here’s Buzz!" data-url="www.google.com/buzz" data-locale="en" data-button-style="normal-count"></a> [/html]

Although not asynchronous the JS embed can still be placed above the </body> tag as shown:

[html] <script src="/img/spacer.gif">

Google Friend Connect (AdSense & Gadgets):
It’s critical to remember that you only need to embed the Friend Connect JS library once per page. If you’re minifying the file be sure to make sure your cache is frequently updated as the code is changed quite often and an old cache may cause anomalies on your site. The reason why this tip is notable is that this implementation supports AdSense as well as all of the other Gadgets with a single embed, so if you have multiple AdSense placements in a page, this is the way to go:

[html] <body> <script src="/img/spacer.gif">

Specify where the placement will appear using a div with a unique ID:

[html] <div id="id"></div> <script> google.friendconnect.container.setParentUrl(‘/’ /* location of rpc_relay.html and canvas.html */); google.friendconnect.container.renderAdsGadget({ id: ‘id’, , site: ‘XXXXXXXXXXXXXXX’,’prefs':{"google_ad_client":"ca-pub-XXXXXXXXXXXXXXX", "google_ad_host":"pub-XXXXXXXXXXXXXXX","google_ad_slot":"XXXXXXXXXX","google_ad_format":"728×90"} }); </script> [/html]

Then you can obviously embed numerous other placements or gadgets all powered by a single JS embedding. Unfortunately the JS embedding is not asynchronous, but at least it’s better than having lots of AdSense JS calls throughout a page or even additional calls for your gadgets.

Facebook Share / Facebook Like / Other Facebook plugins:
Use the XFBML implementation described on the various plugin pages; this implementation does interfere with page render and positioning it after the <body> tag means that each of the plugins used in a given page will load at the same time as soon as the scripts have loaded. No need for multiple scripts, which have to be downloaded repeatedly and slow down the page render etc etc.

Add support of the XFBML markup to the document:

[html] <!DOCTYPE html> <html xmlns="www.w3.org/1999/xhtml" dir="ltr" lang="en-US" xmlns:x2="www.w3.org/2002/06/xhtml2" xmlns:fb="www.facebook.com/2008/fbml"> <head> [/html]

The embed itself:

[html] <body> <div id="fb-embed"></div> <script> window.fbAsyncInit = function() { FB.init({appId: ‘XXXXXXXXXXXXXXX’, status: true, cookie: true, xfbml: true}); }; (function() { var e = document.createElement(‘script’); e.async = true; e.src = document.location.protocol + ‘//connect.facebook.net/en_US/all.js'; document.getElementById(‘fb-embed’).appendChild(e); }()); </script> [/html]

Then place the Like Box itself where you desired:

[html] <fb:like profile_id="XXXXXXXXXXXX" class="domain.com/" "450"></fb:like> [/html]

Meebo Bar:
Meebo has actually taken a number of strides (with the consult of Steve Souders as well) to improve the performance of their meebo bar; still it’s something more for users to download and more JavaScript to be run in your visitor’s browser, but I can now actually recommend this for publishers looking to increase engagement and create new monetization opportunities for their site. Their implementation is fully asynchronous and has a number of optimizations compared to earlier version. The latest implementation documentation at their site is the best reference.

OpenX:
The OpenX team has promised some an asynchronous embedding code for their single page call (SPC) implementation, which basically means that multiple ads in a given page can be requested without blocking the page render and are requested at once instead of sequentially, however for the moment, this is the best implementation I can recommend. It also uses brs to alleviate render-blocking issues as well some:

I recommend adding this 1.3K of (closure compiler optimized) code directly in the <head> of the page to power the widgets. It’s small enough that it is faster than making another HTTP transaction (DNS lookup, connect, download, execute etc) for this purpose, the original file is here:

[html] <script>var adPositions=[];function writeAdDiv(a,b,c){document.write(‘<div class="banner" id="’+a+’" style="’+b+"px; "+c+"px; line-"+c+’px;">&nbsp;</div>’);adPositions[a]=a}function OpenX_findPosX(a){var b=0;if(a.offsetParent)for(;a.offsetParent;){b+=a.offsetLeft;a=a.offsetParent}else if(a.x)b+=a.x;return b}function OpenX_findPosY(a){var b=0;if(a.offsetParent)for(;a.offsetParent;){b+=a.offsetTop;a=a.offsetParent}else if(a.y)b+=a.y;return b} function OpenX_moveAbove(a,b){var c=0;if(a.offsetHeight)c=a.offsetHeight;else if(a.clip&&a.clip.height)c=a.clip.height;else if(a.style&&a.style.pixelHeight)c=a.style.pixelHeight;if(window.XMLHttpRequest)if(!document.all){b.style.paddingTop="0px";b.style.paddingBottom="0px"}if(c>0)b.style.c+"px";a.style.left=OpenX_findPosX(b)+"px";a.style.top=OpenX_findPosY(b)+"px"} function OpenX_positionDivs(){for(var a in adPositions){var b=a+"-Hidden";if(document.getElementById){targetZoneDivID=document.getElementById(a);sourceZoneDivID=document.getElementById(b)}else if(document.all){targetZoneDivID=document.all[a];sourceZoneDivID=document.all[b]}else if(document.layers){targetZoneDivID=document.layers[a];sourceZoneDivID=document.layers[b]}targetZoneDivID!=null&&sourceZoneDivID!=null&&OpenX_moveAbove(sourceZoneDivID,targetZoneDivID)}}window.onresize=function(){OpenX_positionDivs()};</script> [/html]

The SPC implementation is vital in making sure that the execution and transaction times are as small as possible. So create the slot(s) in the page as follows:

[html] <body> <script>var OA_zones = {"728x90_Leaderboard" : 1}</script> <script src="/img/spacer.gif">

Then place the slots in your HTML as appropriate:

[html] <script><!–//<![CDATA[ writeAdDiv('button1', 728, 90); //]]>–></script> [/html]

And finally, in the footer of the document, make the call to draw the ad in the appropriate slot:

[html] <div id="button1-Hidden" style="position:absolute;left:-1000px;top:-1000px;"> <script>OA_show("728x90_Leaderboard");</script> </div> </body> [/html]

Because of the various use cases and implementations supported I do recommend OpenX, but depending on the size and needs of your site/organization Google’s offerings are far more robust and will eventually perform better than they do now.

Google DoubleClick for Publishers (formerly Google Ad manager):
If your site is monetized with AdSense as well as various types of ad formats or networks, Google DFP is a great solution, however for now, it actually creates a negative experience for users depending on the quantity and type of ads being displayed. Instead of embedding the snippet in the <head> of the page, instead embed it after <body> and make sure note that this implementation uses the single request command to make the render more responsive:

[html] <body> <script src="/img/spacer.gif">

Then place your ad slots as you normally would in your page template. I’m definitely looking forward better performing implementation for Google DFP, ads are not optional for many publishers today and ironically they are actually causing publishers to lose money.

BuySellAds:
If you monetize your site using BSA, and still have not switched to their asynchronous embed code, make sure you do, your users will appreciate seeing the content they’re after without delay.

[html] <script> (function(){ var bsa = document.createElement(‘script’); bsa.type = ‘text/javascript'; bsa.async = true; bsa.src = ‘//s3.buysellads.com/ac/bsa.js'; (document.getElementsByTagName(‘head’)[0]||document.getElementsByTagName(‘body’)[0]).appendChild(bsa); })(); </script> [/html]

If you don’t already use the asynchronous snippet, make sure you do!

Google Analytics:
Google’s asynchronous tracking code has been out for some time, I recommend it for lots of reasons, like:

  • More accurate stats
  • Non-blocking user experience
  • Simplified implementation and optimized execution
  • Capture partial page views

So this is what the implementation looks like:

[html] <script> var _gaq = _gaq || []; _gaq.push( ['_setAccount', 'UA-XXXXX-X'], ['_setDomainName', 'domain.com'], ['_trackPageview'] ); (function() {var ga = document.createElement(‘script’); ga.type = ‘text/javascript'; ga.async = true;ga.src = (‘https:’ == document.location.protocol ? ‘https://ssl’ : ‘www’) + ‘.google-analytics.com/ga.js';document.getElementsByTagName(‘head’)[0] || document.getElementsByTagName(‘body’)[0]).appendChild(ga);})(); </script> </head> [/html]

Woopra:
Woopra Analytics not only has a decent WordPress plugin, they also now have an asynchronous tracking code implementation (which is not yet available in the WordPress plugin at the time of this writing). Being that it’s actually asynchronous, I recommend embedding it in the <head> of the page manually if you want to capture partial page views:

[html] <script> (function(){ var wsc=document.createElement(‘script’); wsc.type=’text/javascript'; wsc.src="/img/spacer.gif">

Wrapping Up:
For those buttons, widgets, services etc not covered one of the last remaining rules of thumb (within the scope of this discussion) is to put all scripts that are not essential for functionality of the site (like navigation, but hopefully that’s not the case) above </body> so that they’re not directly interfering with page render. Remember all of the CSS and JS files that exist in <head> must be downloaded and executed before the page can start to render. Note: your mileage may vary, but it’s possible to realize asynchronous performance of some scripts by adding the attribute async to the <script> tag with the value true. Keep in mind that this make break a script so test for yourself.

There are numerous other widgets, advertising networks, statistics and analytics services available, if you don’t see a tip above for the one you use, then reach out to them and find out if they have any performance tips (like asynchronous JavaScript code). Also, don’t forget that if you are able to minify scripts to reduce HTTP transactions, which will be a huge performance win for scripts that support it.

Bonus Tips for WordPress Users:
jQuery is used in countless plugins and themes. It’s often out-of-date and every new release includes bug fixes and more importantly performance improvements. The following snippet is useful for your header.php file, it will make sure that your site is always using the latest version of jQuery without having to modify your theme. You’ll also benefit from Google’s content delivery network and using a hostname other than your domain name, meaning that the file will be pipelined (downloaded in parallel) with the other files in the <head> of the page which is faster:

[php] <?php wp_deregister_script(‘jquery’); wp_register_script(‘jquery’, ‘ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js’); wp_enqueue_script(‘jquery’); ?> [/php]

Similarly, if you have extensive use of swfobject in your theme/plugins, a similar optimization can be applied thusly:

[php] <?php wp_deregister_script(‘swfobject’); wp_register_script(‘swfobject’, ‘ajax.googleapis.com/ajax/libs/swfobject/2/swfobject.js’); wp_enqueue_script(‘swfobject’); ?> [/php]

So again, until jQuery reaches version 2 or swfobject reaches version 3, you will never have to modify this code!

Have a tip I didn’t mention? Let me know in the comments!

Subscribe to W3 EDGE Updates

Tags: performance, plugins, start render, widgets

This entry was posted on and is filed under Usability, User Interface / Experience, Web Development, WordPress. You can follow any responses to this entry through the RSS 2.0 feed.

Related posts

  • Page Weight, Download Times and Your Conversion Rate

    , No Comments

  • Making the Most of Google's Search Engine

    , No Comments

  • Submitting Y
gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.