We’ve migrated our documentation to a new site, which means some URLs have changed.
Audience

Creative Template / Client-Side Template-Based Rendering

Examples and how to

  • cx.js simple HTML templating

  • Example 1 - Simple image ad

  • Example 2a - Simple image ad with collapsing (unit resizing)

  • Example 2b - Resizing to content size (pixel resizing)

  • Example 2c - Resizing to content size (100%-wide ad)

  • Example 3 - Simple combo ad (image + text)

  • Example 4a - Rendering without an IFrame - Inline template

  • Example 4b - Rendering without an IFrame - AJAX-loaded template

  • Example 4c - Rendering without an IFrame - JSONP-loaded template

  • Example 5 - Expanding image ad

  • Example 6 - Combined Cxense Content (recs) and Ads widget

  • Example 7 - Adding a logo

  • Example 8a - Using the default renderer

  • Example 8b - Custom rendering for one ad type and default rendering for all other ad types

  • Example 9 - Adding a timeout

  • Using the render template editor

Rationale

  • The default rendering engine in cX::ad provides one look for rendering ads. It is possible to do some CSS styling, but not much, and nothing on HTML layout

  • Rendering templates provide an easy layout and rendering option for combo creatives and third-party creatives.

Benefits

  • Can accommodate any kind of HTML rendered output, unlimited control of CSS, HTML and JavaScript

  • Handles all the aspects of user tracking and passing unique user identifiers

  • Does not need a proxy at the publisher site.

  • We can provide the ad search results as data to the client to allow for any kind of custom client rendering.

Implementation

Overview

JSON-Templating.png

How it works

  1. The end-user's browser loads our customer's page

  2. That page includes our ad script that loads cx.js and adds a call to the method "insertAdSpace" (as before)

  3. The call to insertAdSpace also has a new parameter " renderTemplateUrl: 'http://cdn.cxpublic.com/customerX/templateY.html' "

  4. cx.js sees this parameter, and instead of creating an IFRAME and sourcing it directly from the AdServer, cx.js creates the IFRAME and sources it from the renderTemplateUrl

  5. To optimize caching from the CDN, cx.js modifies any random or unique URL parameter to be sent as an URL fragment instead, e.g.:

    1. Instead of http://adserver.cxad.cxense.com/adserver/search?asId=123&rnd=1231231231231&pn=0

    2. we send: http://cdn.cxpublic.com/customerX/templateY.html#asId=123&rnd=1231231231231&pn=0

  6. The browser loads the HTML from the CDN into the IFRAME

  7. The browser executes JavaScript in the IFRAME

  8. The JavaScript in the IFRAME issues a JSONP call to the AdServer by dynamically inserting a <script> tag with source like:

    1. http://adserver.cxad.cxense.com/adserver/search?asId=123&rnd=1231231231231&media= javascript&callback=myCallback

  9. The AdServer processes the request as normal

  10. The AdServer formats the result as JSON (e.g. "ads: {}" (no ads))

  11. The AdServer sees that there is a "callback" parameter, and wraps the JSON in a callback: "myCallback({ads: {} }); "

  12. The browser loads the script respnse and executes the callback

  13. The IFRAME HTML receives the callback, iterates over the returned ads and instantiates the templates

You must control pagination manually (e.g. the pn=0 parameter above) as the adserver is unable to determine whether creatives will fit in your allocated space.

Performance

The performance is as good or better than the "media=html" responses, because the template is cached hard (thus removing the one extra HTTP request) and the transferred data is less than for HTML, which must include the layout. If the template is cached very hard, it will almost never be loaded by the browser, and the actual data transferred is less then the "media=html" version, hence the performance is even better.

Behavioural ads / user tracking / cookies

None of these are modified in with this approach:

  • cx.js still sets / reads the site-specific cookies on the publisher's page

  • The template page does not modify any cookies

  • The JSONP requset to the adserver is done on the "http://cxense.com " domain, so the gckp and gcks cookies are added to the request by the browser automatically

Contextual ads

For the JSONP request, the HTTP referrer header cannot be used, as it will be pointing to the template CDN URL. The cx.js script therefore always pass on the URL of the publishers page in the ctx parameter to the adserver.

Considerations for external Publishers

Some Brokers will not have direct access to a website to embed or update an Ad Tag(s).

In these cases, you should include only the bare minimum specification in the tags themselves to reduce the maintenance of the tag(s). For example do not include Ad Dimensions (e.g. auw, auh), Required amount of Ads (e.g. ps values), nor Pagination options (pn values). You can read about these settings further in the Search REST and JavaScript API page. The User Interface should be the 'control' for these settings, as it is always accessible without bothering your Publisher.

Security

Script domains

JavaScript code in the template is run in a separate domain.

