ads performance

Overview:

Demonstrate improvements to ads implementation and show the empirical process needed for this, -ie, an improvement provides context though which another improvement is made and so on -not a two-step process.


current improvements:

  1. analysis, peformance

    I analyzed performance issues around our site layout.

    summary:

  2. documentation, building block

    I documented the ad-display process and added explanations and examples around methods in the new ads script, adengine.js.

    Documentation was needed to understand relationship among various disconnected files, including (but not limited to) the following files:

    /apps/fscom/components/content/advertising/clientcontext/clientcontext.jsp
    /apps/fscom/components/content/article/articleFooterTeaser/articleFooterTeaser.jsp
    /apps/fscom/components/content/advertising/interstitialTeaser/content.jsp
    /apps/cq/personalization/components/teaser/content.jsp
    ../../../../../../platform/platform-core-ui/src/main/content/jcr_root/apps/platform/components/content/adTeaser/content.jsp
    /apps/fscom/components/content/advertising/msnAdvertisement/msnAdvertisement.jsp,
    /apps/fscom/components/content/advertising/nativeTeaser/nativeTeaser.jsp,
    /apps/fscom/components/content/advertising/overlayteaserconfig/overlayteaserconfig.jsp,
    /apps/fscom/components/content/advertising/ribbonAdvertisement/ribbonAdvertisement.jsp
    /apps/fscom/components/content/advertising/ribbonAdvertisement/ribbonAdvertisement.jsp
    /etc/designs/fsdigital/foxsports/scripts/main_async/source/ads.js
    /etc/designs/fsdigital/foxsports/scripts/main_async/source/app/transitions.js
    granite_shared_override.js
    scripts/main_async/source/app/views/photo.js
    apps/fscom/components/content/advertising/clientlib/utils.js
    /libs/cq/personalization/clientlib/kernel/source/segmentmanager/segmentmanager.js
    /libs/cq/personalization/clientlib/kernel/source/shared/clientcontextmanager.js
    /libs/cq/personalization/components/clickstreamcloud/clickstreamcloud.jsp
    apps/cq/personalization/components/teaser/content.jsp
    fscom/components/content/advertising/interstitialTeaser/content.jsp
    fscom/components/content/article/articleFooterTeaser/articleFooterTeaser.jsp
    

    Basically these three things must happen sequentially:

    1. CQ scripts are requested
    2. page state is 'set' in CQ namespace clientcontext
    3. campaign info is 'set' in CQ namespace segmentation
    4. CQ namespace 'chooses' ads, config data is requested
    5. config data is used to request the ad from a service

    summary:

  3. centralization, building block/stability

    Understanding ads allows us to centralize and control behaviour.

    There is now one initialization method that serves as the starting point for all ad display, adengine.initializeClientContext. Following that, these things are added to the new implementation and are not found in the current one.

    initializeClientContext begins an ordered construction of ads:

    1. one system used to construct all ads
    2. needed CQ scripts are requested one time only
    3. methods on CQ scripts are redefined
      • this was previously impossible because the additional requests for CQ scripts would in newly made definitions
    4. all campaign data initialized one time
    5. all ads constructed one time
    6. all events around ads are bound one time
    7. configuration data for each ad is used for each ad before the associated template it comes from is added to the document
      • for example, previously, markup around the ribbon ad would be added to the document first and then data would be extracted from that and used to request the ad. What if the request fails? What if the data is invalid?
      • do we want the markup there? maybe not.
  4. hooks, building block

    Centralizing ads functionality enables the addition of reliable hooks into the ad loading process. A 'hook' give us the ability to control a behaviour before moving on to the next step.

    Hooks are added to the new ads script and are not found in the old one.

    For example, a hook added for msnads. We use the hook to verify the requested ad is valid -if not valid do not create markup in the document for it. We may now request a different ad if we choose.

    A list of added hooks:

    1. For loading CQ scripts
    1. For initializing campaign data
    1. Loading each ad
    1. Loading the msn ad
    1. Requesting ad data
    1. Signaling completion of all ad activity
  5. modularization, building block/stability

    The new adengine creates ad-type-specific objects. Previously all ads where managed by a single script and data for each ad was stored in the document.

    The old way was error prone -the document changes and is an unreliable data store. It prohibited clear separation of behaviours needed for each ad. Managing specific and global ad concerns in one script is an unnecessary cognitive overhead.

    The follwing ad scripts are new: admsn.js, adribbon.js, adoverlay.js, with a pending adphoto.js.


