The base URL for the serving API is srv.buysellads.com. HTTPS is supported and its use is encouraged.
Zone Key:
A zone key is a unique identifer that we use to serve ads a zone
Segment:
Segments can be used to add custom demographics to your traffic, which can then be used further when setting up custom targeting for ads.
For example, a blog with a "technology" category could have a segment passed to the ad server as category:technology. When setting up a campaign, one could add the category:technology segment to the campaign's targeting, requiring the campaign to only be displayed when this segment is present.
When using a segment as part of a campaign's targeting, additional segments are allowed - any single segment that matches will allow the ad to serve. For instance, if you have a campaign targeting category:technology and category:computers, it would be allowed to serve even if the only segment attached to the serving call is category:computers.
There are a few API calls available, but the one that suits most cases is /ads/<zonekey>.<format>.
For the purpose of getting familiar with the data returned by the API, you can use the zonekey CKYD623L, which we have set up as a demo.
Behavior:
This API call returns N ads, up to the maximum number of ads specified in the zone's configuration. It will track an impression for each ad, as well as a single zone hit for the zone in question.
Formats allowed:
Supported parameters:
A full serving request URL might look like:
https://srv.buysellads.com/ads/CKYD623L.json?ignore=yes&segment=category:bitcoin;category:ethereum&forwardedip=207.241.225.186Effectively, it would tell the ad server to:
The response to this request might look like:
{
"ads":[
{
"active":"1",
"backgroundColor":"#cf215b",
"backgroundHoverColor":"#cf215b",
"bannerid":"72986",
"callToAction":"Learn more!",
"company":"Slack",
"creativeid":"154224",
"ctaBackgroundColor":"#0089ee",
"ctaBackgroundHoverColor":"#036dbf",
"description":"Where work happens. All the tools your team needs in one place.",
"evenodd":"0",
"height":"0",
"i":"0",
"image":"https://cdn4.buysellads.net/uu/1/33/1504895696-Slack_80x80.png",
"logo":"https://cdn4.buysellads.net/uu/1/63/1508205679-35252.png",
"longimp":"TDJQPZLBTTTTTTCBXYUMWTTTTTTZ35QKZVTTTTTTYDJLANETTTTTT",
"longlink":"TFJQPZLBTTTTTTCBXYUMWTTTTTTZ35QKZVTTTTTTYDJLANETTTTTTBDW5JYFC5JGHR7NYYZD2KUCCSS2HRNFT",
"rendering":"fancybar",
"statimp":"//srv.buysellads.com/ads/imp/x/GTND42QJCKYDTKJWCYS4YKQMC67IT5QWFTSIVZ3JCWYI653YCTBIKK3KC6BI4K7ECV7DVK3EHJWNBADLKM7UCBZG2Y",
"statlink":"//srv.buysellads.com/ads/click/x/GTND42QJCKYDTKJWCYS4YKQMC67IT5QWFTSIVZ3JCWYI653YCTBIKK3KC6BI4K7ECV7DVK3EHJNCLSIZ/ignore/yes",
"textColor":"#ffffff",
"textColorHover":"#ffffff",
"timestamp":"1513024726",
"title":"Slack",
"width":"0",
"zoneid":"30242",
"zonekey":"CKYD623L"
},
{
}
]
}
The most important parts here are the values used for displaying the campaign's ad.
For tracking clicks to campaigns, you must use the "statlink" value that is returned. Note that when using the "ignore" parameter, this will be appended to the "statlink" value. In order for clicks to be tracked, this parameter must be removed from the /ads/click/x/<value> link.
Very important: If no "statlink" parameter exists within the response, then there are no ads to serve for the current request.
Any ad within the response may contain a "pixel" key. Pixels must be dropped in to the page when present. Multiple pixels are allowed, and will be separated by two pipes (||).
To prevent caching, the string [timestamp] within the pixel URL must be replaced with the current time. An example of doing this is below.
Here's how we use pixels in our wrapper:
var time = Math.round(Date.now() / 10000) | 0;
if (typeof ad.pixel != 'undefined')
{
var pixels = ad.pixel.split('||');
for (var j = 0; j < pixels.length; j++)
{
var pix = document.createElement('img');
pix.src = pixels[j].replace('[timestamp]', time);
pix.border = '0';
pix.height = '1';
pix.width = '1';
pix.style.display = 'none';
el.appendChild(pix);
}
}
Frequency caps must be tracked in your implementation.
A frequency capping string should look like:
<banner ID>:<today's impressions>,<lifetime impressions>
Multiple frequency caps can be present, and will be separated by a semicolon ;:
<banner ID>:<today>,<lifetime>;<banner ID 2>:<today 2>,<lifetime 2>
Using the banner ID from the example response illustrated above, assume the user has seen this ad 2 times today, and 30 times total:
72986:2,30
The easiest way to track these long-term is by setting a cookie for the user, and updating it when ads have displayed.
A full serving request URL might look like:
https://srv.buysellads.com/ads/CKYD623L.json?freqcap=72986:1,1;72987:5,300
Here's a sample function you might use for frequency capping:
window['_bsap_serving_callback'] = function(banner, zone, freqcap) {
var append = function(w, data, days) {
var c = document.cookie,
i = c.indexOf(w + '='),
existing = i >= 0 ? c.substring(i + w.length + 1).split(';')[0] + '%2C' : '',
d = new Date();
d.setTime(days * 3600000 + d);
data = existing + data;
data = data.substring(0, 2048);
document.cookie = w + '=' + data + '; expires=' + d.toGMTString() + '; path=\/';
};
if (freqcap) {
append('_bsap_daycap', banner, 1);
append('_bsap_lifecap', banner, 365);
}
};
// we check for a frequency cap here and if we find one make
// the call to the Ad Server API with the additional info
var ck = '';
try { ck = decodeURIComponent(document.cookie) } catch (e) {};
var day = ck.indexOf('_bsap_daycap='),
life = ck.indexOf('_bsap_lifecap=');
day = day >= 0 ? ck.substring(day + 12 + 1).split(';')[0].split(',') : [];
life = life >= 0 ? ck.substring(life + 13 + 1).split(';')[0].split(',') : [];
if (day.length || life.length) {
var freqcap = [];
for (var i = 0; i < day.length; i++) {
var adspot = day[i];
// using an array here is ugly, but safer cross-browser than for(var i in...) from an obj
for (var found = -1, find = 0; find < freqcap.length && found == -1; find++)
if (freqcap[find][0] == adspot) found = find;
if (found == -1) freqcap.push([adspot, 1, 0]);
else freqcap[found][1]++;
}
for (var i = 0; i < life.length; i++) {
var adspot = day[i];
// using an array here is ugly, but safer cross-browser than for(var i in...) from an obj
for (var found = -1, find = 0; find < freqcap.length && found == -1; find++)
if (freqcap[find][0] == adspot) found = find;
if (found == -1) freqcap.push([adspot, 0, 1]);
else freqcap[found][2]++;
}
for (var i = 0; i < freqcap.length; i++)
freqcap[i] = freqcap[i][0] + ':' + freqcap[i][1] + ',' + freqcap[i][2];
if (freqcap.length) pro.src += '&freqcap=' + encodeURIComponent(freqcap.join(';'));
}