SlideShare a Scribd company logo

How Edmunds Got in the Fast Lane: 80% Reduction in Page Load Time in 3 Simple Steps

Edmunds.com, Inc.
Edmunds.com, Inc.
Edmunds.com, Inc.Edmunds.com, Inc.

(YouTube presentation is at the end of the slides) Back in the day, the onLoad event on our edmunds.com and insidelien.com pages used to take 9 seconds to fire! Yeah, we thought it was awful too. That's why in late 2008, we set out to do something about. In this deck, I will discuss the three main concepts that helped us take our pages from slow to really fast.

How Edmunds Got in the Fast Lane: 80% Reduction in Page Load Time in 3 Simple Steps

1 of 78
Download to read offline
HOW EDMUNDS GOT IN THE FAST LANE
    80% Reduction in Page Load Time in   Simple Steps




                                              by Ismail Elshareef

Sunday, January 16, 2011
The Results




  onLoad: 8.4s ➙ 1.9s      (≈ 80% reduction)


  Page Views: 20%
  Bounce Rate: 4%
  Ad Impression Variance: 3%

Sunday, January 16, 2011
Edmunds, Inc.

               Online since 1995
                Properties:
                200M+ page views/month
                Revenue = Ads + Leads




Sunday, January 16, 2011
Memory Lane




Sunday, January 16, 2011
Edmunds.com Legacy Site




Sunday, January 16, 2011
Meanwhile ...


                                                   “95% of Performance
                                                  is Frontend” - Steve Souders




                                        “Performance Matters!” - Organizations
                             +100ms in response time ➡ -1% in sales

                           -30% in file size ➡ +30% in requests

Sunday, January 16, 2011

Recommended

Best Practices for Architecting High Volume, High Performance Publishing for ...
Best Practices for Architecting High Volume, High Performance Publishing for ...Best Practices for Architecting High Volume, High Performance Publishing for ...
Best Practices for Architecting High Volume, High Performance Publishing for ...Edmunds.com, Inc.
 
Scott Edmunds & Rob Davidson's talk at the Metabolomics Society 2014 Meeting ...
Scott Edmunds & Rob Davidson's talk at the Metabolomics Society 2014 Meeting ...Scott Edmunds & Rob Davidson's talk at the Metabolomics Society 2014 Meeting ...
Scott Edmunds & Rob Davidson's talk at the Metabolomics Society 2014 Meeting ...GigaScience, BGI Hong Kong
 
Comparison of Autotrader, Carfax, Cargurus, Edmunds.com and Other Top Car Buy...
Comparison of Autotrader, Carfax, Cargurus, Edmunds.com and Other Top Car Buy...Comparison of Autotrader, Carfax, Cargurus, Edmunds.com and Other Top Car Buy...
Comparison of Autotrader, Carfax, Cargurus, Edmunds.com and Other Top Car Buy...Unmetric
 
Peak Performance for Sales Excellence
Peak Performance for Sales ExcellencePeak Performance for Sales Excellence
Peak Performance for Sales ExcellenceMatt Hallett, M.A.
 
Walmart pagespeed-slide
Walmart pagespeed-slideWalmart pagespeed-slide
Walmart pagespeed-slideBitsytask
 
The Art Of War In Sales - Derek Grant
The Art Of War In Sales - Derek GrantThe Art Of War In Sales - Derek Grant
The Art Of War In Sales - Derek GrantSalesLoft
 

More Related Content

Similar to How Edmunds Got in the Fast Lane: 80% Reduction in Page Load Time in 3 Simple Steps

McAnerin technical seo
McAnerin   technical seoMcAnerin   technical seo
McAnerin technical seoIan McAnerin
 
Errors and handling them. YOW nights Sydney 2011
Errors and handling them. YOW nights Sydney 2011Errors and handling them. YOW nights Sydney 2011
Errors and handling them. YOW nights Sydney 2011Michael Neale
 
Error Handling Done Differently
Error Handling Done DifferentlyError Handling Done Differently
Error Handling Done DifferentlyCloudBees
 
HTML XHTML HTML5
HTML XHTML HTML5HTML XHTML HTML5
HTML XHTML HTML5timstone
 
How to use Mobile Applications to extend your brand
How to use Mobile Applications to extend your brandHow to use Mobile Applications to extend your brand
How to use Mobile Applications to extend your brandAxway Appcelerator
 
Debugging tips in YUI 3
Debugging tips in YUI 3Debugging tips in YUI 3
Debugging tips in YUI 3Luke Smith
 

Similar to How Edmunds Got in the Fast Lane: 80% Reduction in Page Load Time in 3 Simple Steps (7)

McAnerin technical seo
McAnerin   technical seoMcAnerin   technical seo
McAnerin technical seo
 
Errors and handling them. YOW nights Sydney 2011
Errors and handling them. YOW nights Sydney 2011Errors and handling them. YOW nights Sydney 2011
Errors and handling them. YOW nights Sydney 2011
 
Error Handling Done Differently
Error Handling Done DifferentlyError Handling Done Differently
Error Handling Done Differently
 
HTML XHTML HTML5
HTML XHTML HTML5HTML XHTML HTML5
HTML XHTML HTML5
 
Tim stone.html5.rjug.20110316
Tim stone.html5.rjug.20110316Tim stone.html5.rjug.20110316
Tim stone.html5.rjug.20110316
 
How to use Mobile Applications to extend your brand
How to use Mobile Applications to extend your brandHow to use Mobile Applications to extend your brand
How to use Mobile Applications to extend your brand
 
Debugging tips in YUI 3
Debugging tips in YUI 3Debugging tips in YUI 3
Debugging tips in YUI 3
 

Recently uploaded

Curtain Module Manual Zigbee Neo CS01-1C.pdf
Curtain Module Manual Zigbee Neo CS01-1C.pdfCurtain Module Manual Zigbee Neo CS01-1C.pdf
Curtain Module Manual Zigbee Neo CS01-1C.pdfDomotica daVinci
 
DNA LIGASE BIOTECHNOLOGY BIOLOGY STUDY OF LIFE
DNA LIGASE BIOTECHNOLOGY BIOLOGY STUDY OF LIFEDNA LIGASE BIOTECHNOLOGY BIOLOGY STUDY OF LIFE
DNA LIGASE BIOTECHNOLOGY BIOLOGY STUDY OF LIFEandreiandasan
 
Navigating the Never Normal Strategies for Portfolio Leaders
Navigating the Never Normal Strategies for Portfolio LeadersNavigating the Never Normal Strategies for Portfolio Leaders
Navigating the Never Normal Strategies for Portfolio LeadersOnePlan Solutions
 
Enhancing SaaS Performance: A Hands-on Workshop for Partners
Enhancing SaaS Performance: A Hands-on Workshop for PartnersEnhancing SaaS Performance: A Hands-on Workshop for Partners
Enhancing SaaS Performance: A Hands-on Workshop for PartnersThousandEyes
 
Unlocking the Cloud's True Potential: Why Multitenancy Is The Key?
Unlocking the Cloud's True Potential: Why Multitenancy Is The Key?Unlocking the Cloud's True Potential: Why Multitenancy Is The Key?
Unlocking the Cloud's True Potential: Why Multitenancy Is The Key?GleecusTechlabs1
 
2) Presentation_Overview_ISO_16140-3_Method_verification_20210322.pptx
2) Presentation_Overview_ISO_16140-3_Method_verification_20210322.pptx2) Presentation_Overview_ISO_16140-3_Method_verification_20210322.pptx
2) Presentation_Overview_ISO_16140-3_Method_verification_20210322.pptxssuser796efb
 
From eSIMs to iSIMs: It’s Inside the Manufacturing
From eSIMs to iSIMs: It’s Inside the ManufacturingFrom eSIMs to iSIMs: It’s Inside the Manufacturing
From eSIMs to iSIMs: It’s Inside the ManufacturingSoracom Global, Inc.
 
GDSC MMCOE - ML Campaign
GDSC MMCOE - ML CampaignGDSC MMCOE - ML Campaign
GDSC MMCOE - ML CampaignLavesh Akhadkar
 
AWS reInvent 2023 recaps from Chicago AWS user group
AWS reInvent 2023 recaps from Chicago AWS user groupAWS reInvent 2023 recaps from Chicago AWS user group
AWS reInvent 2023 recaps from Chicago AWS user groupAWS Chicago
 
OTel Orientation_ How to Train Teams (OTel in Practice).pdf
OTel Orientation_ How to Train Teams (OTel in Practice).pdfOTel Orientation_ How to Train Teams (OTel in Practice).pdf
OTel Orientation_ How to Train Teams (OTel in Practice).pdfPaige Cruz
 
Manual Eurotronic Thermostatic Valve Comry Z-Wave
Manual Eurotronic Thermostatic Valve Comry Z-WaveManual Eurotronic Thermostatic Valve Comry Z-Wave
Manual Eurotronic Thermostatic Valve Comry Z-WaveDomotica daVinci
 
Microsoft Azure - GAA and Irish Tech Society Hackathon
Microsoft Azure - GAA and Irish Tech Society HackathonMicrosoft Azure - GAA and Irish Tech Society Hackathon
Microsoft Azure - GAA and Irish Tech Society HackathonJuarez Junior
 
A Comprehensive Theoretical Overview of Self-Driving Car Technology
A Comprehensive Theoretical Overview of Self-Driving Car TechnologyA Comprehensive Theoretical Overview of Self-Driving Car Technology
A Comprehensive Theoretical Overview of Self-Driving Car TechnologyKumar Bipin
 
Bringing nullability into existing code - dammit is not the answer.pptx
Bringing nullability into existing code - dammit is not the answer.pptxBringing nullability into existing code - dammit is not the answer.pptx
Bringing nullability into existing code - dammit is not the answer.pptxMaarten Balliauw
 