next steps:

  1. 'fix' author-mode creation of ads

    Locally, I'm unable to configure new ads. This situation existed before I began work on the ads. It needs to be fixed.

  2. 'fix' caching/headers of ads in development

    Locally, I need to open chrome in incognito mode to test changes made to ads scripts or templates. A slow and tiresome process.

  3. mock ads and related services for testing ad behaviour

    Sometimes an overlay ad appears. Sometimes it doesn't. We want the ability to produce an overlay ad on command.

  4. reduce number of requests for ads

    The ads scripts are currently enabled to make these requests.

    1) serve campaign/page configuration data in one request.

    Currently, several slightly different files may construct this data.

    We would centralize construction of the data to one class. Tests could be written around that.

    Currently templates are made with an assumption the ads namespace is defined. data is passed to calls on that namespace at whatever time the browser evaluates the template.

    We would control this process, requesting data with our ads script after CQ scripts are loaded and any other needed requirements are met.

    The service response would look like this:

    {
      pageObj : {
        ccPath: "/etc/clientcontext/foxsports",
        currentPath: "/content/fsdigital/fscom/nfl",
        isEditMode: false,
        segmentsPath: "/etc/segmentation"
      },
      campaignObjArr : [{
        from:"adTeaser/content.jsp",
        allTeasers:[{
          path:"/content/campaigns/nfl/ribbon/visa",
          name:"visa",
          title:"Visa",
          campaignName:"ribbon",
          thumbnail:"/content/campaigns/nfl/ribbon/visa.thumb.png",
          id:"ribbon_visa",
          segments:[
            "/etc/segmentation/nfl/stories"
          ],
          tags:[]
        },{
          path:"/content/campaigns/nfl/ribbon/training-teaser",
          name:"training-teaser",
          title:"Training Teaser",
          campaignName:"ribbon",
          thumbnail:"/content/campaigns/nfl/ribbon/training-teaser.thumb.png",
          id:"ribbon_training-teaser",
          segments:[
            "/etc/segmentation/nfl/homepage"
          ],
          tags:[]
        }],
        strategy:"random",
        targetDivId:"_content_fsdigital_fscom_nfl_jcr_content_adplaceholderBelowNavigation_adteaser",
        WCMMode:"false",
        trackingUrlStr:"null",
        resourcePath:"/content/fsdigital/fscom/nfl/jcr:content/adplaceholderBelowNavigation/adteaser"
      }, {
        from:"teaser/content.jsp",
        allTeasers:[{
          path:"/content/campaigns/nfl/buzzer/sample_html",
          name:"sample_html",
          title:"sample_html",
          campainName:"buzzer",
          thumbnail:"/content/campaigns/nfl/buzzer/sample_html.thumb.png",
          id:"buzzer_sample_html",
          segments:[],
          tags:[]
        }],
        strategy:"first",
        targetDivId:"_content_fsdigital_fscom_nfl_jcr_content_buzz_buzzer_buzzerTeaser",
        WCMMode:false,
        trackingUrlStr:"http://localhost:4502/libs/wcm/stats/tracker",
        resourcePath:"/content/fsdigital/fscom/nfl/jcr:content/buzz/buzzer/buzzerTeaser"
      }, {
        from:"teaser/content.jsp",
        allTeasers:[{
          path:"/content/campaigns/nfl/columnb/Visa",
          name:"Visa",
          title:"Visa",
          campainName:"columnb",
          thumbnail:"/content/campaigns/nfl/columnb/Visa.thumb.png",
          id:"columnb_Visa",
          segments:[],
          tags:[]
        }],
        strategy:"random",
        targetDivId:"_content_fsdigital_fscom_nfl_jcr_content_newsTop_teaser",
        WCMMode:false,
        trackingUrlStr:"http://localhost:4502/libs/wcm/stats/tracker",
        resourcePath:"/content/fsdigital/fscom/nfl/jcr:content/newsTop/teaser"
      }]
    }
    

    2) serve ad configuration data with one response.

    We currently request config data for each ad displayed. When 5 ads are displayed 5 requests are made.

    We would separate the config data from the markup which currently owns it, requesting ad data after necessary page and campaign configuration are complete.

    Request info could be a PUT/POST request body (not restful):

    [
        "/content/campaigns/nfl/ribbon/training-teaser/_jcr_content/par.html?wcmmode=disabled",
        "/content/campaigns/nfl/buzzer/sample_html/_jcr_content/par.html?wcmmode=disabled",
        "/content/campaigns/nfl/columnb/Visa/_jcr_content/par.html?wcmmode=disabled"
    ]
    

    Or added to a GET request path as x-www-form-urlencoded data:

    http://chris.foxsports.com/jenniesadresource?0=%2Fcontent%2Fcampaigns%2Fnfl%2Fribbon%2Ftraining-teaser%2F_jcr_content%2Fpar.html%3Fwcmmode%3Ddisabled&1=%2Fcontent%2Fcampaigns%2Fnfl%2Fbuzzer%2Fsample_html%2F_jcr_content%2Fpar.html%3Fwcmmode%3Ddisabled&2=%2Fcontent%2Fcampaigns%2Fnfl%2Fcolumnb%2FVisa%2F_jcr_content%2Fpar.html%3Fwcmmode%3Ddisabled
    

    A response would look like this:

    [{
      type:"ads",
      elemId:"77d42c34_ca51_449b_bf4e_c18db50f773d",
      adtype:"ads.msn",
      defaultConfig:{
        type:"ads.msn",
        PG:"SPTRF1",
        AP:"1390",
        W:"728",
        H:"90"
      },
      config2col:{
        type:"msn",
        PG:"SPTRF1",
        AP:"1390",
        W:"728",
        H:"90"
      },
      config1col:{
        type:"msn",
        PG:"123456",
        AP:"1402",
        W:"1",
        H:"1"
      }
    },{
      type:"ads",
      elemId:"50971120_b3c8_4294_a00e_2f60bbbe4a76",
      adtype:"ads.msn",
      defaultConfig:{
        type:"ads.msn",
        PG:"RMT152",
        AP:"1089",
        W:"300",
        H:"250"
      },
      config2col:{
        type:"msn",
        PG:"RMT152",
        AP:"1089",
        W:"300",
        H:"250"
      },
      config1col:{
        type:"msn",
        PG:"RMT152",
        AP:"1089",
        W:"300",
        H:"250"
      }
    },{
      type:"ads",
      elemId:"f5335522_c088_4bf9_aa9b_8dcb54538a45",
      adtype:"ads.msn",
      defaultConfig:{
        type:"ads.msn",
        PG:"RMT151",
        AP:"1402",
        W:"980",
        H:"50"
      },
      config2col:{
        type:"msn",
        PG:"123456",
        AP:"1402",
        W:"1",
        H:"1"
      },
      config1col:{
        type:"msn",
        PG:"123456",
        AP:"1402",
        W:"1",
        H:"1"
      }
    }]
    
  5. testing

    We'll need to test scenarious around each ad type to find any problems and make necessary changes.

bumblehead.com