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

Update Criteo bid adapter to Prebid 1.x #2370

Merged
merged 35 commits into from
May 24, 2018

Conversation

Spark-NF
Copy link
Contributor

@Spark-NF Spark-NF commented Apr 9, 2018

Type of change

  • New bidder adapter
  • Official adapter submission

Description of change

  • Test parameters for validating bids
{
    code: '...',
    sizes: [[300, 250], [728, 90]],
    bids: [{
        bidder: 'criteo',
        params: {
            zoneId: 497747
        }
    }]
}

Other information

  • The old Prebid 0.x adapter can be found here on the legacy branch

'amp': 1,
};
const PROFILE_ID = 207;
const PUBLISHER_TAG_URL = '//static.criteo.net/js/ld/publishertag.prebid.js';
Copy link
Member

@mkendall07 mkendall07 Apr 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@mkendall07
Copy link
Member

@Spark-NF
Not seeing any test bid responses. Anything I need to do to get that to work?

@mkendall07
Copy link
Member

request:

http://bidder.criteo.com/cdb?ptv=48&profileId=207&av=4&cb=59440494674

Response

{"exd":{"genimpids":["5acfb1914eb96c31e554aa689b681713"],"slots":[{"imp_id":"5acfb1914eb96c31e554aa689b681713","ad_unit_id":"div-gpt-ad-1460505748561-0","zone_id":497747}]}}

