Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Teads: AutoplayDetection causes fullscreen video on WKWebView #11438

Closed
webberig opened this issue May 3, 2024 · 31 comments · Fixed by #11822
Closed

Teads: AutoplayDetection causes fullscreen video on WKWebView #11438

webberig opened this issue May 3, 2024 · 31 comments · Fixed by #11822
Labels

Comments

@webberig
Copy link

webberig commented May 3, 2024

Type of issue

Bug

Description

We encountered some strange behavior in our mobile app after updating prebid.js. A full screen native media player appears with a black 1-second video.

20240430_upd_r200_ios_black_overlay.mp4

This is caused by the autoplay detection:
https://github.com/prebid/Prebid.js/blob/7ab6165e342294fafa087135af219f3f88f0e220/libraries/autoplayDetection/autoplay.js

The app is built using Cordova and Ionic which uses a WKWebView component to render the web application. Apparently, WKWebView has a property allowsInlineMediaPlayback which - when turned off - forces video content to be displayed in a native fullscreen controller.

This property is turned off by default on iPhone, turned on by default on iPad.

The autoplay detection of prebid.js plays a small video to determine wether autoplay is supported, which is invisible in most common browsers but seems to have a disturbing side effect in WKWebView.

Steps to reproduce

This can only be reproduced in a native iOS application using a WKWebView which in turn contains a webpage that is running prebid.js.

Test page

Providing a demo app has little use as you need to have XCode installed and run the app in Simulator. One does not simply install an app from unknown origin on iPhones ;-)

I'm hoping the WKWebView documentation is enough to prove the bug being presented.

Expected results

prebid.js should not bother a user with a fullscreen 1s black video. The current approach can be considered hacky at best, so I would recommend looking at proper feature detection such as this draft spec: https://www.w3.org/TR/autoplay-detection/

Actual results

As soon as prebid.js is loaded, the user gets a fullscreen 1s black video. After closing it (by swiping or a close button in a corner of the screen), normal behavior is resumed.

Platform details

Tested with prebid.js v8.45.0
Browser is a WKWebView inside a native iOS mobile app, built using XCode 15.3. According to docs, this property is present in iOS version >= 8.0

Other information

@patmmccann
Copy link
Collaborator

patmmccann commented May 6, 2024

cc @github-matthieu-wipliez

fwiw only Teads adapter uses this. One solution could be to disable Teads while the fix is pending.

@patmmccann patmmccann added the bug label May 6, 2024
@github-matthieu-wipliez
Copy link
Contributor

Hi @webberig, sorry for the trouble! I'm not sure why the video is displayed as the video element we create is not even inserted in the DOM. I'll try to see if setting display: none on the element fixes this.

I would have been very happy to use a standard feature, unfortunately the getAutoplayPolicy is only available on Firefox :/

@patmmccann patmmccann changed the title AutoplayDetection causes fullscreen video on WKWebView Teads: AutoplayDetection causes fullscreen video on WKWebView May 6, 2024
@github-matthieu-wipliez
Copy link
Contributor

Hi again, I have failed to reproduce it locally using a WKWebView with a configuration that sets allowsInlineMediaPlayback = false and loads a simple HTML page running the piece of script from the autoplay detection. I'm using XCode 15.3 and tested with the simulator (iPhone 15, iOS 17.2 and iPhone 15, iOS 17.4).

How is Prebid.js loaded? Do you have something else specific on your WKWebView? I'm trying to find a way to reproduce it so I can find a way to fix it

@whatadewitt
Copy link

