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

Guidance required - how to implement diversity filtering when running native advertising in PAAPI with multi sellers and multi auctions #1199

Open
vladimanaev opened this issue Jun 10, 2024 · 20 comments

Comments

@vladimanaev
Copy link

Overview

We are in the middle of our live testing with the PAAPI, one of the challenges we have is to implement diversity logic.

Unlike display advertising, native advertising has several parts: title, description, image URL, and sometimes also a call to action.
Diversity is basically a filtering mechanism that enforces limits on the number of similar content that are coming from the same advertiser and has similarity in the assets details (e.g. title, description, thumbnail url, campaign id, item id) in order to create better user experience for our Publishers.

We are experiencing a challenge when trying to implement such logic into our framework using PAAPI. We have many auctions happening on the single page for a specific user, sometimes it can get to hundreds of auctions. Due to so many auctions we are performing those auctions in parallel else we won't manage to complete them all within a limited timeframe. In such a case we don't see a way to implement such diversity logic.

Few directions we imagined that might be possible are:

  • Creating some kind of lock mechanism during ScoreAd (or other) to allow sync between parallel running auctions on the same page for a specific user.

  • Perform an auction that returns a list of ads.

Can you please advise?

Relevant issues:

#792 ,#1074 , #1097

Thank you!

@michaelkleber
Copy link
Collaborator

Hi Vladi, interesting question.

Is this just about parallelization in auctions? That is, the prevWins field of an Interest Group already allows for an IG's bidding to be based on previous times that same IG has won an auction and shown the ad. Is that enough, and your only problem is that parallel auctions mean prevWins is not updated yet? Or are you trying to solve a more general problem in which you want to enforce diversity across ads coming from different IGs?

@vladimanaev
Copy link
Author

Hi Michael, sorry for late response.

The issues we see with prevWins are following

  1. It mark win item only after rendering which is too late for us when we performing parallel rendering (in Native there can be many items per single page, sometime it can get to more than 50 or even more) . Best would have been somewhere after ScoreAd once it is sent to rendering but before it is actually being rendered.
  2. We need to have full asset details of previous winning items (e.g. title, thumbnail, description, advertiser, campaign id, etc) to perform diversity logics
@michaelkleber
Copy link
Collaborator

Regarding 1, it certainly makes sense for us to have a faster mechanism for on-this-page winners. There would still be some risk of a race condition if two auctions were running at the same time, but the situation "won an auction on this page, even if it has not yet rendered" is definitely a condition we can cover.

Regarding 2, it would be much better if your "diversity logics" could be implemented by some sort of static declaration that we could use as a filter, rather than arbitrary JS code. Can you describe what kind of rules you want to be able to apply? The easiest thing I could imagine is each bid coming with a list of labels (e.g. ["nike.com", "campaign12345"]), and each ad having a static list of exclusion strings, where the ad is ineligible if any of its exclusions have previously appeared as the labels of winning bids on this page.

@vladimanaev
Copy link
Author

Regarding 2, static declaration idea is nice and generic but the diversity should be applied on a wider context of what is present on a page for the user not just specific protected audience interested group pool of ads so if it is something that we can apply broader it might work.

@MattMenke2
Copy link
Contributor

Are you sure prevWins is being updated only on render completion, rather than on nav start? While it would be a little more robust against incorrectly recording wins, we should be committing changes to our database when navigation starts, rather that only after the ad is fully loaded.

Note that if you start a navigation and an auction at the same time, the events are potentially racy, since they use two different IPC pipes, so may not see the previous win consistently, based on vagaries of the timing of the navigation and the database lookups for the new auction.

@michaelkleber
Copy link
Collaborator

michaelkleber commented Jun 20, 2024

@vladimanaev If this can be solved using static declarations, then I think we ought to be able to make it work pretty broadly:

  1. Any ad on the page should be able to register its own labels for future exclusions to take into account; and
  2. Any ad in a PA auction should be able to exclude itself based on those labels — that is, both ads coming from an Interest Group and ads passing through the auction as part of the Additional Bids mechanism.

As Matt says, there is still the risk of a race condition, if the addition of a label and the PA auction happen at nearly the same time.

@vladimanaev
Copy link
Author

@michaelkleber that can work as long as it provide a way count similarity and apply logic based on this counter, see my quote below.

Quote from original comment of mine:

... that enforces limits on the number of similar content that are coming from the same advertiser and has similarity in the assets details ...

@michaelkleber
Copy link
Collaborator

that can work as long as it provide a way count similarity and apply logic based on this counter

Okay, it sounds like that is the essential question! So let's discuss how you count similarity, and figure out what the browser would need to offer that would be enough for you to accomplish basically the same thing.

