Protecting your User Experience While
Integrating 3rd-party Code

Patrick Meenan
Software Engineer
A simple content page
Feels Like




             http://youtu.be/HSbHNIvhOFU
The Social Widget
When the widget is Unavailable




                    http://youtu.be/3-zaos02CxI
Because of

This:
                                                                                            HTML
      <script
      src=‘https://apis.google.com/js/plusone.js’></script
      >
Instead of:
                                                                                            HTML
        <script>
         (function() {
            var po = document.createElement(‘script’);
            po.src = ‘https://apis.google.com/js/plusone.js’;
            var s = document.getElementsByTagName(‘script’)[0];
            s.parentNode.insertBefore(po, s);
          })();
        </script>



                 http://www.stevesouders.com/blog/2009/12/01/google-analytics-goes-async/
Loaded Asynchronously




                  http://youtu.be/krin-F65Fd8
Loaded Asynchronously




                  http://youtu.be/krin-F65Fd8
And Monitoring Says…

• Server Monitoring
   Base page responded in 0.160 seconds
• Full-Browser Monitoring
   Page loaded in 25 seconds
• Analytics Page Views
   Loaded and executed asynchronously
• Real User Monitoring Performance Reporting
   No data if user bailed before onLoad
There’s More!

On that one page, all before the main content:
                                                                               HTML
      <script src=‘http://code.jquery.com/jquery-1.7.1.min.js’></script>
      <script
      src=‘http://scripts.verticalacuity.com/vat/mon/vt.js’></script>
      <script src=‘http://ak.sail-horizon.com/scout/v1.js’></script>
      <script src=‘//cdn.optimizely.com/js/xxxxx.js’></script>
      <script src=‘https://platform.twitter.com/anywhere.js’></script>
      <script src=‘http://www.reddit.com/static/button/button1.js’></script>
      <script src=‘http://widgets.digg.com/buttons.js’></script>
      <script src=‘//assets.pinterest.com/js/pinit.js’></script>
      <script src=‘//platform.linkedin.com/in.js’></script>




                                                                                10
HTTP Archive




               http://httparchive.org/trends.php
But I’d Notice….

• Globally?
   – Social sites tend to be targets for blocking
      • platform.twitter.com
      • connect.facebook.net
      • apis.google.com
   – HTTPS as well

• In an Enterprise?
    – Corporate policies
Back-end vs Front-end


 Base Page
 (Back-end)



                                      Front-end




                        First Paint
High Availability Server Architectures
    DNS


                                         Read-Only Database

          Load Balancers   App Servers




          Site 1




                                                              Database Master



          Site 2
All for…


 Base Page
 (Back-end)
To the Front End!
Async Snippet
Good for code with no dependencies (widgets)

                                                   HTML
  <script>
   (function() {
      var po = document.createElement(‘script’);
      po.src =
  ‘https://apis.google.com/js/plusone.js’;
      var s =
  document.getElementsByTagName(‘script’)[0];
      s.parentNode.insertBefore(po, s);
    })();
  </script>

                                                    17
Put Scripts at the Bottom
• Easy to implement and describe
• Delays script loading and execution later than Async at the top

                                                                    HTML
      …
    <script
src=‘//assets.pinterest.com/js/pinit.js’></script>
</body>




                                                                     18
Protocol-relative URLs
• Look strange
• Safe across all browsers (for Javascript)

                                                          HTML
//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min
.js


Instead of:


https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jque
ry.min.js

                                                           19
Async Loaders
Help for dependency chaining

•   Modernizr
•   LABjs
•   RequireJS
•   ControlJS

    Modernizr.load([{                                                    HTML


       load: '//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js',
      }, {
       load: 'needs-jQuery.js'
    }]);

                                                                                20
HTML
Modernizr.load([ {
   load: '//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js',
   complete: function () {
        if ( !window.jQuery ) {
            Modernizr.load('js/libs/jquery-1.7.1.min.js');
        }
   }
 }, {
   load: 'needs-jQuery.js'
} ]);



                                                                       21