@github-matthieu-wipliez does your cordova config support AllowInlineMediaPlayback for iOS? (https://cordova.apache.org/docs/en/3.2.0/guide/platforms/ios/config.html)

It would appear the autoplay detection would be great, but is unsupported at this time on most browsers. If you check the doc link above I think there is a solution you could try in there?

@github-matthieu-wipliez
Copy link
Contributor

Hi @webberig, good news, I've managed to reproduce the bug!

@whatadewitt I don't use Cordova, I'm directly testing in an iOS app using a WKWebView with a custom configuration.

I had not set mediaTypesRequiringUserActionForPlayback so it still had the default value (which appears to be .all) so even if I set allowsInlineMediaPlayback = false when I started the autoplay detection then iOS would prevent the video from starting (because no gesture was made). Setting both allowsInlineMediaPlayback = false and mediaTypesRequiringUserActionForPlayback = [] makes the video player start in fullscreen without any user interaction, as in your example.

That being said, the Teads ad player appears to assume that allowsInlineMediaPlayback is true and that video would play inline and not in fullscreen; in other words, even if I fix autoplay detection, our ad player would still play video ads directly in fullscreen (not sure if this is what you intend?)

I see several ways to fix this:

  • in your app, leave mediaTypesRequiringUserActionForPlayback to its default value so that no video opens for a user until they interact with the page.
  • set allowsInlineMediaPlayback = true in your application. It allows inline playback, but video without playsinline will still be in fullscreen, that's kind of the best of both worlds.
  • in the autoplay detection, I add a condition to check if I can play the video inline, and if I can't I don't run the autoplay detection.

What do you think?

@webberig
Copy link
Author

webberig commented May 7, 2024

Thanks for the efforts @github-matthieu-wipliez!

It appears that the cordova ionic-webview has an undocumented configuration which allows us to set the allowsInlineMediaPlayback to true (https://github.com/ionic-team/cordova-plugin-ionic-webview/blob/master/src/ios/CDVWKWebViewEngine.m#L204). That did solve it for our app. 🎉

It would be an improvement to prebid if you were able to detect that inline playback is allowed or not. Not just for the mock video, but for real ads too. Displaying ads in a fullscreen native player is probably not desirable ;-)

@github-matthieu-wipliez
Copy link
Contributor

That did solve it for our app. 🎉

Great!

I have tried to see if there was a way to detect if the video plays inline or not, and it seems that it's only possible to do that after the video has started playing (so it's already playing in fullscreen).

After discussing with my colleagues, our Teads player is only supposed to be used in an environment where playsinline is true. I propose that we update our documentation here: https://github.com/prebid/prebid.github.io/blob/891d45baf2f20eacfe3b9fa7045692d7db7bf26d/dev-docs/bidders/teads.md?plain=1#L28
to clearly state that requirement. @patmmccann is it an acceptable resolution?

@whatadewitt
Copy link

Apologies @github-matthieu-wipliez I tagged you in my response where I should have tagged @webberig -- regardless, glad you are sorted :)

@patmmccann
Copy link
Collaborator

@github-matthieu-wipliez we'll discuss in committee tomorrow. I'm not familiar enough with how often this may occur to weigh in

@aanton
Copy link

aanton commented May 7, 2024

I have tried to see if there was a way to detect if the video plays inline or not, and it seems that it's only possible to do that after the video has started playing (so it's already playing in fullscreen).

Could the "autoplay detection" feature be optional to avoid this issue on current iOS APPs that does not have the proper configuration?

@github-matthieu-wipliez
Copy link
Contributor

Could the "autoplay detection" feature be optional to avoid this issue on current iOS APPs that does not have the proper configuration?

Something I don't quite understand is that this feature has been part of the Teads ad player for years without any issues. Do you have the Teads adapter enabled by default but not configured? Is it playing any ads?

@aanton
Copy link

aanton commented May 7, 2024

Hi @github-matthieu-wipliez,

Something I don't quite understand is that this feature has been part of the Teads ad player for years without any issues. Do you have the Teads adapter enabled by default but not configured? Is it playing any ads?

We use the Teads adapter in our Prebid integration, but only with banner media types. After a recent upgrade of the Prebid version, this issue has appeared. It is related to the automatic "autoplay detection" recently added in

// starts detection as soon as this library is loaded
startDetection();