zigbee motion sensor user manual NAS-PD07B2.pdf
zigbee motion sensor user manual NAS-PD07B2.pdfzigbee motion sensor user manual NAS-PD07B2.pdf
zigbee motion sensor user manual NAS-PD07B2.pdfDomotica daVinci
 
Introduction to Serverless with AWS Lambda in C#.pptx
Introduction to Serverless with AWS Lambda in C#.pptxIntroduction to Serverless with AWS Lambda in C#.pptx
Introduction to Serverless with AWS Lambda in C#.pptxBrandon Minnick, MBA
 
My sample product research idea for you!
My sample product research idea for you!My sample product research idea for you!
My sample product research idea for you!KivenRaySarsaba
 
M.Aathiraju Self Intro.docx-AD21001_____
M.Aathiraju Self Intro.docx-AD21001_____M.Aathiraju Self Intro.docx-AD21001_____
M.Aathiraju Self Intro.docx-AD21001_____Aathiraju
 

Recently uploaded (20)

Curtain Module Manual Zigbee Neo CS01-1C.pdf
Curtain Module Manual Zigbee Neo CS01-1C.pdfCurtain Module Manual Zigbee Neo CS01-1C.pdf
Curtain Module Manual Zigbee Neo CS01-1C.pdf
 
DNA LIGASE BIOTECHNOLOGY BIOLOGY STUDY OF LIFE
DNA LIGASE BIOTECHNOLOGY BIOLOGY STUDY OF LIFEDNA LIGASE BIOTECHNOLOGY BIOLOGY STUDY OF LIFE
DNA LIGASE BIOTECHNOLOGY BIOLOGY STUDY OF LIFE
 
Navigating the Never Normal Strategies for Portfolio Leaders
Navigating the Never Normal Strategies for Portfolio LeadersNavigating the Never Normal Strategies for Portfolio Leaders
Navigating the Never Normal Strategies for Portfolio Leaders
 
Enhancing SaaS Performance: A Hands-on Workshop for Partners
Enhancing SaaS Performance: A Hands-on Workshop for PartnersEnhancing SaaS Performance: A Hands-on Workshop for Partners
Enhancing SaaS Performance: A Hands-on Workshop for Partners
 
Unlocking the Cloud's True Potential: Why Multitenancy Is The Key?
Unlocking the Cloud's True Potential: Why Multitenancy Is The Key?Unlocking the Cloud's True Potential: Why Multitenancy Is The Key?
Unlocking the Cloud's True Potential: Why Multitenancy Is The Key?
 
2) Presentation_Overview_ISO_16140-3_Method_verification_20210322.pptx
2) Presentation_Overview_ISO_16140-3_Method_verification_20210322.pptx2) Presentation_Overview_ISO_16140-3_Method_verification_20210322.pptx
2) Presentation_Overview_ISO_16140-3_Method_verification_20210322.pptx
 
From eSIMs to iSIMs: It’s Inside the Manufacturing
From eSIMs to iSIMs: It’s Inside the ManufacturingFrom eSIMs to iSIMs: It’s Inside the Manufacturing
From eSIMs to iSIMs: It’s Inside the Manufacturing
 
GTA 6.pdf
GTA 6.pdfGTA 6.pdf
GTA 6.pdf
 
GDSC MMCOE - ML Campaign
GDSC MMCOE - ML CampaignGDSC MMCOE - ML Campaign
GDSC MMCOE - ML Campaign
 
AWS reInvent 2023 recaps from Chicago AWS user group
AWS reInvent 2023 recaps from Chicago AWS user groupAWS reInvent 2023 recaps from Chicago AWS user group
AWS reInvent 2023 recaps from Chicago AWS user group
 
OTel Orientation_ How to Train Teams (OTel in Practice).pdf
OTel Orientation_ How to Train Teams (OTel in Practice).pdfOTel Orientation_ How to Train Teams (OTel in Practice).pdf
OTel Orientation_ How to Train Teams (OTel in Practice).pdf
 
Manual Eurotronic Thermostatic Valve Comry Z-Wave
Manual Eurotronic Thermostatic Valve Comry Z-WaveManual Eurotronic Thermostatic Valve Comry Z-Wave
Manual Eurotronic Thermostatic Valve Comry Z-Wave
 
Microsoft Azure - GAA and Irish Tech Society Hackathon
Microsoft Azure - GAA and Irish Tech Society HackathonMicrosoft Azure - GAA and Irish Tech Society Hackathon
Microsoft Azure - GAA and Irish Tech Society Hackathon
 
A Comprehensive Theoretical Overview of Self-Driving Car Technology
A Comprehensive Theoretical Overview of Self-Driving Car TechnologyA Comprehensive Theoretical Overview of Self-Driving Car Technology
A Comprehensive Theoretical Overview of Self-Driving Car Technology
 
