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

Limit number of times a single bid can be rendered to address increasing number of poor Auto-Refresh implementations #6020

Closed
trex-conversant opened this issue Nov 23, 2020 · 10 comments · Fixed by #6707

Comments

@trex-conversant
Copy link
Contributor

Type of issue

Bug/ Feature Request

Description

Across multiple distinct publisher Prebid integrations, we see a high number of bids being re-rendered at a consistent interval, suggesting there is an issue with auto-refreshing ad slots. After investigating a sample of these publisher integrations, we see many of these publishers have not have implemented auto-refresh correctly, in some cases just calling the googletag.pubads.refresh() without getting new bids first. This is in part a publisher problem, but I thought the concept of a used bid would prevent this.

The majority of this problem is happening with re-renders that happen at 15s/30s/60s intervals, but I also see a good chunk that happen near immediately. We've seen, in the worst case, individual bids be rendered thousands of times as a result of this problem.

Looking at the discussion in this other issue (#4148), it seems like re-rendered ads is an undesirable behavior and others have seen similar behavior to what I've described here. Can additional protections be put in place to prevent this? There is certainly a lot of responsibility on the publisher's end to correctly implement auto-refresh, but we're seeing this across enough distinct publishers to believe this vulnerability should be addressed at the root.

Steps to reproduce

You can go to sites like https://www.jta.org/?pbjs_debug=true or https://www.klbjfm.com/?pbjs_debug=true and let the page run for a bit. You'll see that ads with the same adId get called to render on a timer. This will happen with ads from any demand source. Also, if you call googletag.pubads.refresh() with any of the ad slots, it will just re-render the ad.

Test page

https://www.jta.org/?pbjs_debug=true
https://www.klbjfm.com/?pbjs_debug=true

Expected results

Ideally, once an ad has been rendered, it would no longer be eligible to be rendered again.

Actual results

You can call renderAd on a bidId as many times as you want and the ad will continuously render.

Platform details

We see this happen on many versions of Prebid, not just the latest few.

@stale
Copy link

stale bot commented Dec 25, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Dec 25, 2020
@bretg bretg removed the stale label Jan 9, 2021
@bretg
Copy link
Collaborator

bretg commented Jan 9, 2021

When googletag.pubads.refresh() is called directly without removing the PBJS targeting, the same hb_ variables get re-sent to GAM, re-chosen, and re-rendered. Over and over without ever asking PBJS for updated targeting variables.

There aren't a lot of things we can do about this without getting pretty dramatic.

  1. make the documentation more clear as to which practices to avoid.
  2. have a Prebid background timer that flags adids as stale, from then on squelching their render and instead resolving to a blank pixel.

Escalating this to @gglas to lead the community discussion.

@gglas
Copy link

gglas commented Jan 11, 2021

I will escalate -- I get the feeling that the solution will be number 2 from above, possibly combined with the concept of bid auction eligibility as opposed to just doing it at the end of a render.

@trex-conversant
Copy link
Contributor Author

trex-conversant commented Jan 11, 2021

Hi @bretg, seems like we'd want to do both steps listed. I'm not certain of the latest way the GAM scripts work, but at some point it worked like:

  • Google would return a script that called pbjs.renderAd
  • Google fired an impression pixel.

If thats still the case (or even if they're doing server-side impression counting), it seems like this may cause discrepancies between Google Ad Manager counts and the DSP counts. This is a more fitting discrepancy since it kinda isolates the cause and effect (publisher calls GAM erroneously -> GAM discrepancy accrues). It'd be great if there was a solution that could mitigate this as well, but it's just something to be aware of. @gglas 's point gets at the same thing I think.

Edit: Thinking on it more, isolating this problem to GAM is undesirable unless there is some signal to know that an impression was attempted to render but did not due to impression-duplication prevention. At minimum a debug output might help to work through the discrepancies that would certainly occur between the publisher and DSP as a result. The best solution for this problem (if possible) wouldn't allow GAM the opportunity to count an impression in the first place.

@GLStephen
Copy link
Collaborator

GLStephen commented Jan 20, 2021

I would start with a heavy handed alert in the console. Then ramp up enforcement. This issue is trickier than it appears IMO. The simplest fix is to clear PBJS targeting on a GAM adunit after a GAM adunit is refreshed.

There is no (reliable) refresh event listener in GPT though, so the most obvious hook to "fix" this is not available. The reliability of tracking via a render event hook might be good enough. The googletag.events.SlotRenderEndedEvent https://developers.google.com/publisher-tag/reference#googletag.events.event could work, but might only work if it renders something.

The timer based squelch may interact with valid instances of requesting a bid. Many TTLs for display are inside the troublesome window.

Whatever the solution, it would be good to implement this as a notice/error first so we can sort out instances of people getting enforcement in situations we didn't predict.

@trex-conversant
Copy link
Contributor Author

Hi everyone, just trying to get a sense for where this stands. Is there a general timeframe for addressing this and is there anything else I can do to drive it forward? Thanks

@gglas
Copy link

gglas commented Feb 26, 2021

hey @trex-conversant -- I think we have a number of good ideas in the thread, but I'm aware that most engineering resources on our side are tied up with other projects within Prebid. I do think we have teams who could help with speccing out the solution, are there any engineering resources on your side we could collaborate with for delivery?

@bretg
Copy link
Collaborator

bretg commented Feb 26, 2021

Whoever decides to take a stab at this code, here are some suggested requirements:

  1. Any initial solution should be opt-in. i.e. no immediate change in page behavior. A Javascript console error would be good.
  2. The opt-in signal should be pbjs.setConfig({auctionOptions.suppressStaleRender}), which initially defaults to false. We may change the default to true in a future release.
  3. It might be useful to create a PBJS event for "onStaleRender" in case the publisher wants to create a function that can backfill the adslot. Otherwise it'll just be blank.

@patmmccann
Copy link
Collaborator

patmmccann commented Mar 22, 2021

RE no. 3 above, this event could also be listened to by analytics adapters

@patmmccann
Copy link
Collaborator

Adding feature request and help wanted flags, will be prioritized at a later date.

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

Successfully merging a pull request may close this issue.

6 participants