That code was not included in previous versions of the Teads adapter (I have looked for it in 8.36.0 version). About using the "Teads ad player", I am not sure about it. I don't know the resources used when Teads wins the auction and its creative is displayed. As I have commented, we only use the Teads adapter for banner media types.

Thanks for your help!

@lcorrigall
Copy link

Discussed in the PMC, and we should also add this situation to our documentation as other bidders may also run into this problem.

@github-matthieu-wipliez
Copy link
Contributor

Hi @github-matthieu-wipliez,

That code was not included in previous versions of the Teads adapter (I have looked for it in 8.36.0 version). About using the "Teads ad player", I am not sure about it. I don't know the resources used when Teads wins the auction and its creative is displayed. As I have commented, we only use the Teads adapter for banner media types.

Thanks for your help!

Hi @aanton, what I mean is that while the adapter did not include this code, the Teads ad player runs this code as soon as it starts, regardless of the media type. What did change though is that the video used to be fetched from an external URL, and was one frame long, whereas the new video is embedded and is 1 second long. I will try changing this and see if the video still opens.

Discussed in the PMC, and we should also add this situation to our documentation as other bidders may also run into this problem.

@lcorrigall Hi Luke, I'm not sure what documentation you're referring to, should this be part of the general Prebid.js guidelines?

@github-matthieu-wipliez
Copy link
Contributor

What did change though is that the video used to be fetched from an external URL, and was one frame long, whereas the new video is embedded and is 1 second long. I will try changing this and see if the video still opens.

I just tried, and same thing 🤷

@aanton
Copy link

aanton commented May 13, 2024

Hi @github-matthieu-wipliez.

In my opinion, in the current version the autoplay code always runs if the Prebid file includes the Teads bids adapter, but in the previous versions it didn't. In the previous versions (before 8.42.0), the Teads ad player was only included if the Teads bid was the winner bid in Prebid and, also, the ad server didn't have a better campaign to show (like a more expensive campaign).

So the problem always happens with the newer Prebid version (if it includes de Teads bi adapter) but in the previous versions it only happened in some cases (if the Teads creative was displayed).

@github-matthieu-wipliez
Copy link
Contributor

Hi @github-matthieu-wipliez.

In my opinion, in the current version the autoplay code always runs if the Prebid file includes the Teads bids adapter, but in the previous versions it didn't. In the previous versions (before 8.42.0), the Teads ad player was only included if the Teads bid was the winner bid in Prebid and, also, the ad server didn't have a better campaign to show (like a more expensive campaign).

That's right, from what I see there was no ad served on zimmo (in 2024), which could explain why you never noticed the problem.

@patmmccann
Copy link
Collaborator

@github-matthieu-wipliez : Luke is referring to the reference page on building a bidder https://docs.prebid.org/dev-docs/bidder-adaptor.html

@kohashi
Copy link

kohashi commented May 30, 2024

Hi everyone,

We are facing the same issue.

Our application, which has tens of thousands of iOS users in Japan, has been significantly impacted by this problem. We have confirmed that the changes made to autoplay.js from version 8.42.0 are the cause, and therefore we downgraded to 8.41.0.

It is not advisable to show full-screen videos to all users of an iOS app just to verify if autoplay is enabled. Please consider that in WKWebView, the default value for allowsInlineMediaPlayback is set to false.

And as far as I know, this trick works on iOS 16 and does not play the video, but it does play the video on iOS 17+.
Regardless whether allowsInlineMediaPlayback=false or true.

Thank you

@github-matthieu-wipliez
Copy link
Contributor

Hi @kohashi,

We are facing the same issue.

I'm sorry for the inconvenience. This library is opt-in, are you using the Teads adapter? Can you disable it? Or perhaps another option would be to use our inApp SDK?

It is not advisable to show full-screen videos to all users of an iOS app just to verify if autoplay is enabled. Please consider that in WKWebView, the default value for allowsInlineMediaPlayback is set to false.

My point is that if you integrate the Teads adapter, there's a good chance it will show you a video ad (as maybe 40% of our ads are videos), so you should have allowsInlineMediaPlayback = true to play video ads inline. Perhaps you did not notice this before if we never sent you an ad?

And as far as I know, this trick works on iOS 16 and does not play the video, but it does play the video on iOS 17+. Regardless whether allowsInlineMediaPlayback=false or true.

The video element is not added to the DOM, so the video is played but never shown. This autoplay detection has been part of our ad player for years without problem 🤷

Thank you

I hope I have answered your concerns.

Matthieu

@patmmccann
Copy link
Collaborator

Reproducing a few options here to gauge interest:

Screenshot_20240530-072806

@github-matthieu-wipliez
Copy link
Contributor

Thanks for the suggestions, I'll let the others comment. I have also opened a PR on the documentation of our adapter to state that we require playsinline: Add note for playinline for Teads adapter

@aanton
Copy link

aanton commented May 30, 2024

Hi @github-matthieu-wipliez. Let me share my point about your comment.

My point is that if you integrate the Teads adapter, there's a good chance it will show you a video ad (as maybe 40% of our ads are videos), so you should have allowsInlineMediaPlayback = true to play video ads inline. Perhaps you did not notice this before if we never sent you an ad?

In our case, we have been using 5 Prebid bidders (including Teads), TAM and GAM (with our own campaigns, its programmatic, ...) for a long time. The Teads winning rate is low (there are many competitors) so we did not notice the problem in previous Prebid versions. The impact was quite low.

@kohashi
Copy link

kohashi commented Jun 10, 2024

Hi @github-matthieu-wipliez,

This library is opt-in, are you using the Teads adapter? Can you disable it? Or perhaps another option would be to use our inApp SDK?

We manage ads for several websites, some of which are also offered as app versions.
These app versions primarily wrap the website using a WebView.

For management reasons, we use the same prebid.js across all sites and app versions.
Therefore, using the inApp SDK is not impossible but would be very cumbersome.
Our options are either to continue using Teads at version 8.41.0 or to exclude Teads in the future.

Currently, we have chosen to continue using Teads at version 8.41.0 without updating it.

My point is that if you integrate the Teads adapter, there's a good chance it will show you a video ad
The video element is not added to the DOM, so the video is played but never shown. This autoplay detection has been part of our ad player for years without problem 🤷

Our investigation and testing have identified this Pull Request, created on Mar 20 this year, as the cause of the issue.
While it seems strange to me as well that the video plays without being added to the DOM, you should ask the WebKit development team about this.

Regarding whether there were any issues before this, as @aanton mentioned, it is possible that the problem was not reported because Teads was not winning many bids on iOS apps.
However, about 70% of our traffic is web, 15% is Android, and roughly 15% is iOS app.

We are serious about wanting to keep the Teads module updated.
Please consider detecting allowsInlineMediaPlayback or making a different determination for iOS.
It may be a difficult request, but we sincerely ask for your help in resolving this issue.

@github-matthieu-wipliez
Copy link
Contributor

Hi @github-matthieu-wipliez,

Regarding whether there were any issues before this, as @aanton mentioned, it is possible that the problem was not reported because Teads was not winning many bids on iOS apps. However, about 70% of our traffic is web, 15% is Android, and roughly 15% is iOS app.

We are serious about wanting to keep the Teads module updated. Please consider detecting allowsInlineMediaPlayback or making a different determination for iOS. It may be a difficult request, but we sincerely ask for your help in resolving this issue.

Hi @kohashi,

it does not seem possible to detect if allowsInlineMediaPlayback is true or not from JavasScript. However, after spending some time to tweak the detection, I believe I found a way to stop the video before it appears in fullscreen. I'll update the detection on Teads' side and run an A/B test to be sure it works well at scale. Then I'll open a PR on Prebid.js with the update to the autoplay detection in Prebid.js. I'll keep you posted 👍