The URL of the CDN that serves the static HTML is therefore be something else than http://cxense.com . Currently it is "cxpublic.com".

Templating and cross-site scripting

The templating mechanisms has code that prevents the browser evaluating advertiser-provided data.

Read more about this in cx.js simple HTML templating

Sample code

Sample publisher page

<html>
<head>
 <title>Main page</title>
</head>
<body>
  
 <!-- Publisher's content -->
  
 <!-- cXense Ad script begin -->
 <div id="adPlaceholder" style="display:none"></div>
 <script type="text/javascript">
   (function() { try { var scriptEl = document.createElement('script'); scriptEl.type = 'text/javascript'; scriptEl.async = 'async';
   scriptEl.src = ('https:' == document.location.protocol) ? 'https://scdn.cxense.com/cx.js' : 'http://cdn.cxense.com/cx.js';
   var targetEl = document.getElementsByTagName('script')[0]; targetEl.parentNode.insertBefore(scriptEl, targetEl); } catch (e) {}; }());
 </script>
  
 <script type="text/javascript">
   var cX = cX || {}; cX.callQueue = cX.callQueue || [];
   cX.callQueue.push(['insertAdSpace', {
     adSpaceId:'0000000000a0701d', // Can also be set in the template
     resizeToContent:'true',
     renderTemplateUrl: 'http://cdn.cxpublic.com/customerX/templateY.html'
   }]);
 </script>
 <!-- cXense Ad script end -->
  
 <!-- Publisher's content cont'd -->
  
</body>
</html>

 

Sample template HTML from CDN

<html>
<head>
 <title>Ad Template HTML</title>
</head>
<body xmlns:tmp="javascript:">
 
  <!-- The ads are inserted into this div: -->
  <div id="adArea"></div>
 
  <!-- This is the template that is used to instanciate the ads: -->
  <div id="adTemplate" style="display:none">
    <img
      style="border:none;"
      tmp:src="{{searchResult.contentBaseURL + ad.creative.contentServerId}}"
      width="{{ad.creative.spec.width}}"
      height="{{ad.creative.spec.height}}" />
  </div>
 
  <!-- cXense script begin -->
  <div id="cX-root" style="display:none"></div>
 
  <script type="text/javascript">
    (function() { try { var scriptEl = document.createElement('script'); scriptEl.type = 'text/javascript'; scriptEl.async = 'async';
    scriptEl.src = ('https:' == document.location.protocol) ? 'https://scdn.cxense.com/cx.js' : 'http://cdn.cxense.com/cx.js';
    var targetEl = document.getElementsByTagName('script')[0]; targetEl.parentNode.insertBefore(scriptEl, targetEl); } catch (e) {}; }());
  </script>
 
  <script id="scriptForAdSpace_0000000000a889ff" type="text/javascript">
    var cX = cX || {}; cX.callQueue = cX.callQueue || [];
    cX.callQueue.push(['renderAdSpace', {
      adSpaceId: '0000000000a889ff', // Can be automatically read from URL
      adTemplateElementId: 'adTemplate',
      targetElementId: 'adArea'
    }]);
  </script>
  <!-- cXense script end -->
 
</body>
</html>

 

Sample ad server JSONP response

myCallback({
  "searchResult": {
    "pageNumber": 0,
    "contentBaseURL": "http://adserver.cdn.cxense.com/content/_cid_",
    "previous": "",
    "next": "http://adserver.cxad.cxense.com/adserver/search?pn=1&asId=0000000000a28e7f&media=javascript",
    "spaces": [
      {
        "id": "0000000000a28e7f",
        "ads": [
          {
            "id": "0000000000a55a53",
            "creatives": [
              {
                "type": "com.fastsearch.admomentum.plugins.textcreative.feature.TextCreativeFeature",
                "formatVersion": "1.0",
                "id": "0000000000a54e7a",
                "title": [{"em": "Storbyferie"}, " til ", {"em": "Amsterdam"}],
                "content": [
                  ["Sammenlign priser - ", {"em": "spar"}, " penger. Bestill ", {"em": "storbyferie"}, " til ", {"em": "Amsterdam"}]
                ],
                "displayUrl": "www.ticket.no/storbyferie/amsterdam",
                "destinationUrl": "http://www.ticket.no/bestill/storbyferie/amsterdam.html?cid=ano.btest-adwise.c2011-09.ds.eadwise.fcpc.gsearch.h1.ir.jfh"
              }
            ],
            "clickUrl": "http://adserver.cxad.cxense.com/adserver/click/AAAAAACijn8AAAAAAKVaUwAAAAAApU5661eJKv7)RamBU0hMq4J8IA4wHzIuMDAwMDAwH05PSwAAAAEAAAEzIqQRxgAA"
          }
        ]
      }
    ]
  }
});
 
 


Last updated: