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.08k forks source link

Custom renderer for Criteo RTA #153

Closed BartVB closed 8 years ago

BartVB commented 8 years ago

This issue was prompted by: https://github.com/prebid/Prebid.js/issues/140#issuecomment-166663053

The Criteo tags are fairly simple:

   document.MAX_ct0 ='INSERT_CLICK_URL';
   var m3_u = (location.protocol=='https:'?'https://cas.criteo.com/delivery/ajs.php?':'http://cas.criteo.com/delivery/ajs.php?');
   var m3_r = Math.floor(Math.random()*99999999999);
   document.write ("<scr"+"ipt type='text/javascript' src='"+m3_u);
   document.write ("zoneid=328667");
   document.write ('&amp;cb=' + m3_r);
   if (document.MAX_used != ',') document.write ("&amp;exclude=" + document.MAX_used);
   document.write (document.charset ? '&amp;charset='+document.charset : (document.characterSet ? '&amp;charset='+document.characterSet : ''));
   document.write ("&amp;loc=" + escape(window.location).substring(0,1600));
   if (document.context) document.write ("&context=" + escape(document.context));
   if ((typeof(document.MAX_ct0) != 'undefined') && (document.MAX_ct0.substring(0,4) == 'http')) {
       document.write ("&amp;ct0=" + escape(document.MAX_ct0));
   }
   if (document.mmm_fo) document.write ("&amp;mmm_fo=1");
   document.write ("'></scr"+"ipt>");

The main complexity is that RTA returns a zone name but uses a zone ID in the tag. These two seem to be linked one on one. I.e. in my case when Criteo returns 'zone72890' I am supposed to load the above tag with zone ID '328667'. The size of the zone is also fixed per zone.

So the main things that are needed:

So changing this:

            {
                bidder: 'criteo',
                params: {
                    nid: '4909',
                    cookiename: 'cto_rtt',
                    varname: 'crtg_content'
                }
            }

to:

            {
                bidder: 'criteo',
                params: {
                    nid: '4909',
                    cookiename: 'cto_rtt',
                    varname: 'crtg_content'
                    zones: [['zone72890', '328669'], ['zone72890-2', '328670']]
                }
            }

Should do the trick. The custom renderer should check the content of the 'keys' array to match the first zone name that's present in the 'zones' array for that adUnit and render the tag accordingly.

This would work in my setup, but N=1... I'm currently running a test with four zones; two sizes and two audience segments. I'm currently using DFP to match the segments, I would need to move that to the Prebid code if I wanted to use the custom renderer. Not a big deal in my specific case.

cwbeck commented 8 years ago

@BartVB where do you get the NID from? I'm unable to reference that from the tag?

BartVB commented 8 years ago

@cwbeck Criteo has several products for publishers. The default setup is the 'Publisher Marketplace' which allows you to create JS ad tags with corresponding passbacks. They also have 'RTA' which is their attempt at header bidding. You'll need your account manager to set you up. Their onboarding process is quite elaborate, took me a week to get everything properly setup, tested and approved. Still in the process of optimizing but I'm not that impressed so far.

cwbeck commented 8 years ago

@BartVB thanks for the info. We are not having much luck with them so far. I've been unable to get much info out of them regarding the header bidding setup. They are still trying to force waterfall tags on us!

BartVB commented 8 years ago

Of course they do. It's much, much easier to setup, they see 100% of traffic (if you set this up according to their docs) and they can cherrypick traffic/users.

They big (BIG) disadvantage of RTA is that they only signal if they want the impression. They don't do an actual bid. This means you still need to work with average CPMs. I'm also using RTA in conjunction Cirteo through AdX RTB which also complicates matters. But we are really getting offtopic here :)

baragona commented 8 years ago

Hello, consider this a sort of brainstorming session / request for comment. I am planning on implementing this stuff soon. Please let me know if this design will help you or cause problems, or if you have better ideas!

So let's say the CPM for criteo is pre-negotiated (it is for my case). Then we just need to send in the right value to the adapter, so it can put the right value in the bid object. Like this:

            {
                bidder: 'criteo',
                params: {
                    nid: '4909',
                    cookiename: 'cto_rtt',
                    varname: 'crtg_content'
                    zones: [['zone72890', '328669'], ['zone72890-2', '328670']],
                    constantCpm: 1.2345
                }
            }

Also, we should probably tell prebid.js the w&h of each zone, but at that point the zone has 3 properties, so lets make them objects instead:

            {
                bidder: 'criteo',
                params: {
                    nid: '4909',
                    cookiename: 'cto_rtt',
                    varname: 'crtg_content'
                    zones: [{name: 'zone72890', id: 328669, width: 728, height: 90}, {name: '160600-1', id: 328670, width: 160, height: 600}],
                    constantCpm: 1.2345
                }
            }

Also, in my case, each zone id will correspond to its own ad unit, so it would look a little more like this :

            {
                bidder: 'criteo',
                params: {
                    nid: '4909',
                    cookiename: 'cto_rtt',
                    varname: 'crtg_content'
                    zones: [{name: '160600-1', id: 328670, width: 160, height: 600}],
                    constantCpm: 1.2345
                }
            },
            {
                bidder: 'criteo',
                params: {
                    nid: '4909',
                    cookiename: 'cto_rtt',
                    varname: 'crtg_content'
                    zones: [{name: 'zone72890', id: 328669, width: 728, height: 90}],
                    constantCpm: 2.1234
                }
            }

So in this case, the adapter should still make just one request to criteo (per NID, they are the same here), but when processing the results, create bids for the ad units with the matching zones. Also the constantCpm could be different.

The previous use case of multiple zones per adunit would still be supported.

BartVB commented 8 years ago

I would make that: zones: [{name: 'zone72890', id: 328669, size: [728, 90], cpm: 2.12}],

With Criteo RTA it's possible to set a different CPM per zone.

baragona commented 8 years ago

Also, what would be the best way to handle click urls? Without any other suggestions I would probably just put in in the same bid params object.

baragona commented 8 years ago

Actually, I do not think supporting multiple zones per adunit makes sense. The adapter will populate the .ad property of the adResponse with criteo's ad code html. But if multiple zones got a positive response from criteo, for one adunit, it would not know which zone to use for the adcode!

baragona commented 8 years ago

Having multiple adResponses per-adunit also is problematic, because the bidmanager needs to know how many responses are expected so it can fire the callback at the correct time.

baragona commented 8 years ago

This code seems to work okay. (The ads render, and it seems to handle no-bid responses okay.)

Instead of a 'zones' property, it takes a 'zone' property for a single zone object. Reasons stated above. (When a bid comes back and html is generated, there can't be two zone id's to pick from)

Will be trying this code in production soon.

baragona commented 8 years ago

Example bid object:

                            {
                                bidder: 'criteo',
                                    params: {
                                        nid: '495777',
                                        cookiename: 'crtg_rta',
                                        varname: 'crtg_content',
                                        zone: {name: '72890-1', id: 35431333, width: 728, height: 90, cpm: 2.5}
                                    }
                            }
baragona commented 8 years ago

Update: been running this code in production for the last 5 days. Results look good so far.

lminarini commented 8 years ago

hey guys, can you tell me where exacly do I get the NID on RTA's tag? I'm planning to ask my account manager to set me up RTA only for perform header bidding. And I'm not 100% sure how to get this value (nid).

baragona commented 8 years ago

They should send you a PDF, there will be a section called Header Script, there will be some code in there... you should see a line like this near the top of that script:

var crtg_nid = '12345';

That number is your NID.

lminarini commented 8 years ago

hey guys, first I'd like to thank all of you for the help. So, I've talked to my account manager here in Brazil and she told me that Criteo's RTA (at least here in Latin America) doesn't work at all with header bidding. She explained to me that neither of the Criteo's tools (RTA nor PuMP) are capable of making bids. So I've came back here to make sure that anyone in LATAM that's trying to manage header bidding with Criteo doesn't have to pass through the same as I haha.

prebid commented 8 years ago

Thanks everyone for the help. Archiving this issue for now until new official support from Criteo are more clear.