GithubHelp home page GithubHelp logo

jonhoo / vast-vmap Goto Github PK

View Code? Open in Web Editor NEW
58.0 10.0 19.0 152 KB

JavaScript library for IAB VAST + VMAP

License: MIT License

JavaScript 100.00%
video-player javascript html5-video advertisement vast

vast-vmap's Introduction

Build Status

What is this?

This is a JavaScript library for working with Ad Servers providing ads through IAB VAST and VMAP formatted responses. VAST is the standard for delivering the ads, whereas VMAP is the standard for deciding where in the video stream ads should go.

The library has not yet been tested at all, just written according to the specifications. It is likely that it does not work. Hopefully it will evolve over time now that the ground work has been put down though.

Do you have an example?

Nope, not yet. I'll probably write a HTML5 video integration soon that should act like a demo though. Watch this space.

How do I use it?

For now, read the JSDoc. I think it should be fairly straightforward, but maybe not. When I get around to writing a demo, things might be more clear. Would be good to have a VAST/VMAP provider that were willing to put up a test service though.

Also, note that this is a very low-level library. It parses VAST/VMAP, handles wrapped responses and tracking for you and tells you which ads to play when. It does no do anything unless you ask for something or tell it do do something. For example, you have to explicitly call VASTCreative#track on a creative any time a trackable event happens. The library will not watch for the events since it does not care how you display the data.

Level of standards support