For example, imagine something like:

  1. Each winning ad contributes some collection of labels (just represented as strings), e.g. "campaign-id-12345", "shoes", "brand-manolo-blahnik".
  2. Each candidate comes with some set of labels and weights, e.g. {"shoes":1, "running-shoes":5}
  3. The exclusion rule is something like Do not participate in the auction of the sum of the weights of the labels that match anything else on the page is larger than 3

Could you express your exclusion goals in that language? If not, what's missing?

@eysegal
Copy link

eysegal commented Jul 1, 2024

@michaelkleber, we (@vladimanaev and I) thought about the following design:

A seller will define a diversity filter in the following schema:
[{name, limitation_count, method, mode]} where name is the label name, limitation_count is the number of allowed occurrences, method is either "le" (lexicographically equals) or a UDF implemented in JavaScript and mode defines if a buyer has to populate this field or not (otherwise the ad will be skipped).

Example:
[{name: "advertiser", limitation_count: 2, method: "le", mode: "mandatory"}, {name: "title", limitation_count: 1, method: someSimilarityJS(), mode: "optional"}]

A buyer is responsible to fill relevant fields per ad.

Example:
{"advertiser":"Example Advertiser", "title": "Example Title"}

  1. An ad won't go into generateBid if it violates the rule, but the global context should only be populated if an ad has won.
  2. We need to somehow define it for the contextual ads without using the additionalBids, so we would consider the rules for PAAPI ads in relation to the contextual ads.
@michaelkleber
Copy link
Collaborator

  1. I would prefer a solution that doesn't involve arbitrary JS, if possible. Filters that the browser can execute on its own involve dramatically fewer resources, and also much less privacy risk (since the similarity JS you mention would get to see ads based on data from many sites).
  2. I had been assuming that the way for contextual ads to use this exclusion mechanism would be via the additionalBids mechanism. Why are you hoping to avoid that?
@eysegal
Copy link

eysegal commented Jul 1, 2024

  1. Ok, is this something that already exists or should be developed for this?
  2. We examined the additionalBids mechanism for the scope of suppression and got to the conclusion that it won't work for us since:
  • We'll have to return a considerable high number of ads to avoid cases were a lot of ads are being filtered so we won't be able fill our placements. We estimate that to properly display 6 ads we'll have to return 60 ads to be on the safe side.
  • We have organic recommendations which appear side by side with the ads
  • Rendering in general is a lot more complicated using PAAPI. For example, in our feed widget, the first ad usually appears alone while the second and third ads appear side by side. This becomes even more complicated when we A/B test with UI variations.
  • It limits us in displaying ads in an optimal order (in relation to ecpm) as discussed here - Alternative way to implement negative targeting  #1096
  • And more...
@michaelkleber
Copy link
Collaborator

For 1. avoiding arbitrary JS, this is where I was hoping that your deduplication method was relatively simple, so that the "le" comparison that you proposed was one of only a few options. Maybe that was too optimistic of me! I guess the question is what other kinds of matching logic would you need?

For 2. additionalBids, unfortunately I don't see how we can avoid needing the PA privacy protections. Suppose a page first ran a few PA auctions, which populated the page's list of secret filter labels. Then each purely-contextual auction on the page would effectively let you learn some of the labels that were attached to the PA-chosen ads — and at that point it wouldn't be hard to just learn what ads were chosen by PA in the first place.

@eysegal
Copy link

eysegal commented Jul 2, 2024

  1. @vladimanaev - I'll appreciate your input here.
  2. This is not the flow we thought about. Contextual would always come before PA. We can have the global labels defined in a static way so there is no way to query it, just set a one-way current state and each PA auction should use it (and update when an ad wins), but would have no way of knowing what's the current state.
@michaelkleber
Copy link
Collaborator

Ah wait, let me see if I understand: Your goal is for purely-contextual ads to contribute their exclusion labels to the set of labels that describe ads already on the page in a write-only manner, and then to only have those labels used to remove ads from PA auctions? Sure, that seems fine.

Now let me ask something else that we've swept under the rug so far: What is the scope of these labels across different ad techs? That is, do labels from buyer1 affect future bids from buyer2? If so then there must be some agreed-upon taxonomy of label strings.

Also, does anything stop one ad tech (or one piece of JS code on the page) from flooding the list of exclusion labels, e.g. to keep its competitors from being able to run ads? Surely making your competition decide not to bid is a convenient way to buy more cheaply.

@eysegal
Copy link

eysegal commented Jul 2, 2024

Ah wait, let me see if I understand: Your goal is for purely-contextual ads to contribute their exclusion labels to the set of labels that describe ads already on the page in a write-only manner, and then to only have those labels used to remove ads from PA auctions? Sure, that seems fine.

Yes

Now let me ask something else that we've swept under the rug so far: What is the scope of these labels across different ad techs? That is, do labels from buyer1 affect future bids from buyer2? If so then there must be some agreed-upon taxonomy of label strings.

