Custom HTML elements and better ads

Perry Mitchell / 2016-10-08 17:09:34
Custom HTML elements and better ads

So, cus­tom el­e­ments is a thing and we can be­gin look­ing at how browsers are go­ing to sup­port it go­ing for­ward. Custom el­e­ments are ex­cit­ing be­cause they al­low for great ex­ten­si­bil­ity and bet­ter ex­pres­sion of struc­ture and be­hav­iour. I won’t dive into what cus­tom el­e­ments are, as many have done this be­fore I, but if you want to catch up on what cus­tom el­e­ments are, there’s plenty to find about them on the Googles.

Be aware that there are 2 ver­sions of the spec”: v0 and v1. Tutorials and doc­u­men­ta­tion will cover one or the other mostly.

While v0 has more sup­port across browsers, it still does­n’t look so great:

custom elements v0 browser support

v1 looks even worse.

While cus­tom el­e­ments lacks suf­fi­cient sup­port for wide­spread use, the ideas that can be ac­cu­rately ex­pressed us­ing a cus­tom data struc­ture and be­hav­iour don’t have to be ig­nored. One such idea that I’ve had is the im­prove­ment of on­line ads through cre­at­ing el­e­ments de­signed for the very spe­cific pur­pose of dis­play­ing ads to a user.

Here’s a ground-level stab at ex­press­ing, with cus­tom el­e­ments, what a cus­tom ad im­ple­men­ta­tion might look like:

<i-ad 
  data-creative="http://ad-server.com/banner/728x90.png"
  data-click="https://publisher.org/promotion/"
  data-cb-passback="_ad01_callback"></i-ad>

Without go­ing into too much de­tail, we could prob­a­bly agree that on­line ads have some ba­sic things in com­mon:

  • A cre­ative to show to the user
  • A click event or tar­get (URL or Javascript event)

What all ads should have in com­mon, in my opin­ion, is a uni­ver­sal pass­back method. Having been de­vel­op­ing in the adtech world for some time now it’s very frus­trat­ing work­ing with var­i­ous net­works and their dis­tinct lack of API sup­port. Having some agreed-upon way of sig­nalling a lack of fill and al­low­ing in­te­grated plat­forms to per­form their own pass­back func­tions would rev­o­lu­tionise dy­namic ad place­ments.

My ex­am­ple code in­cludes data-cb-passback, which is de­signed to hold the name of a global pass­back func­tion on the window. When the ad passes-back due to lack of de­mand, the func­tion will be ex­e­cuted.

The <i-ad></i-ad> syn­tax looks pretty neat, right? It’s very ex­pres­sive, and al­lows us to de­fine some cus­tom func­tion­al­ity:

var IAdPrototype = Object.create(HTMLElement.prototype);

/**
 * Initialise a passback
 */
IAdPrototype.passback = function() {
    if (this.hasPassbacked) {
        return;
    }
    this.hasPassbacked = true;
    var cbName = this.dataset.cbPassback;
    if (cbName && window[cbName]) {
        window[cbName](this);
    }
};

/**
 * On-created callback
 */
IAdPrototype.createdCallback = function() {
    var shadow = this.createShadowRoot();

    // If we have a creative
    if (this.dataset.creative) {
        var img = document.createElement("img");
        img.src = this.dataset.creative;
        img.width = 728;
        img.height = 90;
        shadow.appendChild(img);
    }

    // If the 'click' attribute exists
    if (this.dataset.click) {
        this.style.cursor = "pointer";
        this.addEventListener("click", function(e) {
            e.preventDefault();
            // Open the URL
            window.open(this.dataset.click);
        }, false);
    }
};

var IAd = document.registerElement("i-ad", {
    prototype: IAdPrototype
});

So we cre­ate an ex­ten­sion of the HTMLElement ob­ject, at­tach a createdCallback to fire when when an IAd is in­stan­ti­ated or lo­cated in the DOM, and reg­is­ter it on the document.

Our <i-ad> tag will then ren­der the cre­ative in a shadow root and at­taches a click lis­tener. If the ad passes back, we could sim­ply add func­tion­al­ity to take the value of this.dataset.cbPassback, find it on the win­dow and ex­e­cute its func­tion.

This ex­am­ple il­lus­trates a ba­sic im­ple­men­ta­tion with a sin­gle cus­tom el­e­ment, but we could be even more ex­pres­sive:

<i-ad>
    <i-ad-creative>
        <a href="http://somewhere.com">
            <img src="ad.jpg" />
        </a>
    </i-ad-creative>
    <i-ad-pixel data-event="viewed" data-amount="100%" href="http://ad-server.com/ping/?e=viewed&a=100&id=123" />
    <i-ad-pixel data-event="viewed" data-amount="50%" href="http://ad-server.com/ping/?e=viewed&a=50&id=123" />
    <i-ad-pixel data-event="clicked" data-href="http://ad-server.com/ping/?e=clicked&id=123" />
    <i-ad-passback data-callback="_ad01_callback" />
</i-ad>

There are end­less it­er­a­tions avail­able with cus­tom el­e­ments, but I feel that the sup­port lim­i­ta­tion is what’s hold­ing back a more global im­ple­men­ta­tion and pos­si­bly a stan­dard.

There are some sac­ri­fi­cies that could be made to bet­ter to­days ads in plain old HTML5 that’s sup­ported in most cur­rent browsers, but I’ll touch on this next time.