MITIGATING ADVERTISEMENT IMPACT
ON PAGE PERFORMANCE by Ismail Elshareef
Friday, October 22, 2010
ISMAIL
ELSHAREEF
Edmunds, Inc.
@codeish
@EdmundsLabs
Friday, October 22, 2010
EDMUNDS, INC.
Online since 1995
Properties:
150M+ page views/month
Revenue = Ads + Leads
Friday, October 22, 2010
IN 2008 ... A VISION WAS BORN
Friday, October 22, 2010
REDESIGN OBJECTIVES
PERFORMANCE
(Page onLoad in < 1.5 sec)
RICHER CONTENT
(Flash, video, slicker UXD, ...etc)
BETTER REVEN...
OUR DILEMMA
3rd-PARTY CODE PERFORMANCE
UXD
Friday, October 22, 2010
Fast WITHOUT
3rd
Party
Fast WITH 3rd
Party Code
Friday, October 22, 2010
• Fixed width/height
• Easy to late-load
• Sandboxed Code
iFrame JavaScriptOR
• Cannot lazy-load
• Access to DOM
• Richer ...
MISSION:
CONTROL 3RD
-PARTY JS
Friday, October 22, 2010
INITIAL ATTEMPTS
applies to 3rd
-Party JavaScript Code ONLY
Override document.write
iFrame’n’Copy
Friday, October 22, 2010
INITIAL ATTEMPTS
applies to 3rd
-Party JavaScript Code ONLY
Override document.write
iFrame’n’Copy
WE LEARNED THAT ...
3rd-...
(I) CAN’T CONTROL IT ALL
(II) SPEED UP WHAT YOU CAN
(Your code and lazy-loadable code)
(III) DEFER THE REST
(All code that...
JAVASCRIPT
LOADER
Friday, October 22, 2010
3RD
-PARTY
HANDLING
LOGIC
A
Is this an ad?
Is this a JS
ad?
Is this a JS
module?
NO
YES
Create
placeholder
markup
NO
Reque...
3RD
-PARTY
JAVASCRIPT
HANDLING
LOGIC
B
JS
Components?
DONE
NO
load in a hidden DIV
YES
.html?
disableallthird
party=yes
.h...
HOW DOES THE LOADER WORK?
Friday, October 22, 2010
addModule
execControl
addControl
timer
files
modules
queue
PAGESETUP
HOW DOES THE LOADER WORK?
Friday, October 22, 2010
<script type="text/javascript">
//<![CDATA[
PAGESETUP = {
timer: {start: (new Date).getTime()},
files: [],
modules: {},
qu...
var merged = this.merged;
setTimeout(function() {
var item = merged.shift();
if (merged.length > 0) {
setTimeout(arguments...
<script type="text/javascript">
//<![CDATA[
PAGESETUP = {
timer: {start: (new Date).getTime()},
files: [],
modules: {},
qu...
<script type="text/javascript">
//<![CDATA[
PAGESETUP = {
timer: {start: (new Date).getTime()},
files: [],
modules: {},
qu...
<script type="text/javascript">
//<![CDATA[
PAGESETUP = {
timer: {start: (new Date).getTime()},
files: [],
modules: {},
qu...
<script type="text/javascript">
//<![CDATA[
PAGESETUP = {
timer: {start: (new Date).getTime()},
files: [],
modules: {},
qu...
<script type="text/javascript">
//<![CDATA[
PAGESETUP = {
timer: {start: (new Date).getTime()},
files: [],
modules: {},
qu...
<script type="text/javascript">
//<![CDATA[
PAGESETUP = {
timer: {start: (new Date).getTime()},
files: [],
modules: {},
qu...
WHY CREATE OUR OWN LOADER?
Run JS chunks in order of priority
Allow a Debug Mode
Decouple from DOM events
Friday, October ...
3RD
-PARTY CODE WITH JS LOADER
Lazy-load in desired priority
iFrames JavaScriptOR
Include after Loader include
<iframe id=...
With Ads
Without Ads
INSIDELINE.COM STATS
Friday, October 22, 2010
ANOTHER VISION WAS BORN
Friday, October 22, 2010
HTTP REQUESTS
0
50
100
150
200
Homepage New Cars Used Cars
Legacy Site Beta Site
152 135 111
44 72 44
Friday, October 22, ...
PAGESPEED SCORES
0
22.5
45
67.5
90
PageSpeed
Legacy Site Beta Site
8765
Friday, October 22, 2010
INITIAL RESULTS
17%Total PageViews Per Session
Friday, October 22, 2010
(I) CAN’T CONTROL IT ALL
(II) SPEED UP WHAT YOU CAN
(Your code and lazy-loadable code)
(III) DEFER THE REST
(All code that...
WE ARE HIRING!
http://www.edmunds.com/help/about/jobs/
Friday, October 22, 2010
THANK YOU!
ISMAIL ELSHAREEF
Edmunds, Inc.
WE ARE HIRING!
http://www.edmunds.com/help/about/jobs/
@codeish
@EdmundsLabs
Pho...
Upcoming SlideShare
Loading in …5
×

Mitigating Advertisement Impact on Page Performance

1,484 views

Published on

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,484
On SlideShare
0
From Embeds
0
Number of Embeds
35
Actions
Shares
0
Downloads
10
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Mitigating Advertisement Impact on Page Performance

  1. 1. MITIGATING ADVERTISEMENT IMPACT ON PAGE PERFORMANCE by Ismail Elshareef Friday, October 22, 2010
  2. 2. ISMAIL ELSHAREEF Edmunds, Inc. @codeish @EdmundsLabs Friday, October 22, 2010
  3. 3. EDMUNDS, INC. Online since 1995 Properties: 150M+ page views/month Revenue = Ads + Leads Friday, October 22, 2010
  4. 4. IN 2008 ... A VISION WAS BORN Friday, October 22, 2010
  5. 5. REDESIGN OBJECTIVES PERFORMANCE (Page onLoad in < 1.5 sec) RICHER CONTENT (Flash, video, slicker UXD, ...etc) BETTER REVENUE (Only positive impact on ad impressions) Friday, October 22, 2010
  6. 6. OUR DILEMMA 3rd-PARTY CODE PERFORMANCE UXD Friday, October 22, 2010
  7. 7. Fast WITHOUT 3rd Party Fast WITH 3rd Party Code Friday, October 22, 2010
  8. 8. • Fixed width/height • Easy to late-load • Sandboxed Code iFrame JavaScriptOR • Cannot lazy-load • Access to DOM • Richer Content FORMS OF 3RD -PARTY CODE • Disadvantage • Advantage Friday, October 22, 2010
  9. 9. MISSION: CONTROL 3RD -PARTY JS Friday, October 22, 2010
  10. 10. INITIAL ATTEMPTS applies to 3rd -Party JavaScript Code ONLY Override document.write iFrame’n’Copy Friday, October 22, 2010
  11. 11. INITIAL ATTEMPTS applies to 3rd -Party JavaScript Code ONLY Override document.write iFrame’n’Copy WE LEARNED THAT ... 3rd-Party JS Code should be treated as Friday, October 22, 2010
  12. 12. (I) CAN’T CONTROL IT ALL (II) SPEED UP WHAT YOU CAN (Your code and lazy-loadable code) (III) DEFER THE REST (All code that cannot be lazy-loaded) OUR NEWFOUND CREED Friday, October 22, 2010
  13. 13. JAVASCRIPT LOADER Friday, October 22, 2010
  14. 14. 3RD -PARTY HANDLING LOGIC A Is this an ad? Is this a JS ad? Is this a JS module? NO YES Create placeholder markup NO Request JS file after loader is included B Create iframe placeholder markup YES NO Add JS chunk to Loader loading the iframe after page load event Create placeholder markup Request JS file after loader is included B Create iFrame placeholder markup Lazy-load iFrame with JS Loader YES DONE DONE Friday, October 22, 2010
  15. 15. 3RD -PARTY JAVASCRIPT HANDLING LOGIC B JS Components? DONE NO load in a hidden DIV YES .html? disableallthird party=yes .html? disableallads= yes .html? disableadnum ber=[int] YES is ad? NO NO YES YES NO is ad position == [int]? YES YES <script> is done loading move content to placeholder (collapse when appropriate) NO NO Friday, October 22, 2010
  16. 16. HOW DOES THE LOADER WORK? Friday, October 22, 2010
  17. 17. addModule execControl addControl timer files modules queue PAGESETUP HOW DOES THE LOADER WORK? Friday, October 22, 2010
  18. 18. <script type="text/javascript"> //<![CDATA[ PAGESETUP = { timer: {start: (new Date).getTime()}, files: [], modules: {}, queue: {high:[], normal:[], low:[]}, addModule: function(mod) { if (PAGESETUP.modules[mod]) { ++PAGESETUP.modules[mod]; } else { PAGESETUP.modules[mod] = 1; } }, execControls: function(start) { if (!this.merged) { this.merged = PAGESETUP.queue.high; this.merged = this.merged.concat(PAGESETUP.queue.normal).concat(PAGESETUP.queue.low); } var merged = this.merged; setTimeout(function() { var item = merged.shift(); if (merged.length > 0) { setTimeout(arguments.callee, 10); } item.call(); }, 0); }, addControl: function(fn, priority) { switch(priority) { case 'high': this.queue.high.push(fn); break; case 'low': this.queue.low.push(fn); break; case 'normal': default: this.queue.normal.push(fn); break; } } }; //]]> </script> addModule execControl addControl timer files modules queue PAGESETUP HOW DOES THE LOADER WORK? Friday, October 22, 2010
  19. 19. var merged = this.merged; setTimeout(function() { var item = merged.shift(); if (merged.length > 0) { setTimeout(arguments.callee, 10); } item.call(); }, 0); }, addControl: function(fn, priority) { switch(priority) { case 'high': this.queue.high.push(fn); break; case 'low': this.queue.low.push(fn); break; case 'normal': default: this.queue.normal.push(fn); break; } } }; //]]> </script> addModule execControl addControl timer files modules queue PAGESETUP HOW DOES THE LOADER WORK? Friday, October 22, 2010
  20. 20. <script type="text/javascript"> //<![CDATA[ PAGESETUP = { timer: {start: (new Date).getTime()}, files: [], modules: {}, queue: {high:[], normal:[], low:[]}, addModule: function(mod) { if (PAGESETUP.modules[mod]) { ++PAGESETUP.modules[mod]; } else { PAGESETUP.modules[mod] = 1; } }, execControls: function(start) { if (!this.merged) { this.merged = PAGESETUP.queue.high; this.merged = this.merged.concat(PAGESETUP.queue.normal).concat(PAGESETUP.queue.low); } var merged = this.merged; setTimeout(function() { var item = merged.shift(); if (merged.length > 0) { setTimeout(arguments.callee, 10); } item.call(); }, 0); }, addControl: function(fn, priority) { switch(priority) { case 'high': this.queue.high.push(fn); break; case 'low': this.queue.low.push(fn); break; case 'normal': default: this.queue.normal.push(fn); break; } } }; //]]> </script> addModule execControl addControl timer files modules queue PAGESETUP HOW DOES THE LOADER WORK? Friday, October 22, 2010
  21. 21. <script type="text/javascript"> //<![CDATA[ PAGESETUP = { timer: {start: (new Date).getTime()}, files: [], modules: {}, queue: {high:[], normal:[], low:[]}, addModule: function(mod) { if (PAGESETUP.modules[mod]) { ++PAGESETUP.modules[mod]; } else { PAGESETUP.modules[mod] = 1; } }, execControls: function(start) { if (!this.merged) { this.merged = PAGESETUP.queue.high; this.merged = this.merged.concat(PAGESETUP.queue.normal).concat(PAGESETUP.queue.low); } var merged = this.merged; setTimeout(function() { var item = merged.shift(); if (merged.length > 0) { setTimeout(arguments.callee, 10); } item.call(); }, 0); }, addControl: function(fn, priority) { switch(priority) { case 'high': this.queue.high.push(fn); break; case 'low': this.queue.low.push(fn); break; case 'normal': default: this.queue.normal.push(fn); break; } } }; //]]> </script> addModule execControl addControl timer files modules queue PAGESETUP !"#$%&'(')&*+,'*-'./010"#$%&',("$#+,&0'2.'3.0&%.4305*$.4305*$6/",7!."#$%&'7 HOW DOES THE LOADER WORK? Friday, October 22, 2010
  22. 22. <script type="text/javascript"> //<![CDATA[ PAGESETUP = { timer: {start: (new Date).getTime()}, files: [], modules: {}, queue: {high:[], normal:[], low:[]}, addModule: function(mod) { if (PAGESETUP.modules[mod]) { ++PAGESETUP.modules[mod]; } else { PAGESETUP.modules[mod] = 1; } }, execControls: function(start) { if (!this.merged) { this.merged = PAGESETUP.queue.high; this.merged = this.merged.concat(PAGESETUP.queue.normal).concat(PAGESETUP.queue.low); } var merged = this.merged; setTimeout(function() { var item = merged.shift(); if (merged.length > 0) { setTimeout(arguments.callee, 10); } item.call(); }, 0); }, addControl: function(fn, priority) { switch(priority) { case 'high': this.queue.high.push(fn); break; case 'low': this.queue.low.push(fn); break; case 'normal': default: this.queue.normal.push(fn); break; } } }; //]]> </script> addModule execControl addControl timer files modules queue PAGESETUP !"#$%&'(')&*+,'*-'./010"#$%&',("$#+,&0'2.'3.0&%.4305*$.4305*$6/",7!."#$%&'7 HOW DOES THE LOADER WORK? - Loads global core libs (with YUI libs) Friday, October 22, 2010
  23. 23. <script type="text/javascript"> //<![CDATA[ PAGESETUP = { timer: {start: (new Date).getTime()}, files: [], modules: {}, queue: {high:[], normal:[], low:[]}, addModule: function(mod) { if (PAGESETUP.modules[mod]) { ++PAGESETUP.modules[mod]; } else { PAGESETUP.modules[mod] = 1; } }, execControls: function(start) { if (!this.merged) { this.merged = PAGESETUP.queue.high; this.merged = this.merged.concat(PAGESETUP.queue.normal).concat(PAGESETUP.queue.low); } var merged = this.merged; setTimeout(function() { var item = merged.shift(); if (merged.length > 0) { setTimeout(arguments.callee, 10); } item.call(); }, 0); }, addControl: function(fn, priority) { switch(priority) { case 'high': this.queue.high.push(fn); break; case 'low': this.queue.low.push(fn); break; case 'normal': default: this.queue.normal.push(fn); break; } } }; //]]> </script> addModule execControl addControl timer files modules queue PAGESETUP !"#$%&'(')&*+,'*-'./010"#$%&',("$#+,&0'2.'3.0&%.4305*$.4305*$6/",7!."#$%&'7 HOW DOES THE LOADER WORK? - Loads global core libs (with YUI libs) - Executes JS chunks in priority in 25 ms intv. Friday, October 22, 2010
  24. 24. <script type="text/javascript"> //<![CDATA[ PAGESETUP = { timer: {start: (new Date).getTime()}, files: [], modules: {}, queue: {high:[], normal:[], low:[]}, addModule: function(mod) { if (PAGESETUP.modules[mod]) { ++PAGESETUP.modules[mod]; } else { PAGESETUP.modules[mod] = 1; } }, execControls: function(start) { if (!this.merged) { this.merged = PAGESETUP.queue.high; this.merged = this.merged.concat(PAGESETUP.queue.normal).concat(PAGESETUP.queue.low); } var merged = this.merged; setTimeout(function() { var item = merged.shift(); if (merged.length > 0) { setTimeout(arguments.callee, 10); } item.call(); }, 0); }, addControl: function(fn, priority) { switch(priority) { case 'high': this.queue.high.push(fn); break; case 'low': this.queue.low.push(fn); break; case 'normal': default: this.queue.normal.push(fn); break; } } }; //]]> </script> addModule execControl addControl timer files modules queue PAGESETUP !"#$%&'(')&*+,'*-'./010"#$%&',("$#+,&0'2.'3.0&%.4305*$.4305*$6/",7!."#$%&'7 HOW DOES THE LOADER WORK? - Loads global core libs (with YUI libs) - Executes JS chunks in priority in 25 ms intv. - Has debugging features ?jsflag=full Friday, October 22, 2010
  25. 25. <script type="text/javascript"> //<![CDATA[ PAGESETUP = { timer: {start: (new Date).getTime()}, files: [], modules: {}, queue: {high:[], normal:[], low:[]}, addModule: function(mod) { if (PAGESETUP.modules[mod]) { ++PAGESETUP.modules[mod]; } else { PAGESETUP.modules[mod] = 1; } }, execControls: function(start) { if (!this.merged) { this.merged = PAGESETUP.queue.high; this.merged = this.merged.concat(PAGESETUP.queue.normal).concat(PAGESETUP.queue.low); } var merged = this.merged; setTimeout(function() { var item = merged.shift(); if (merged.length > 0) { setTimeout(arguments.callee, 10); } item.call(); }, 0); }, addControl: function(fn, priority) { switch(priority) { case 'high': this.queue.high.push(fn); break; case 'low': this.queue.low.push(fn); break; case 'normal': default: this.queue.normal.push(fn); break; } } }; //]]> </script> addModule execControl addControl timer files modules queue PAGESETUP !"#$%&'(')&*+,'*-'./010"#$%&',("$#+,&0'2.'3.0&%.4305*$.4305*$6/",7!."#$%&'7 HOW DOES THE LOADER WORK? - Loads global core libs (with YUI libs) - Executes JS chunks in priority in 25 ms intv. - Has debugging features ?jsflag=full - Ability to exclude 3rd party code Friday, October 22, 2010
  26. 26. WHY CREATE OUR OWN LOADER? Run JS chunks in order of priority Allow a Debug Mode Decouple from DOM events Friday, October 22, 2010
  27. 27. 3RD -PARTY CODE WITH JS LOADER Lazy-load in desired priority iFrames JavaScriptOR Include after Loader include <iframe id=”ad1” width=”300” height=”250”> // add JS chunk to loader ... ... ... <script src=”loader.js”></script> // execute JS chunk through loader </body> <div id=”ad2”></div> ... ... ... ... ... <script src=”loader.js”></script> // Handle JavaScript ads </body> Friday, October 22, 2010
  28. 28. With Ads Without Ads INSIDELINE.COM STATS Friday, October 22, 2010
  29. 29. ANOTHER VISION WAS BORN Friday, October 22, 2010
  30. 30. HTTP REQUESTS 0 50 100 150 200 Homepage New Cars Used Cars Legacy Site Beta Site 152 135 111 44 72 44 Friday, October 22, 2010
  31. 31. PAGESPEED SCORES 0 22.5 45 67.5 90 PageSpeed Legacy Site Beta Site 8765 Friday, October 22, 2010
  32. 32. INITIAL RESULTS 17%Total PageViews Per Session Friday, October 22, 2010
  33. 33. (I) CAN’T CONTROL IT ALL (II) SPEED UP WHAT YOU CAN (Your code and lazy-loadable code) (III) DEFER THE REST (All code that cannot be lazy-loaded) AGAIN ... OUR NEWFOUND CREED Friday, October 22, 2010
  34. 34. WE ARE HIRING! http://www.edmunds.com/help/about/jobs/ Friday, October 22, 2010
  35. 35. THANK YOU! ISMAIL ELSHAREEF Edmunds, Inc. WE ARE HIRING! http://www.edmunds.com/help/about/jobs/ @codeish @EdmundsLabs Photo Credits: http://farm3.static.flickr.com/2203/2498445479_064841a97d_o.jpg http://jcreviews.files.wordpress.com/2010/03/battlestar-galactica.jpg http://img.wallpaperstock.net:81/crossroads-in-life-wallpapers_10124_1600x1200.jpg http://upload.wikimedia.org/wikipedia/commons/0/01/Stapler-swingline-red.jpg Friday, October 22, 2010

×