Yes, this is something we need to agree with our buyers. That's why we added the mode field. If a field is mandatory for us and the buyer hasn't provided it, its ad will be blocked.

Also, does anything stop one ad tech (or one piece of JS code on the page) from flooding the list of exclusion labels, e.g. to keep its competitors from being able to run ads? Surely making your competition decide not to bid is a convenient way to buy more cheaply.

Each buyer can only set one label per ad, e.g. one "title", one "advertiser", etc. Also, we don't expect our labels to affect Google Display and vice versa. Each seller should have a separate context of labels.

@michaelkleber
Copy link
Collaborator

Each buyer can only set one label per ad, e.g. one "title", one "advertiser", etc.

I'm not sure how the browser could enforce this along with your proposal that contextually-targeted ads can contribute to the set of labels. The browser doesn't know anything about non-PA ads, so any content on the page could say "I'm an ad with title X and advertiser Y", right?

Also, we don't expect our labels to affect Google Display and vice versa. Each seller should have a separate context of labels.

Hmm, interesting. I am not sure that buyers who buy through multiple supply channels will be happy with this answer.

And again this seems tricky to handle in the contextual-ad case. The browser doesn't know where different pieces of content on the page come from. I'm not sure how we could only allow Taboola contextual ads to contribute labels that would exclude Taboola PA ads, since there's no built-in way for the browser to know what contextual content really did come from Taboola.

@eysegal
Copy link

eysegal commented Jul 2, 2024

I'm not sure how the browser could enforce this along with your proposal that contextually-targeted ads can contribute to the set of labels. The browser doesn't know anything about non-PA ads, so any content on the page could say "I'm an ad with title X and advertiser Y", right?

Basically yes, but we imagined it that we'll have some kind of API to update it globally:
navigator.addAdConstraints(seller, json-representing-contextual-ad-constraints)
or maybe through auction-config, though then I don't know how we can add constraints, only set them, but I'm sure it's solvable - for example have us holding the global state and feed it into each auction. Need to think about race conditions, etc.

Hmm, interesting. I am not sure that buyers who buy through multiple supply channels will be happy with this answer.

It's happening today, so in any case we won't make things worse. From our experience, usually buyers don't have a problem with duplicated ads, it's publishers who don't want a bad UI experience and ad platforms (like us) who wants to maximize the opportunities.

And again this seems tricky to handle in the contextual-ad case. The browser doesn't know where different pieces of content on the page come from. I'm not sure how we could only allow Taboola contextual ads to contribute labels that would exclude Taboola PA ads, since there's no built-in way for the browser to know what contextual content really did come from Taboola.

Is this a security constraint (Taboola and Google interfere with one another) or a technical constraint?
If we define it in the auction-config instead of a global definition, would that work? I can still think of problems like if we render in different iframes and some race conditions, but it would probably be ok in most cases.
What do you think about navigator.addAdConstraints we defined above, where the seller is a mandatory parameter?

@michaelkleber
Copy link
Collaborator

My concern is that navigator.addAdConstraints('taboola.com', {...}) could be called by anyone on the page, not just by Taboola. I don't know who all the parties are that might want to interfere with your ad selection logic, but this seems to give pretty broad license to interfere. That makes it a worrying API design.

Hmm, interesting. I am not sure that buyers who buy through multiple supply channels will be happy with this answer.

It's happening today, so in any case we won't make things worse. From our experience, usually buyers don't have a problem with duplicated ads,...

I think we can try to do better than that. Are there any buyers out there following this conversation who would like to chime in? :-)

@eysegal
Copy link

eysegal commented Jul 3, 2024

My concern is that navigator.addAdConstraints('taboola.com', {...}) could be called by anyone on the page, not just by Taboola. I don't know who all the parties are that might want to interfere with your ad selection logic, but this seems to give pretty broad license to interfere. That makes it a worrying API design.

Through Auction config then? But then note that the result should be
restrictions_from_auction_config ∪ all_labels_from_all_auctions_winners_on_page_for_the_same_seller

We should probably support an enhancement where it's not necessarily global, where certain restrictions apply on the placement level.
So a better scheme is:
In auction-config, set a new field:
{scope_label, constraints:[{name, limitation_count, method, optional, scope}], contextual_labels: [{name, value}]} - Where optional is true/false (default true) and scope is either "global" (default) or "local" which is limited by the scope label.
[scope_label: "Below Article", constraints: [{name: "advertiser", limitation_count: 2, method: "le", optional: false, scope: "global"}, {name: "title", limitation_count: 1, method: "le", optional: true, scope: "local"}], contextual_labels: [{name: "title", value: "example title"}, {name: "advertiser", value: "example adv"}]

@eysegal
Copy link

eysegal commented Jul 9, 2024

@michaelkleber I'll appreciate your comments on the design proposal

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