Bringing nullability into existing code - dammit is not the answer.pptx
Bringing nullability into existing code - dammit is not the answer.pptxBringing nullability into existing code - dammit is not the answer.pptx
Bringing nullability into existing code - dammit is not the answer.pptx
 
zigbee motion sensor user manual NAS-PD07B2.pdf
zigbee motion sensor user manual NAS-PD07B2.pdfzigbee motion sensor user manual NAS-PD07B2.pdf
zigbee motion sensor user manual NAS-PD07B2.pdf
 
Introduction to Serverless with AWS Lambda in C#.pptx
Introduction to Serverless with AWS Lambda in C#.pptxIntroduction to Serverless with AWS Lambda in C#.pptx
Introduction to Serverless with AWS Lambda in C#.pptx
 
My sample product research idea for you!
My sample product research idea for you!My sample product research idea for you!
My sample product research idea for you!
 
M.Aathiraju Self Intro.docx-AD21001_____
M.Aathiraju Self Intro.docx-AD21001_____M.Aathiraju Self Intro.docx-AD21001_____
M.Aathiraju Self Intro.docx-AD21001_____
 
Russia Ukraine war Cyberspace operations (2022-2024)
Russia Ukraine war Cyberspace operations (2022-2024)Russia Ukraine war Cyberspace operations (2022-2024)
Russia Ukraine war Cyberspace operations (2022-2024)
 