Well, Almost…


Desktop Browser          OnLoad Blocked                     Mobile Browser               OnLoad Blocked
Chrome                   Yes                                Android 2.x                  No
Firefox                  Yes                                Android 4.x                  Yes
Internet Explorer 9-     No                                 Chrome Mobile                Yes
Internet Explorer 10     Yes                                iOS 4                        No
Safari 5+                Yes                                iOS 5                        Yes
Opera                    Yes                                IE Mobile 9                  No


             http://www.browserscope.org/user/tests/table/agt1YS1wcm9maWxlcnINCxIEVGVzdBjrq90MDA


                                                                                                     22
How are we doing?
Widgets

Async                  Blocking
Google Analytics       Google +1 Badge
Google +1 Button       Twitter Anywhere
Twitter Tweet Button   Facebook Channel File Example
Facebook Like Button   Pinterest (end of body)
Digg                   Reditt
                       AddThis
                       ShareThis
Code Libraries (examples)

• Jquery: Blocking in the head
• Closure Library: Blocking in the head
• YUI: Blocking
• Dojo: Blocking in the head
• Moo Tools: Blocking in the head
• Google jsapi: Blocking (default, Async available)
Ad Providers

• Doubleclick: Fully Async available (October 2011)

• Adsense: Blocking script, ad itself is async

• Others: Ask – iFrame solutions are async
Demonstrating Frontend SPOF
Routing to localhost

• Fails FAST! (connections rejected)
• Not good for real failure scenarios
You Need a Black Hole
      blackhole.webpagetest.org – 72.66.115.13


hosts file
72.66.115.13 ajax.googleapis.com
72.66.115.13 apis.google.com
72.66.115.13 www.google-analytics.com
72.66.115.13 connect.facebook.net
72.66.115.13 platform.twitter.com
...


                                          Courtesy NASA/JPL-Caltech.
                                                                       29
On WebPagetest.org



setDnsName ajax.googleapis.com blackhole.webpagetest.org
setDnsName apis.google.com blackhole.webpagetest.org
setDnsName www.google-analytics.com blackhole.webpagetest.org
setDnsName connect.facebook.net blackhole.webpagetest.org
setDnsName platform.twitter.com blackhole.webpagetest.org
navigate your.url.com




                                                  http://www.webpagetest.org/   30
SPOF-O-Matic
In The Chrome Web Store




     https://chrome.google.com/webstore/detail/plikhggfbplemddobondkeogomgoodeg
                       https://github.com/pmeenan/spof-o-matic
Normal Operation


                   Gray circle = Boring/Good
SPOF Detected



                Warning indicator =
                SPOF Detected
SPOF Details
Amount of page content blocked




    Near the top = BAD




Near the bottom = Better
Whitelisting
Resetting Third Party/White Lists
Turning on Blocking
Blocking Enabled


                   Black Hole Enabled
Resources Blocked


                    Black Hole Used
Pages in the Wild
News*
CNN News Article Page
                                                                                     HTML
     <script src=‘http://cache-02.cleanprint.net/cpf/cleanprint?key=cnn’>
     <script src=‘http://connect.facebook.net/en_US/all.js’>

today.msnbc.msn.com
                                                                                     HTML
     <script src=‘http://www.polls.newsvine.com/_elliott/jenga’>
     <script src=‘http://amch.questionmarket.com/…/randm.js’>
     <script src=‘http://use.typekit.com/kjy8rxx.js’>



ABC News Main Page
                                                                                     HTML
     <script src=‘http://connect.facebook.net/en_US/all.js’>




                                                                   *As of May 2012     43
Blogs/Content*
The Verge Article Page
                                                                                    HTML
     <script
     src=‘http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js’>
     <script src=‘http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.15/jquery-
     ui.min.js’>