try {
const fastBid = localStorage.getItem('criteo_fast_bid');
if (fastBid !== null) {
eval(fastBid); // eslint-disable-line no-eval
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there an alternative to using eval here? What's being done?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our adapter relies on an external script (publishertag.js). Once loaded for the first time we put it into the local storage and eval it during the next calls to not reload it from the network and have a better performances.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very interesting. Going to discuss with the prebid team

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about this some more, I don't think this is safe since you are blindly reading in content from localStorage, which can be overwritten by any script on page. Please remove.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed by mail the is the only way we can store our library in the local storage and then reuse it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ahubertcriteo
Do you have any stats that show this is faster than a modern browser caching of the parsed code? It doesn't really make sense to eval (parse) it twice.

Copy link
Contributor Author

@Spark-NF Spark-NF May 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we made a lot of testing with our publishers, and results are very positive.

The time between the call to buildRequests/callBids and the call to the PublisherTag entry point (in this adapter new Criteo.PubTag.Adapters.Prebid) was reduced by 80 to 95%, going from a few hundreds milliseconds (sometimes more than 1s depending on the publisher) to a few milliseconds (usually around 10ms).

The number of timeouts as detected by Prebid was also halved.

Even if the file was cached by the browser, the fact that we're simply adding a <script> causes it to have a pretty low priority in the loading chain. Plus, it's asynchronous as opposed to the localStorage that is synchronous (and fast).

If you'd rather have the localStorage.setItem more explicit, we can update the adapter to do so. However, we'd need an API to do a GET and return the file's contents (the ajax one seems like it could do the job).

window.criteo_prebid_native_slots[id] = { callback, payload };

// The creative is in an iframe so we have to get the callback and payload
// from the parent window (doesn't work with safeframes)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you have a postMessage solution that would work in safeFrames?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe, we will study this possibility and push it in a second iteration if feasable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's fine


// Reload the PublisherTag after the timeout to ensure FastBid is up-to-date and tracking done properly
setTimeout(() => {
loadScript(PUBLISHER_TAG_URL);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are going to update this function signature to include module/bidder code so we can track who is loading external JS. Will reply shortly with the changes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ahubertcriteo @Spark-NF
Please use loadExternalScript method instead.
This will enforce a whitelist of which adapters are allowed to load external JS:
https://github.com/prebid/Prebid.js/blob/master/src/adloader.js#L9

import { parse } from 'src/url';
import * as utils from 'src/utils';

var events = require('src/events');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prefer const.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will be remove if we remove the event listenening below.


registeredEvents = true;

events.on(EVENTS.BID_WON, (bid) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we currently have a policy that bidder adapters cannot consume internal prebid.js events. You'll need to remove these event listeners.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Can I ask what is the rational of this policy?
  • On our side we wanted to track those events to help publishers with their integrations when they encounter a lot of timeouts
    (some of them have inconsistencies in their timeouts configuration between the one passed in requestBids call and the one in the global setTimeout)
  • As documented here (http://prebid.org/dev-docs/publisher-api-reference.html#module_pbjs.onEvent), can we replace the call to "events.on" by onEvent ?
  • If not what would be the right alternative way to collect those informations ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reason is that we don't want vendors inspecting other vendor bids. I realize that you are not doing that but we want to make this preventable in the code.

The correct way is not fully implemented yet, but you could start with spec.onTimeout function.
http://prebid.org/dev-docs/bidder-adaptor.html#registering-on-timeout

Other events can be added to the spec in a separate PR if desired. Thanks

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will remove this and use the onTimeout instead for the timeout event.
However we wanted to catch those events to spot publishers with timeout issues (inconsistencies between the timeout given in requestBids and the global one triggering dfp). Have you solutions on your side which will allow the bidders to known which timeout will be triggered first ?

@mkendall07
Copy link
Member

@Spark-NF @ahubertcriteo
If you can make the requested changes (drop eval and event) we can merge this for now and work on further enhancements in new PRs.

In some cases, the buildCdbRequest function might return a falsy value,
in case of error in creating the request or if we know in advance that
this request will return a no-bid.

In this case, the buildRequests() method should not return a request,
causing a no-bid.
@bretg
Copy link
Collaborator

bretg commented May 4, 2018

@Spark-NF and @ahubertcriteo - any further progress on this PR?

@cwbeck
Copy link

cwbeck commented May 22, 2018

Would be nice to get this merged in...

@mkendall07 mkendall07 merged commit ad1507b into prebid:master May 24, 2018
@benjaminclot
Copy link
Contributor

How did this get committed with eval still there? 🙁

@piwanczak
Copy link
Contributor

How about the convention "No loading of external libraries: All code must be present in the adapter, not loaded at runtime."?
Should it be signed as redundant?

@benjaminclot
Copy link
Contributor

@mkendall07 Are you going to enforce rules on this adapter or is Criteo going to get a free pass?

@mafaigna
Copy link

mafaigna commented Jun 6, 2018

Dear @benjaminclot , @piwanczak ,

Thank you for your interest in Criteo Direct Bidder.

On the question above (usage of external library), Criteo follows the policies put in place by Prebid.org. Our adapter indeed makes use of our external library, so as to ensure that you can smoothly benefit from some of our latest updates. In doing so, we are following a review process from Prebid.org and comply with the the instructions and policy described by Prebid’s external JS repository mechanism (see link). Would you have any question, feel free to reach out your Criteo representative.

On Fastbid/eval: the function is being used to ensure correct working of our adapter in Prebid 1.0 and doesn’t represent a risk per se. In parallel, we are working on alternative versions, which will soon be submitted to our Prebid repo. In the meantime, would you have any concern, please contact your Criteo representative so as to address it.

Kind regards,
Maxence

@piwanczak
Copy link
Contributor

@mkendall07 Could you please state the official approach by Prebid team?
My key points are:

  • I've seen a few external js used in the branch 0.X, but only Criteo in 1.X
  • prebid-js-external-js-template seems pretty lonely with 14 watches and zero stars. This seems to point that it's nowhere to be found in official Prebid docs
  • on the contrary - official docs forbid external JS's in adapters
  • non-minified extenal code seems not-up-to-date or unavailable:
    https://github.com/Prebid-org/prebid-js-external-js-criteo/blob/master/dist/prod.js returns 404

As I strongly believe in "open" in opensource I feel it would be great for everyone to know the very same thing and be able to use the same tools.

@mafaigna Thank you for your input. Unfortunately this does not answer my question. I'm glad to hear that you work on alternatives, though.

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

Successfully merging this pull request may close these issues.

None yet

9 participants