prebid / Prebid.js

Setup and manage header bidding advertising partners without writing code or confusing line items. Prebid.js is open source and free.
https://docs.prebid.org
Apache License 2.0
1.33k stars 2.09k forks source link

Initializing userid module with config requires manual refresh of ids once config is updated #12104

Open coreyb-cbs opened 3 months ago

coreyb-cbs commented 3 months ago

Type of issue

bug

Description

User ids are not present in bid requests on 247sports.com most of the time. I am seeing the user ids present in the bid requests very infrequently, like every few days for one or two page reloads. This is working as expected 100% of the time on some of our other properties (comicbook.com, insideedition.com, cbssports.com for example) with the same implementation. The user ids are present in the userSync config (pbjs.getConfig().userSync.userIds), but not in the Prebid userIds object (pbjs.getUserIds()).

Steps to reproduce

  1. go to https://247sports.com/?pbjs_debug=true
  2. filter the console by "requested" and drill into an individual bid and notice that the userId object is not present
  3. execute pbjs.getConfig().userSync.userIds in the console to see that the userSync config is set properly
  4. execute pbjs.getUserIds() to see an empty prebid userIds object

Expected results

If the userSync.userIds config is set, there should be a userId object in the bid requests and running pbjs.getUserIds() should produce a non-empty object.

Actual results

There is no userId object in the bid requests.

dgirardi commented 3 months ago

That site appears to work as expected for me.

image

Here's some things that might affect user IDs:

coreyb-cbs commented 3 months ago

@dgirardi Thanks for your reply. I'm not sure your screenshot is from 247sports.com as we don't have any of those user ids enabled and we don't have Criteo as a bidder. I'm aware first page load usually doesn't have user ids, but this has been every page load for a while now - I'm just simply not seeing user ids 99% of the time.

We have a 500ms auction delay set. I tested out 5000ms and 10000ms and am still not seeing user ids present.

We have Optanon consent CMP on all Paramount properties. I thought of that and verified that consent is true (visible in the console logs) so that's not gating this.

dgirardi commented 3 months ago

You are correct, I managed to look at the wrong site - I apologize! And I do see the issue on the correct one.

I think the issue is that user IDs are not automatically picked up if they are configured multiple times (which I'm not sure if it's a bug or intended behavior). I see multiple calls to setConfig({userSync: {userIds: [...]}}}), where the first one has an empty userIds array.

A workaround is to call pbjs.refreshUserIds() after updating configuration: image

coreyb-cbs commented 3 months ago

@dgirardi Thanks for your assistance here.

  1. Our internal module that handles setting the user ids calls setConfig on each id as we process it (we loop through an internal identity config). Is that a problem to call setConfig on each individual user id?
  2. I tried calling refreshUserIds after we complete setting the pbjs user ids config, but they still are not present as this all seems to occur after the bid request has already gone out.
  3. I have an auctionDelay set to 500 but that's not solving it. Just to test it out, I tried an auctionDelay of 5000 locally but still I see the user ids updating after the bid requests go out.

Is there a way to force the processing of the user ids before the bid requests go out? The auctionDelay doesn't seem to do it, but I was hopeful.

dgirardi commented 3 months ago

The first call to setConfig with a non-null userSync.userIds triggers initialization of userID. So if the first call has an empty list of userIds, we consider them good to go and the auction does not need to wait for auctionDelay (we have all the IDs already - all 0 of them).

refreshUserIds called after the last setConfig and before requestBids should "reset" auctionDelay. I verified this locally, but I'm having trouble trying it on your site as it's heavy enough to crash my debugger.

If you are adding ids one at a time, you could also refresh each one individually as you go:

pbjs.mergeConfig({
   userSync: {
      userIds: [{
          name: 'someIdModule',
          ...
      }]
   }
});
pbjs.refreshUserIds({submoduleNames: ['someIdModule']})

Is there a way to force the processing of the user ids before the bid requests go out?

You can wait (for an indefinite time) until all IDs have been refreshed before starting auctions:

pbjs.refreshUserIds().finally(() => {
   pbjs.requestBids(...)
})
patmmccann commented 3 months ago

It seems the solution may be to not call setConfig until your loop s over?

patmmccann commented 3 months ago

Some options: we could try and issue more prominent documentation about not calling setconfig in a loop like this, or initializing setConfig and then later not calling refresh, we could autorefresh ids after a short delay if config changes and the refresh is not called, or we could add autorefresh on config change to prebid 10.

coreyb-cbs commented 3 months ago

@dgirardi How are you monitoring the calls to setConfig? I'm not seeing a call with a non-null userSync.userIds. Part of my confusion here is that the same implementation works well on all our other properties (comicbook.com, insideedition.com, cbssports.com for example), but not on 247sports. If you have a moment could you take a look at https://www.insideedition.com/?pbjs_debug=true to see if you notice any differences? I'm seeing user ids consistently included in the bid requests there and core code that handles consent, user id configs, bid requests, gpt, etc are identical. Thanks!

@patmmccann Thanks for the suggestions and ideas for future-proofing. I've tried calling refreshUserIds after each id is set in the config but that doesn't work. I'll see about only setting the config once, but again this same implementation is working elsewhere for us so I'm stumped as to why it's behaving different on 247sports.

dgirardi commented 3 months ago

I am using a debugger, looking at configuration coming into userId, and I don't see any difference - the first call has an empty userIds, and no ids are included in requests:

image image

dgirardi commented 3 months ago

Actually - the above is with Firefox. With chrome the first call has all (or maybe some?) of the IDs:

image

That is not the case on 247sports:

image

I think this might be a race condition - 247sports is a much heavier website, and it's possible that the configuration logic runs in a different order (also affected by the browser).

coreyb-cbs commented 3 months ago

I think this might be a race condition - 247sports is a much heavier website, and it's possible that the configuration logic runs in a different order (also affected by the browser).

Agreed that this seems like some sort of race condition. CBS Sports is a heavy site as well, but user ids are usually present in the bid requests there, might be a better means of comparison. I'm wondering if consent is hanging things up on 247 Sports - it's initially set to false until we process Optanon data and then we trigger the setting of the user ids when consent is true. It seems like this is perhaps happening after the bid requests have already gone out on 247...

patmmccann commented 3 months ago

Committee discussion result: we should add the auto-id-refresh-on-config-change feature behind a flag, and make it default in 10.

dgirardi commented 3 months ago

Proposal: