googleads / videojs-ima

IMA SDK Plugin for Video.js
Apache License 2.0
450 stars 284 forks source link

IMA returns 402 when player div repositioned during session in React SPA #956

Closed matt-iakhno closed 3 years ago

matt-iakhno commented 3 years ago

"video.js": "^7.9.7" "videojs-ima": "^1.8.3" "videojs-contrib-ads": "^6.7.0"

Hi IMA team,

I've been battling with this one for 3 days now, and am all out of ideas. We are building an SPA (React) where we'd like to maintain the player session between pages. The issue we've run into is if the player loads a VMAP tag on one page, and then we move the player anywhere else, all subsequent ad requests in the session return a 402 and the IMA SDK times out on playback.

A link to reproduce this issue is available here:

https://codepen.io/mattdsp/pen/pobNGqm

Steps to reproduce:

  1. Select an ad tag from the dropdown (eg "VMAP Postroll")
  2. Press the "Play Ads" button below the player (3rd button)
  3. After playback begins, press the "Move Player" button
  4. Now, request a different ad (eg "VMAP Preroll")
  5. Press the "Play Ads" button again - ad will not play.

Output:

[ima.admanager.VideoAdManager] Playback error: [object Object] AdError 402: VAST media file loading reached a timeout of 8 seconds. bridge3.418.3_debug_en.html:929 [ 11.197s] [UrlReporter] Reporting urls for event : error bridge3.418.3_debug_en.html:929 [ 11.199s] [ima.common.ErrorUtils] Error play dispatched: AdError 402: VAST media file loading reached a timeout of 8 seconds.

Although the above is a CodePen, the behavior in my SPA environment is identical (including me moving the player with .appendChild() ). The main difference is I guess that I'm requesting a new Ad Tag using the VideoJS IMA method rather than the native IMA SDK method as in the codepen:

async changeSource(src, vmap, doAutoplay = false) {
    this.player.pause();
    return new Promise(async (resolve) => {
        // listen to the loadedmetadata event right away so we can resolve the
        // promise as soon as the new video has loaded
        this.player.on('loadedmetadata', function(){
            resolve();
        })
        if (this.player.ima && typeof this.player.ima.changeAdTag === 'function') {
            this.player.ima.changeAdTag(vmap);
            this.player.ima.requestAds();
        }
        this.player.src(src);
    })
}

How can I "reset" the IMA SDK after repositioning it? Do I need to somehow perform a more "full" teardown of the SDK, and if so - how? At this point it is not possible for me to completely dispose of the entire player and re-render it.

Thank you in advance for your help. Best, Matt

Kiro705 commented 3 years ago

Hello Matt (@matt-iakhno) ,

I'm afraid that this is an unsupported use case. The player should already be on the page and appended correctly before ads are being requested and played. Moving the player within the DOM will break functionality as you have seen.

I do not believe there is currently a method to 'reset' the player in a new location, and so a full re-instantiation of the player would be necessary. What is your use-case that requires the player to move during your app's lifecycle? I can share it with the IMA team to see what possible solution could exist.

Thank you, IMA SDK DevRel, Jackson

matt-iakhno commented 3 years ago

Hi Kiro,

Thank you for your response. We will change our app logic to fully dispose of the player on route change.

The only hack we were able to come up that "worked" with was overriding one of the constructors in the plugin to delete and re-instantiate the ads display container on ad requests, but do not feel comfortable shipping that to a production environment.

Best, Matt