How Edmunds Got in the Fast Lane: 80% Reduction in Page Load Time in 3 Simple Steps

  • 1. HOW EDMUNDS GOT IN THE FAST LANE 80% Reduction in Page Load Time in Simple Steps by Ismail Elshareef Sunday, January 16, 2011
  • 2. The Results onLoad: 8.4s ➙ 1.9s (≈ 80% reduction) Page Views: 20% Bounce Rate: 4% Ad Impression Variance: 3% Sunday, January 16, 2011
  • 3. Edmunds, Inc. Online since 1995 Properties: 200M+ page views/month Revenue = Ads + Leads Sunday, January 16, 2011
  • 6. Meanwhile ... “95% of Performance is Frontend” - Steve Souders “Performance Matters!” - Organizations +100ms in response time ➡ -1% in sales -30% in file size ➡ +30% in requests Sunday, January 16, 2011
  • 7. The Real Picture! Sunday, January 16, 2011
  • 8. Site Condition - Too Many Requests (150+) - Many Blocking Requests (20+) - Perceived Slowness (onLoad in 8.4s) - No Caching - 1 Domains Serves All Requests - External Factors (ads, videos, ..etc) - Dependency on DOM Events Sunday, January 16, 2011
  • 9. We Started Tinkering ... Sunday, January 16, 2011
  • 10. Quick Wins: CACHING! - Solution Added Expires Header + Removed Etags - Result: 34% reduction in bandwidth = 34TB annual savings = FREE video streaming for 2 years = Faster pages when cache is primed Sunday, January 16, 2011
  • 11. ... but Legacy was complicated. Sunday, January 16, 2011
  • 12. 2008: A Vision Was Born Sunday, January 16, 2011
  • 13. Redesign Objectives PERFORMANCE (Faster Page Loads .. onLoad =< 1.5s) RICHER CONTENT (Flash, video, slicker UXD, ...etc) BETTER REVENUE (Positive impact on ad impressions) Sunday, January 16, 2011
  • 14. The Mindset FASTER PAGES POSITIVE USER EXPERIENCE HIGHER REVENUE Sunday, January 16, 2011
  • 15. The Challenge HTTP Requests Page Performance User Experience Sunday, January 16, 2011
  • 16. Types of HTTP Requests 1) Our Own Requests (files served from our own domains) 2) 3rd-party Requests (files served from other domains) Sunday, January 16, 2011
  • 17. 3rd-party Requests Exist in Two Forms JavaScript iFrame Cons: Cons: - Access to DOM - Fixed width/height - document.write Pros: Pros: - Easy to lazy-load - Richer Content - Sandboxed Code Sunday, January 16, 2011
  • 18. 3rd-party Requests Roles on Our Sites JavaScript iFrame Analytics A/B Testing Ads Video Widgets Monitoring Surveys Sunday, January 16, 2011
  • 19. Our Challenge 3rd-party Requests HTTP Requests Page Performance User Experience Sunday, January 16, 2011
  • 20. 3rd-party iFrame 3rd-party JavaScript Agreeable Problematic Sunday, January 16, 2011
  • 21. Mission: Control 3rd Attempt #1: Override document.write()function Example: var buffer = []; document.write = function(st) { buffer.push(st); } // when a specific event occurs ... var s = buffer.join(‘’); document.getElementById(‘destination’).innerHTML = s; Problem: Didn’t work with daisy-chained document.write calls Sunday, January 16, 2011
  • 22. Mission: Control 3rd Attempt #2: Load in iFrame and Copy on Load (iFrame’n’Copy) Example: var jsAd = “http://ad.doubleclick.net/adj/....”; iFrameObj.src = “http://www.edmunds.com/adSub.html?”+jsAd; // Option 1: listen to iFrame onLoad event // Option 2: iFrame page calls parent when done Problem: Buggy in IE 7 + Hard to Maintain Sunday, January 16, 2011
  • 23. Our New Found Creed  You Can Not Control Everything Sunday, January 16, 2011
  • 24. Edmunds vs. 3rd-party Requests %"#$ %"#$ &'()*'+,$-./).+0+$ 12'345206$-./).+0+$ !"#$ !"#$ New Sites Old Sites &'()*'+,$-./).+0+$ 12'345206$-./).+0+$ Sunday, January 16, 2011
  • 25. Our New Found Creed  Make What You Control FAST Sunday, January 16, 2011
  • 27. How Does it Work? Sunday, January 16, 2011
  • 28. How Does it Work? ❶ Quick page is served to user Sunday, January 16, 2011
  • 29. How Does it Work? 2 1 ❶ Quick page is 3 served to user 4 ❷ Page components register themselves with the page 5 6 7 Sunday, January 16, 2011
  • 30. How Does it Work? 2 1 ❶ Quick page is 3 served to user 4 ❷ Page components register themselves with the page 5 ❸ Registered components rendered 6 in parallel 7 Sunday, January 16, 2011
  • 31. Component 1 Component 2 Component 3 Registration Component 4 Component 5 Process Component 6 I need YUI’s Carousel module. Here’s my code, render me right away! I need flash.js and here’s my code. I need to be rendered right away Component 7 I need YUI’s Carousel module and here’s my code. I am below the fold so I can wait Component 8 Sunday, January 16, 2011
  • 32. Component 1 Component 2 Component 3 Registration Component 4 Component 5 Process Declare Dependencies Component 6 I need YUI’s Carousel module. Here’s my code, render me right away! I need flash.js and here’s my code. I need to be rendered right away Component 7 I need YUI’s Carousel module and here’s my code. I am below the fold so I can wait Component 8 Sunday, January 16, 2011
  • 33. Component 1 Component 2 Component 3 Registration Component 4 Component 5 Process Declare Dependencies Component 6 I need YUI’s Carousel module. Here’s my code, render me right away! Submit Functionality I need flash.js and here’s my code. I need to be rendered right away Component 7 I need YUI’s Carousel module and here’s my code. I am below the fold so I can wait Component 8 Sunday, January 16, 2011
  • 34. Component 1 Component 2 Component 3 Registration Component 4 Component 5 Process Declare Dependencies Component 6 I need YUI’s Carousel module. Here’s my code, render me right away! Submit Functionality I need flash.js and here’s my code. I need to be rendered right away Component 7 Set Priority I need YUI’s Carousel module and here’s my code. I am below the fold so I can wait Component 8 Sunday, January 16, 2011
  • 35. Registration Process Declare Dependencies PAGESETUP.files.push('file1.js'); PAGESETUP.files.push('file2.js'); PAGESETUP.files.push('file7.js'); Submit functionality PAGESETUP.addControl(function() { // .... // Anything from rendering a component to making an AJAX call. All goes here. // ... }, 'high'); Set Priority Sunday, January 16, 2011
  • 36. Process function load() { // ..... // ..... Dependencies var parent = arguments.callee; if (unique_files.length) { var file = unique_files.shift(); var js = document.createElement('script'); js.type = 'text/javascript'; js.src = file; if (!FF || FF >= 2) { js.onreadystatechange = function() { if (this.readyState == 'complete' || this.readyState == 'loaded' || this.status == 304 || this.status == 404) { parent(); } }; } else { parent(); } document.getElementsByTagName('head')[0].appendChild(js); if (PAGESETUP.execControls) { PAGESETUP.execControls(); } } } Sunday, January 16, 2011
  • 37. Get a reference to the function Process function load() { // ..... // ..... Dependencies var parent = arguments.callee; if (unique_files.length) { var file = unique_files.shift(); var js = document.createElement('script'); js.type = 'text/javascript'; js.src = file; if (!FF || FF >= 2) { js.onreadystatechange = function() { if (this.readyState == 'complete' || this.readyState == 'loaded' || this.status == 304 || this.status == 404) { parent(); } }; } else { parent(); } document.getElementsByTagName('head')[0].appendChild(js); if (PAGESETUP.execControls) { PAGESETUP.execControls(); } } } Sunday, January 16, 2011
  • 38. Get a reference to the function Process function load() { // ..... // ..... Dependencies var parent = arguments.callee; if (unique_files.length) { var file = unique_files.shift(); var js = document.createElement('script'); Process unique js.type = 'text/javascript'; js.src = file; dependencies if (!FF || FF >= 2) { js.onreadystatechange = function() { if (this.readyState == 'complete' || this.readyState == 'loaded' || this.status == 304 || this.status == 404) { parent(); } }; } else { parent(); } document.getElementsByTagName('head')[0].appendChild(js); if (PAGESETUP.execControls) { PAGESETUP.execControls(); } } } Sunday, January 16, 2011
  • 39. Get a reference to the function Process function load() { // ..... // ..... Dependencies var parent = arguments.callee; if (unique_files.length) { var file = unique_files.shift(); var js = document.createElement('script'); Process unique js.type = 'text/javascript'; js.src = file; dependencies if (!FF || FF >= 2) { js.onreadystatechange = function() { if (this.readyState == 'complete' || For all browsers but this.readyState == 'loaded' || FireFox < 4, Download this.status == 304 || this.status == 404) dependencies serially ... { parent(); } }; } else { parent(); } document.getElementsByTagName('head')[0].appendChild(js); if (PAGESETUP.execControls) { PAGESETUP.execControls(); } } } Sunday, January 16, 2011
  • 40. Get a reference to the function Process function load() { // ..... // ..... Dependencies var parent = arguments.callee; if (unique_files.length) { var file = unique_files.shift(); var js = document.createElement('script'); Process unique js.type = 'text/javascript'; js.src = file; dependencies if (!FF || FF >= 2) { js.onreadystatechange = function() { if (this.readyState == 'complete' || For all browsers but this.readyState == 'loaded' || FireFox < 4, Download this.status == 304 || this.status == 404) dependencies serially ... { parent(); } }; Otherwise, download in } else { parallel parent(); } document.getElementsByTagName('head')[0].appendChild(js); if (PAGESETUP.execControls) { PAGESETUP.execControls(); } } } Sunday, January 16, 2011
  • 41. Get a reference to the function Process function load() { // ..... // ..... Dependencies var parent = arguments.callee; if (unique_files.length) { var file = unique_files.shift(); var js = document.createElement('script'); Process unique js.type = 'text/javascript'; js.src = file; dependencies if (!FF || FF >= 2) { js.onreadystatechange = function() { if (this.readyState == 'complete' || For all browsers but this.readyState == 'loaded' || FireFox < 4, Download this.status == 304 || this.status == 404) dependencies serially ... { parent(); } }; Otherwise, download in } else { parallel parent(); } document.getElementsByTagName('head')[0].appendChild(js); if (PAGESETUP.execControls) { PAGESETUP.execControls(); } } When done downloading, } render registered components! Sunday, January 16, 2011
  • 42. Rendering Components execControls: function(start) { // Get a timestamp here to indicate the start of the process // Merge all the queues into one! high->normal->low var merged = this.merged; // Go through the merged array and execute the chunks! setTimeout(function() { // Get a chunk from the top of the array var item = merged.shift(); if(item){ // Execute the chunk! item.call(); } if (merged.length > 0) { // Wait 25 ms and then get the next chunk setTimeout(arguments.callee, 25); } else { // Otherwise, get a timestamp to indicate the end of the process } }, 0); }, Sunday, January 16, 2011
  • 43. Rendering Components execControls: function(start) { // Get a timestamp here to indicate the start of the process // Merge all the queues into one! high->normal->low var merged = this.merged; // Go through the merged array and execute the chunks! setTimeout(function() { // Get a chunk from the top of the array Combine functions var item = merged.shift(); submitted by if(item){ components in // Execute the chunk! item.call(); priority order (high } -> normal -> low) if (merged.length > 0) { // Wait 25 ms and then get the next chunk setTimeout(arguments.callee, 25); } else { // Otherwise, get a timestamp to indicate the end of the process } }, 0); }, Sunday, January 16, 2011
  • 44. Rendering Components execControls: function(start) { // Get a timestamp here to indicate the start of the process // Merge all the queues into one! high->normal->low var merged = this.merged; // Go through the merged array and execute the chunks! setTimeout(function() { // Get a chunk from the top of the array Combine functions var item = merged.shift(); submitted by if(item){ components in // Execute the chunk! Process one function at item.call(); a time ... priority order (high } -> normal -> low) if (merged.length > 0) { // Wait 25 ms and then get the next chunk setTimeout(arguments.callee, 25); } else { // Otherwise, get a timestamp to indicate the end of the process } }, 0); }, Sunday, January 16, 2011
  • 45. Rendering Components execControls: function(start) { // Get a timestamp here to indicate the start of the process // Merge all the queues into one! high->normal->low var merged = this.merged; // Go through the merged array and execute the chunks! setTimeout(function() { // Get a chunk from the top of the array Combine functions var item = merged.shift(); submitted by if(item){ components in // Execute the chunk! Process one function at item.call(); a time ... priority order (high } -> normal -> low) if (merged.length > 0) { // Wait 25 ms and then get the next chunk setTimeout(arguments.callee, 25); } else { // Otherwise, get a timestamp to indicate the end of the process } every 25 ms! }, 0); }, Sunday, January 16, 2011
  • 46. Our New Found Creed  Treat Everything Else as a Black Box Sunday, January 16, 2011
  • 47. 3rd-party iFrame 3rd-party JavaScript Agreeable Problematic Sunday, January 16, 2011
  • 48. 3rd-party iFrame 3rd-party JavaScript Agreeable Problematic Sunday, January 16, 2011
  • 49. 3rd-party Handling Logic Component Placeholder Markup on a page YES NO 3rd-party? Process through JS Loader JavaScript iFrame Render before </html> in a Register as "3rd- Remove original call hidden <div> party" component Relocate generated markup into placeholder Sunday, January 16, 2011
  • 50. Rendering 3rd-party JavaScript: Part 1 - Register the Call // Add the placeholder <div id="js-ad1"></div> <script type="text/javascript"> (function() { // Construct the ad URL var ad = new EDMUNDS.AdUnit(); // Inform the PAGESETUP object of what’s going on PAGESETUP.thirdpartyids.push('js-ad1'); PAGESETUP.thirdpartydetails['js-ad1'] = {}; PAGESETUP.thirdpartydetails['js-ad1']['type'] = 'ad'; PAGESETUP.thirdpartydetails['js-ad1']['src'] = ad.getAdUrl(); })(); </script> Sunday, January 16, 2011
  • 51. Rendering 3rd-party JavaScript: Part 1 - Register the Call Placeholder Markup // Add the placeholder <div id="js-ad1"></div> <script type="text/javascript"> (function() { // Construct the ad URL var ad = new EDMUNDS.AdUnit(); // Inform the PAGESETUP object of what’s going on PAGESETUP.thirdpartyids.push('js-ad1'); PAGESETUP.thirdpartydetails['js-ad1'] = {}; PAGESETUP.thirdpartydetails['js-ad1']['type'] = 'ad'; PAGESETUP.thirdpartydetails['js-ad1']['src'] = ad.getAdUrl(); })(); </script> Sunday, January 16, 2011
  • 52. Rendering 3rd-party JavaScript: Part 1 - Register the Call Placeholder Markup // Add the placeholder <div id="js-ad1"></div> Register details about <script type="text/javascript"> the JavaScript Request (function() { // Construct the ad URL var ad = new EDMUNDS.AdUnit(); // Inform the PAGESETUP object of what’s going on PAGESETUP.thirdpartyids.push('js-ad1'); PAGESETUP.thirdpartydetails['js-ad1'] = {}; PAGESETUP.thirdpartydetails['js-ad1']['type'] = 'ad'; PAGESETUP.thirdpartydetails['js-ad1']['src'] = ad.getAdUrl(); })(); </script> Sunday, January 16, 2011
  • 53. Rendering 3rd-party JavaScript: Part 1 - Register the Call Placeholder Markup // Add the placeholder <div id="js-ad1"></div> Register details about <script type="text/javascript"> the JavaScript Request (function() { // Construct the ad URL var ad = new EDMUNDS.AdUnit(); // Inform the PAGESETUP object of what’s going on Register: placeholder ID PAGESETUP.thirdpartyids.push('js-ad1'); PAGESETUP.thirdpartydetails['js-ad1'] = {}; PAGESETUP.thirdpartydetails['js-ad1']['type'] = 'ad'; PAGESETUP.thirdpartydetails['js-ad1']['src'] = ad.getAdUrl(); })(); </script> Sunday, January 16, 2011
  • 54. Rendering 3rd-party JavaScript: Part 1 - Register the Call Placeholder Markup // Add the placeholder <div id="js-ad1"></div> Register details about <script type="text/javascript"> the JavaScript Request (function() { // Construct the ad URL var ad = new EDMUNDS.AdUnit(); // Inform the PAGESETUP object of what’s going on Register: placeholder ID PAGESETUP.thirdpartyids.push('js-ad1'); PAGESETUP.thirdpartydetails['js-ad1'] = {}; PAGESETUP.thirdpartydetails['js-ad1']['type'] = 'ad'; PAGESETUP.thirdpartydetails['js-ad1']['src'] = ad.getAdUrl(); })(); </script> Register: JavaScript Call Sunday, January 16, 2011
  • 55. Rendering 3rd-party JavaScript: Part 2 - Render at the bottom of the page <script type="text/javascript"> if (PAGESETUP.thirdpartyids.length > 0) { (function() { var id = PAGESETUP.thirdpartyids.shift(); var file = PAGESETUP.thirdpartydetails[id].src; if (file) { document.write('<div id="'+id+'-cache'+'" style="display:none;"> <div id="'+id+'-root'+'">'); document.write('<script type="text/javascript" src="'+file+'" ></script>'); } })(); } </script> <script type="text/javascript">document.write('</div></div>');</script> Sunday, January 16, 2011
  • 56. Rendering 3rd-party JavaScript: Part 2 - Render at the bottom of the page Get the registered ID <script type="text/javascript"> if (PAGESETUP.thirdpartyids.length > 0) { (function() { var id = PAGESETUP.thirdpartyids.shift(); var file = PAGESETUP.thirdpartydetails[id].src; if (file) { document.write('<div id="'+id+'-cache'+'" style="display:none;"> <div id="'+id+'-root'+'">'); document.write('<script type="text/javascript" src="'+file+'" ></script>'); } })(); } </script> <script type="text/javascript">document.write('</div></div>');</script> Sunday, January 16, 2011
  • 57. Rendering 3rd-party JavaScript: Part 2 - Render at the bottom of the page Get the registered ID <script type="text/javascript"> Get the registered if (PAGESETUP.thirdpartyids.length > 0) { (function() { JavaScript Call var id = PAGESETUP.thirdpartyids.shift(); var file = PAGESETUP.thirdpartydetails[id].src; if (file) { document.write('<div id="'+id+'-cache'+'" style="display:none;"> <div id="'+id+'-root'+'">'); document.write('<script type="text/javascript" src="'+file+'" ></script>'); } })(); } </script> <script type="text/javascript">document.write('</div></div>');</script> Sunday, January 16, 2011
  • 58. Rendering 3rd-party JavaScript: Part 2 - Render at the bottom of the page Get the registered ID <script type="text/javascript"> Get the registered if (PAGESETUP.thirdpartyids.length > 0) { (function() { JavaScript Call var id = PAGESETUP.thirdpartyids.shift(); var file = PAGESETUP.thirdpartydetails[id].src; if (file) { document.write('<div id="'+id+'-cache'+'" style="display:none;"> <div id="'+id+'-root'+'">'); document.write('<script type="text/javascript" src="'+file+'" ></script>'); } })(); Wrap the call in a } </script> hidden DIV <script type="text/javascript">document.write('</div></div>');</script> Sunday, January 16, 2011
  • 59. Rendering 3rd-party JavaScript: Part 2 - Render at the bottom of the page Get the registered ID <script type="text/javascript"> Get the registered if (PAGESETUP.thirdpartyids.length > 0) { (function() { JavaScript Call var id = PAGESETUP.thirdpartyids.shift(); var file = PAGESETUP.thirdpartydetails[id].src; if (file) { document.write('<div id="'+id+'-cache'+'" style="display:none;"> <div id="'+id+'-root'+'">'); document.write('<script type="text/javascript" src="'+file+'" ></script>'); } })(); Wrap the call in a } </script> hidden DIV <script type="text/javascript">document.write('</div></div>');</script> Close the DIV Sunday, January 16, 2011
  • 60. In Summary  You Can Not Control Everything It’s OK, it really is :-)  Make What You Control FAST No DOM Event dependency Render components as soon as page is parsed Render components in priority  Treat Everything Else as a Black Box Process separately Delay inclusion as much as possible It’s about “mitigation” not “elimination” Sunday, January 16, 2011
  • 61. Inside Line Results Sunday, January 16, 2011
  • 62. Inside Line Redesign Objectives PERFORMANCE (onLoad ≈1.5) RICHER CONTENT (Large Flash content serving photos and videos) BETTER REVENUE (Ad impression variance reduced by 3%) Sunday, January 16, 2011
  • 63. Another Vision Was Born Sunday, January 16, 2011
  • 64. Legacy Redesign Sunday, January 16, 2011
  • 65. Edmunds Legacy Edmunds Redesign 8.4 seconds 1.9 seconds ≈ 80% Reduction in Load Time! Sunday, January 16, 2011
  • 66. The Results 20% Total Page Views Per Session Sunday, January 16, 2011
  • 67. The Results 3% Ad Impression Variance Sunday, January 16, 2011
  • 68. The Results 4% Bounce Rate Sunday, January 16, 2011
  • 69. In The Works ... Sunday, January 16, 2011
  • 70. JavaScript Loader 2.0 EVEN FASTER! Load in parallel and execute on-demand COMPONENT METRICS (When it’s loaded, how long it took, ..etc) MANY ENHANCEMENTS :) Sunday, January 16, 2011
  • 71. Soon ... http://www.github.com/edmunds Sunday, January 16, 2011
  • 72. What About The Future? Sunday, January 16, 2011
  • 73.  You Can Not Control Everything  Make What You Control FAST  Treat Everything Else as a Black Box How Will It Apply To ... Sunday, January 16, 2011
  • 76. Edmunds Platform Plug-n-Play Widgets Syndication Managed Products raw data Content ® Standalone packaged data Tools Open Source Plugins Code Snippets Cars Mobile UI Handheld Wired UI API Backend Systems Sunday, January 16, 2011
  • 77. Edmunds Platform 3rd-party Consumer ® 3rd-party Provider Sunday, January 16, 2011
  • 78. Let’s Continue the Conversation @codeish http://tech.edmunds.com Photo Credits: All Car Photos are from www.insideline.com http://www.cantronicsglobal.com/images/MissionVision.jpg http://www.kewlwallpapers.com/images/wallpapers/John_C-680196.jpeg Sunday, January 16, 2011