CBS Sports Article Page
     <script src=‘http://tags.crwdcntrl.net/c/1198/cc_af.js’>
                                                                                    HTML
     <script src=‘//platform.twitter.com/widgets.js’>

Tumblr
                                                                                    HTML
      <script
      src=‘https://www.google.com/recaptcha/api/js/recaptcha_ajax.js’>
Cnet.com
                                                                                    HTML
     <script src=‘http://html5shim.googlecode.com/svn/trunk/html5.js’>



                                                                  *As of May 2012     44
Political sites*
whitehouse.gov
                                                                                   HTML
     <script
     src=‘https://www.google.com/recaptcha/api/js/recaptcha_ajax.js’>
     <script src=‘https://s7.addthis.com/js/250/addthis_widget.js’>
democrats.org
                                                                                   HTML
     <script src=‘https://use.typekit.com/wym0ldn.js’>


gop.com
                                                                                   HTML
     <script src=‘http://tags.crwdcntrl.net/c/546/cc.js’>




                                                                 *As of May 2012     45
E-Commerce*
Newegg Product Page
                                                                                    HTML
     <script src=‘http://assets.pinterest.com/js/pinit.js’>

Best Buy Product Page
                                                                                    HTML
      <script
      src=‘http://bestbuy.ugc.bazaarvoice.com/static/3545w/bvapi.js’>
      <script src=‘http://platform.twitter.com/widgets.js’>
Target
                                                                                    HTML
     <script src=‘http://media.richrelevance.com/rrserver/js/1.0/p13n.js’>

Redbox
                                                                                    HTML
     <script src=‘http://connect.facebook.net/en_US/all.js#xfbml=1’>



                                                                  *As of May 2012     46
Homework
Widget Owners

• Never EVER provide blocking snippets

• All examples should be asynchronous

• Do not force HTTPS if it isn't required

• Where possible, allow for sites to self-host any critical code
Site Owners

• Never load 3rd party resources synchronously
   – refuse 3rd party code that doesn't have an async option

• Do not rely on onload for important functionality

• Make sure your monitoring has aggressive time limits (under 20 seconds)

• Make sure your real user monitoring has an aggressive timeout

• Track real user failures by region
Live Browsing with SPOF-O-Matic
Thank You!

pmeenan@webpagetest.org
@patmeenan
+Patrick Meenan