That said, as I said before in this thread, while this will fix the autoplay detection, having an app with a WebView using allowsInlineMediaPlayback = false means that if there is a video ad in your app, it will play in fullscreen (and I'm not sure this is something that is expected). But you can also exclude video from the kind of creatives you accept in your publisher configuration.

Matthieu

@kohashi
Copy link

kohashi commented Jun 12, 2024

Hi @github-matthieu-wipliez,

Thanks for the good information!
I will wait for an update post. Until then, We'll use with 8.41.0.
And I will try to update publisher configuration in prebid.js to see if It can prevent video bid requests being sent.
Thanks!

Kohashi

@github-matthieu-wipliez
Copy link
Contributor

Hi @kohashi,

I have opened a PR: #11822 with the fix that I've tested on my side.
Is there a way you could test it and see if it works for you as well?

Thanks,
Matthieu

@kohashi
Copy link

kohashi commented Jun 18, 2024

Hi @github-matthieu-wipliez,

Thanks for the update!
It seems like a great solution.
I tried it, and it works perfectly on iOS 17, but it still shows a black video on iOS 16.4 and iOS 16.2.
Your trick is literally a great solution, however, iOS 16.x still has a 10% market share.

Normally, I wouldn't be concerned with this share,
but if fullscreen black video appears for 10% of iOS 16- users, it's a different story.
(I mean, 10% people will get angry, i would say.)

Could you add code to exclude iOS 16 and below in your code?
Like this.

const isStandalone = window.navigator.standalone; // WKWebView: true, iOS Safari: false, other: undefined.
const isIOS = /iP(hone|od|ad)/.test(navigator.platform);
const match = navigator.userAgent.match(/Version\/(\d+(\.\d+)+)/);
const version = match ? match[1] : null;

const isUnderIOS17 = isStandalone === true &&  isIOS && parseInt(version) < 17);

if(isUnderIOS17){
     // iOS16- WebView, low share, but skip startDetection() due to possible fullscreen-video
     autoplayEnabled = false;
} else {
    // starts detection as soon as this library is loaded
    startDetection();
}

Another idea would be pbjs.setConfig.

pbjs.setConfig({
   disableAutoplayDetection: isUnderIOS17,
   // ...
})

Looking forward to your feedback!

Thanks,
Kohashi

@patmmccann patmmccann linked a pull request Jun 18, 2024 that will close this issue
1 task
@github-matthieu-wipliez
Copy link
Contributor

Hi @kohashi

thanks for your suggestion! I have tried it on the Simulator with my sample WebView on iPhone 16 and 17, it appears that navigator.standalone is not properly set in this context. I will instead rely on the absence of "Safari" in the user agent. Also, I have tried with iPadOS, but in this case it appears there is no way to detect the OS version by relying on the userAgent (it is the same "Intel Mac OS X 10_15_7" regardless of the underlying OS version 🤷

I'll keep you posted.

Thanks,
Matthieu

@github-matthieu-wipliez
Copy link
Contributor

Hi again, I have updated my PR accordingly, see this commit. In the case of iOS 16.x in a web view, autoplay detection is skipped, but autoplay will still be considered enabled (since typically 97% of users have autoplay enabled).

@kohashi
Copy link

kohashi commented Jun 20, 2024

Hi @github-matthieu-wipliez,

It looks almost perfect!
Great job!
Determining WebView on iPad is really difficult.
Even though we can determine iPad by the touch events exist or not, but we can't get the Safari version in WebView.

I can't think of a solution.
However, I have confirmed that the fullscreen video issue has solved on iPad OS 17+.

There will be issues with fullscreen videos in iPad 16-, but I believe that iPad users tend to use newer versions of the OS compared to iPhone users, so I want to incorporate this change.

Thanks for everything.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Development

Successfully merging a pull request may close this issue.

7 participants