Should support most sensible VAST 3.0 (and therefore also 2.0) and VMAP 1.0 resources. Also supports some silly things like deeply nested Wrapper resources and even more silly things like AdPods inside AdPods inside AdPods (which is possble because of the weird way IAB have decided to do Wrapper responses). The following things have been left out mostly intentionally:

  • Sequence numbers for creatives (because the standard doesn't really give a use case for them)
  • Any kind of extensions
  • Survey elements (what are these anyway?)
  • Anything that has to do with pricing or money
  • Anything related to "apiFramework"

Known issues

The following is a list of features that I do want to implement, but I just haven't gotten around to them yet.

  • Enforcement of the "required" attribute for Companion Ads
  • An interface for reporting errors so that they are reported back to the Ad Server
  • adParameters for Flash StaticResources
  • Industry Icons (which are required according to the standard). This is simply because I haven't gotten around to it yet. Also, they're not very well described in the standard.

Testing

I've added some rudimentary tests using BusterJS based on some VAST 2.0 XML files distributed by the IAB. Feel free to add more if you want to. Still need a good example VMAP document though...

In order to run the tests, start by installing dev dependencies:

npm install

And then:

grunt test

You can also watch for changes and immediately run the tests:

grunt watch:tests

Support

This code is not officially supported by anyone, not even me. I give no guarantees that it is working, nor that it will work any time soon. Don't come running to me if your server catches on fire because of using this libary.

Any issues should be submitted at the Github issues page. Pull requests are more than welcome!

vast-vmap's People

Contributors

alex-phillips avatar jonhoo avatar shlomi-tc avatar shlomitc avatar sterpe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vast-vmap's Issues

Handle empty vast response (no ads)

According to iab spec (vast 3.0, section 2.4.2.4):

When the ad server does not or cannot return!an Ad, the VAST response should contain only the root element with optional element, as shown below:

<VAST version=”3.0”>
    <Error>
        <![CDATA[http://adserver.com/noad.gif]>
</Error>
</VAST>

The issue in our case, which is related to issue #7 is that when there are no ads, the 'onAdsAvailable' callback is not triggered.

The solution should contain both handling 'no ads' and adding the "error" element to the callback response (so the user will be able to fire this error pixel).

Regarding "no ads" callback there are two possible solutions:

  1. Trigger the same "onAdsAvailable" callback, with no ads. The user should validate the response and check for available ads
  2. Trigger a different error callback

I will be happy to assist & add a solution here.

tnx!

Dynamic `window[cls]` constructor generation fails when `vast-vmap` runs within a function scope.

So what I am doing is injecting VAST-VMAP into the DOM via Flash ExternalInterface.call and wrapping it in an anonymous function that looks basically like this:

!function (url) {
  <% = vast-vmap.js %>
  ;function onSuccess () { /* code here */}
  ;function onFailure () {/* code here */}
  ;queryVAST(url, onSuccess, onFailure)
}("http://some.vast.server.com/foo.xml")

And this is just to avoid polluting the containing document global space and other weirdness.

This is all fine, until L797 and L811:

var cls = tag === "Companion" ? "VASTCompanion" : "VASTNonLinear";
// ...
 n = new window[cls](this, items.item(j));

Which then fails because these are not defined on the global scope.

I'd like to put in a PR to change these two lines to use the function references in the scope, wherever that may be.

var cls = tag === "Companion" ? VASTCompanion : VASTNonLinear;
// ...
n = new cls(this, items.item(j));

Checking if tag is VPAID or Non-VPAID

I first would like to say that your vast-parser is awesome and easy to use.

I was wondering if there's a check in your code for whether the tag is VPAID. I'm implementing a bundle that parses the VAST tag only if it's non-VPAID and it'd be helpful if that functionality is implemented somewhere already.

Handling error tags for <InLine> and <Wrapper>

According to IAB documentation:
" contains a URI to a tracking resource that the video player should request if for some reason the InLine ad could not be served"

As I saw, VASTAd object implementation (inside the constructor) doesn't extract these errors from the given .

New Chrome has no 'namespaceURI'

My google Chrome just got updated to version 46.0.2490.71 m (latest at the moment) and suddenly all my ads ware gone (while on FireFox it still works well) , from a quick debug i found that on the VASTAds constructor (line 420) the adElement variable is empty after line 425 :

  var adElements = root.getElementsByTagNameNS(root.namespaceURI, 'Ad');

I've noticed that namespaceURI is undefined on Chrome,
on FireFox it is null and adElement is not empty after line 425 and has the ad in it.

any idea what might cause this and how to fix it?

Script breaks when Wrapper-VASTAdTagURI fails

If VAST is a wrapper, and the VASTAdTagURI fails (e.g. due to missing CORS), onLoaded breaks, consequently the queryVAST onFetched callback is never called. onLoaded expects ads to be populated, there is no error checking in there.

(Possible solution, and workaround for me locally: If ads arrives as null in onLoaded, this.loaded is be set to true anyway and onAdAvailable is called, so errors could still be tracked, but I'm not sufficiently familiar with the recursion mechanism to actually decide this.)

Missing withCredentials

The XHR is missing the withCredentials flag. This is easily remedied by setting it in fetchXML():

  var request = new XMLHttpRequest();
  request.withCredentials = true;

Without withCredentials, some advertisers' (e.g., doubleclick) servers would not respond properly.

Functions scope

Hi,

I'm currently working on a HTML5 video player for a French company. Your script is really helpful for my VAST developpements! Thank you for create it!

This message does not really concern an issue.

Can I suggest you a small update which can be very usefull? All your functions are in the "window" scope, it can be better if all your functions move to a specific scope like "vastVamp" or something like that :)

Regards

Updating README

Hi, first, i wanted to say job well done! 👍 this lib is awesome!

Thing is, the JSDocs are not all the clear to newbies.
Any chance you could please update the README with some info on how to approach different functionality? from using the queryVAST to Tracking and pixel handling etc... ?

Thanks in advance!

namespaceURI is deprecated

According to this: https://developer.mozilla.org/en-US/docs/Web/API/Element/namespaceURI

Node.namespaceURI was removed from Chrome as of version 46.

So in the code (line 435), this will not work:

var adElements = root.getElementsByTagNameNS(root.namespaceURI, 'Ad');

root.namespceURI will return undefined.

In my case, I added the following check, but I'm not sure if it's enough.

if (typeof root.namespaceURI === 'undefined') {
    root.namespaceURI = null;
}

<AdParameters> not being parsed

Hi,
With the big change of dropping Flash in the browser world, the Javascript VPAID format is gaining popularity.

In a lot of VAST xml ads i can find the <AdParameters> tag (usualy as a JSON object).
Is it possible to please add the code and add it to the VASTLiner object?

mediatype supported?

Hey man quick question. How could I check whether the media player supports a certain format? I see that you have the function getBestMedia which matches the closest width, height, and bitrate, but what if the player doesn't actually support a certain format?

Thanks!

screen shot 2016-01-25 at 8 06 44 pm

Missing License

Can you please add a license to the code so it can be (legitimately) used by others?

When using a 'wrapper', the data passed in 'onGotFirstAd' is not updated

Inside onGotFirstAd, when calling oaf.call(that, that);, the that argument is passed instead of ads. As far as I understand it should be:

(function(ad, allowPods, that) {
                onGotFirstAd = function(ads) {
                    ad.onLoaded(ads, allowPods);
                    if (that.onAdsAvailable) {
                        var oaf = that.onAdsAvailable;
                        that.onAdsAvailable = null;
                        oaf.call(that, ads);//instead of oaf.call(that, that);
                    }
                };
})(ad, allowPods, that);

while debugging the wrapper example I noticed that the that object which is passed does not contain the updated data. I guess it is somehow related to the fact that its value is passed before parsing and the reference not being changed later. Changing the value to ads fixed this issue for me. I will have to take a deeper look at this problem and see what could be the correct fix for that (if you have any ideas/suggestions I will love to here).

Wrapper example:
http://demo.tremorvideo.com/proddev/vast/vast_wrapper_linear_2.xml

related to issue #2

<Impression> tags are not extracted from a parent wrapper

Causes the wrapping VAST provider to not be notified when the inner-vast impression is sent.

I think this is quite a simple fix and I will open a PR for that, but I just wanted to know where is the right place to do it.

No doubt it should inside the VASTAd function flow.
At first look I thought it should be where you copy tracking and creatives from parent (line 578).
But since parentAd.impressions is an array of string, you don't need to copy the same way you extract TrackingEvents (companions/nonlinears/...)

Any other thoughts?

Ad tag macros

Most of the tags i see these days are VPAID (Flash/JS) and look somthing like this:

http://ads.somesite.advertising.com/ad?cb=[CACHE_BUSTER]&pageUrl=[URL]&description=[VIDEO_DESCRIPTION]&duration=[VIDEO_DURATION]&id=[VIDEO_ID]&keywords=&title=[VIDEO_TITLE]&url=[VIDEO_FILE_URL]

All these macros need to be filled as best as possible in order for the ad server to return the most comprehensive VAST xml file it can, i thought about writing a function that would do just that, but i'm not sure if it should be a part of the VAST-VMAP library or a stand-alone function, any ideas?

Macros object being changed

in javascript TrackingEvents.prototype.Track(ev, macros) the macros object sent will be changed by the function when called again and again on that Ad, resulting in each key getting wrapped with additional [] every time:

for example:
before: {height:100, width:200}
after first pixel sent: {[height]:100, [width]:200}
after second pixel sent: {[[height]]:100, [[width]]:200}
after thired pixel sent: {[[[height]]]:100, [[[width]]]:200}
... and so on.

might be useful to clone that object using this function:

function clone(obj){
    if(obj === null || typeof(obj) != 'object')
        return obj;

    var temp = new obj.constructor();
    for(var key in obj)
        temp[key] = clone(obj[key]);

    return temp;
}

like so

TrackingEvents.prototype.track = function(ev, macros) {
  var temp_macros = clone(macros) // code added
  if (!this.events[ev] || this.events[ev].length === 0) {
    return;
  }
  var evs = [].concat(this.events[ev]);
  var i;
  for (var m in temp_macros) { //changed here
    if (!temp_macros.hasOwnProperty(m)) { //changed here
      continue;
    }

    temp_macros["[" + m + "]"] = encodeURIComponent(temp_macros[m]); //changed here
    delete temp_macros[m]; //changed here
  }
...
}

that way if the same macro is being sent it won't be changed outside Track()
hope this helps 😄

Vast wrapper + linear augment issue

Hey,

I am playing with this parser (great work, man!!!). I found two issues while trying to use a wrapper request:

First, VASTLinear.prototype.augment will not copy duration and mediaFiles, which results in the final VASTAd.linear missing this data. Changing this method to be:

VASTLinear.prototype.augment = function(other) {
    this.duration = other.duration;//new line, copy duration
    this.mediaFiles = other.mediaFiles.slice(0); //new line, copy mediaFiles array
    this.tracking.augment(other.tracking);
    this.clickThrough = other.clickThrough || this.clickThrough;
};

Am I missing something?

Second, inside onGotFirstAd, when calling oaf.call(that, that);, the that argument is passed instead of ads. As far as I understand it should be:

(function(ad, allowPods, that) {
                onGotFirstAd = function(ads) {
                    ad.onLoaded(ads, allowPods);
                    if (that.onAdsAvailable) {
                        var oaf = that.onAdsAvailable;
                        that.onAdsAvailable = null;
                        oaf.call(that, ads);//instead of oaf.call(that, that);
                    }
                };
})(ad, allowPods, that);

You can test it with IAB tests from here:
http://demo.tremorvideo.com/proddev/vast/vast_wrapper_linear_2.xml
http://demo.tremorvideo.com/proddev/vast/vast_inline_linear.xml

I would love to hear what you think about my comments (I can add a pull request with the fixes if it helps).

Format separation

Hi, as i saw in previous issue, there's no other option but saying: good job!

Is it possible to have the formats separated into different files(VAST and VMAP)?
I'd do it myself but i don't wanna drop something buy accident.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.