Google I/O 2012 - Protecting your user experience while integrating 3rd party code

  • 1.
    Protecting your UserExperience While Integrating 3rd-party Code Patrick Meenan Software Engineer
  • 2.
  • 3.
    Feels Like http://youtu.be/HSbHNIvhOFU
  • 4.
  • 5.
    When the widgetis Unavailable http://youtu.be/3-zaos02CxI
  • 6.
    Because of This: HTML <script src=‘https://apis.google.com/js/plusone.js’></script > Instead of: HTML <script> (function() { var po = document.createElement(‘script’); po.src = ‘https://apis.google.com/js/plusone.js’; var s = document.getElementsByTagName(‘script’)[0]; s.parentNode.insertBefore(po, s); })(); </script> http://www.stevesouders.com/blog/2009/12/01/google-analytics-goes-async/
  • 7.
    Loaded Asynchronously http://youtu.be/krin-F65Fd8
  • 8.
    Loaded Asynchronously http://youtu.be/krin-F65Fd8
  • 9.
    And Monitoring Says… •Server Monitoring Base page responded in 0.160 seconds • Full-Browser Monitoring Page loaded in 25 seconds • Analytics Page Views Loaded and executed asynchronously • Real User Monitoring Performance Reporting No data if user bailed before onLoad
  • 10.
    There’s More! On thatone page, all before the main content: HTML <script src=‘http://code.jquery.com/jquery-1.7.1.min.js’></script> <script src=‘http://scripts.verticalacuity.com/vat/mon/vt.js’></script> <script src=‘http://ak.sail-horizon.com/scout/v1.js’></script> <script src=‘//cdn.optimizely.com/js/xxxxx.js’></script> <script src=‘https://platform.twitter.com/anywhere.js’></script> <script src=‘http://www.reddit.com/static/button/button1.js’></script> <script src=‘http://widgets.digg.com/buttons.js’></script> <script src=‘//assets.pinterest.com/js/pinit.js’></script> <script src=‘//platform.linkedin.com/in.js’></script> 10
  • 11.
    HTTP Archive http://httparchive.org/trends.php
  • 12.
    But I’d Notice…. •Globally? – Social sites tend to be targets for blocking • platform.twitter.com • connect.facebook.net • apis.google.com – HTTPS as well • In an Enterprise? – Corporate policies
  • 13.
    Back-end vs Front-end Base Page (Back-end) Front-end First Paint
  • 14.
    High Availability ServerArchitectures DNS Read-Only Database Load Balancers App Servers Site 1 Database Master Site 2
  • 15.
    All for… BasePage (Back-end)
  • 16.
  • 17.
    Async Snippet Good forcode with no dependencies (widgets) HTML <script> (function() { var po = document.createElement(‘script’); po.src = ‘https://apis.google.com/js/plusone.js’; var s = document.getElementsByTagName(‘script’)[0]; s.parentNode.insertBefore(po, s); })(); </script> 17
  • 18.
    Put Scripts atthe Bottom • Easy to implement and describe • Delays script loading and execution later than Async at the top HTML … <script src=‘//assets.pinterest.com/js/pinit.js’></script> </body> 18
  • 19.
    Protocol-relative URLs • Lookstrange • Safe across all browsers (for Javascript) HTML //ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min .js Instead of: https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jque ry.min.js 19
  • 20.
    Async Loaders Help fordependency chaining • Modernizr • LABjs • RequireJS • ControlJS Modernizr.load([{ HTML load: '//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js', }, { load: 'needs-jQuery.js' }]); 20
  • 21.
    HTML Modernizr.load([ { load: '//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js', complete: function () { if ( !window.jQuery ) { Modernizr.load('js/libs/jquery-1.7.1.min.js'); } } }, { load: 'needs-jQuery.js' } ]); 21
  • 22.
    Well, Almost… Desktop Browser OnLoad Blocked Mobile Browser OnLoad Blocked Chrome Yes Android 2.x No Firefox Yes Android 4.x Yes Internet Explorer 9- No Chrome Mobile Yes Internet Explorer 10 Yes iOS 4 No Safari 5+ Yes iOS 5 Yes Opera Yes IE Mobile 9 No http://www.browserscope.org/user/tests/table/agt1YS1wcm9maWxlcnINCxIEVGVzdBjrq90MDA 22
  • 23.
    How are wedoing?
  • 24.
    Widgets Async Blocking Google Analytics Google +1 Badge Google +1 Button Twitter Anywhere Twitter Tweet Button Facebook Channel File Example Facebook Like Button Pinterest (end of body) Digg Reditt AddThis ShareThis
  • 25.
    Code Libraries (examples) •Jquery: Blocking in the head • Closure Library: Blocking in the head • YUI: Blocking • Dojo: Blocking in the head • Moo Tools: Blocking in the head • Google jsapi: Blocking (default, Async available)
  • 26.
    Ad Providers • Doubleclick:Fully Async available (October 2011) • Adsense: Blocking script, ad itself is async • Others: Ask – iFrame solutions are async
  • 27.
  • 28.
    Routing to localhost •Fails FAST! (connections rejected) • Not good for real failure scenarios
  • 29.
    You Need aBlack Hole blackhole.webpagetest.org – 72.66.115.13 hosts file 72.66.115.13 ajax.googleapis.com 72.66.115.13 apis.google.com 72.66.115.13 www.google-analytics.com 72.66.115.13 connect.facebook.net 72.66.115.13 platform.twitter.com ... Courtesy NASA/JPL-Caltech. 29
  • 30.
    On WebPagetest.org setDnsName ajax.googleapis.comblackhole.webpagetest.org setDnsName apis.google.com blackhole.webpagetest.org setDnsName www.google-analytics.com blackhole.webpagetest.org setDnsName connect.facebook.net blackhole.webpagetest.org setDnsName platform.twitter.com blackhole.webpagetest.org navigate your.url.com http://www.webpagetest.org/ 30
  • 31.
  • 32.
    In The ChromeWeb Store https://chrome.google.com/webstore/detail/plikhggfbplemddobondkeogomgoodeg https://github.com/pmeenan/spof-o-matic
  • 33.
    Normal Operation Gray circle = Boring/Good
  • 34.
    SPOF Detected Warning indicator = SPOF Detected
  • 35.
  • 36.
    Amount of pagecontent blocked Near the top = BAD Near the bottom = Better
  • 37.
  • 38.
  • 39.
  • 40.
    Blocking Enabled Black Hole Enabled
  • 41.
    Resources Blocked Black Hole Used
  • 42.
  • 43.
    News* CNN News ArticlePage HTML <script src=‘http://cache-02.cleanprint.net/cpf/cleanprint?key=cnn’> <script src=‘http://connect.facebook.net/en_US/all.js’> today.msnbc.msn.com HTML <script src=‘http://www.polls.newsvine.com/_elliott/jenga’> <script src=‘http://amch.questionmarket.com/…/randm.js’> <script src=‘http://use.typekit.com/kjy8rxx.js’> ABC News Main Page HTML <script src=‘http://connect.facebook.net/en_US/all.js’> *As of May 2012 43
  • 44.
    Blogs/Content* The Verge ArticlePage HTML <script src=‘http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js’> <script src=‘http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.15/jquery- ui.min.js’> CBS Sports Article Page <script src=‘http://tags.crwdcntrl.net/c/1198/cc_af.js’> HTML <script src=‘//platform.twitter.com/widgets.js’> Tumblr HTML <script src=‘https://www.google.com/recaptcha/api/js/recaptcha_ajax.js’> Cnet.com HTML <script src=‘http://html5shim.googlecode.com/svn/trunk/html5.js’> *As of May 2012 44
  • 45.
    Political sites* whitehouse.gov HTML <script src=‘https://www.google.com/recaptcha/api/js/recaptcha_ajax.js’> <script src=‘https://s7.addthis.com/js/250/addthis_widget.js’> democrats.org HTML <script src=‘https://use.typekit.com/wym0ldn.js’> gop.com HTML <script src=‘http://tags.crwdcntrl.net/c/546/cc.js’> *As of May 2012 45
  • 46.
    E-Commerce* Newegg Product Page HTML <script src=‘http://assets.pinterest.com/js/pinit.js’> Best Buy Product Page HTML <script src=‘http://bestbuy.ugc.bazaarvoice.com/static/3545w/bvapi.js’> <script src=‘http://platform.twitter.com/widgets.js’> Target HTML <script src=‘http://media.richrelevance.com/rrserver/js/1.0/p13n.js’> Redbox HTML <script src=‘http://connect.facebook.net/en_US/all.js#xfbml=1’> *As of May 2012 46
  • 47.
  • 48.
    Widget Owners • NeverEVER provide blocking snippets • All examples should be asynchronous • Do not force HTTPS if it isn't required • Where possible, allow for sites to self-host any critical code
  • 49.
    Site Owners • Neverload 3rd party resources synchronously – refuse 3rd party code that doesn't have an async option • Do not rely on onload for important functionality • Make sure your monitoring has aggressive time limits (under 20 seconds) • Make sure your real user monitoring has an aggressive timeout • Track real user failures by region
  • 50.
    Live Browsing withSPOF-O-Matic
  • 51.