Created
August 19, 2016 18:55
-
-
Save kasparsd/8c14bf83d5c9d98d860988cc29ffa901 to your computer and use it in GitHub Desktop.
Source code of the Headerbid Expert Chrome extension
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<body> | |
<script src="bidderPatterns.js"></script> | |
<script src="background.js"></script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Authors: julien delhommeau | |
* Description: chrome extension background.js file | |
* used to filter ad calls and look for known patterns for both prebid and class 1 ad servers | |
**/ | |
// class 1 ad server and urls patterns to look for for each known tag types | |
// var class1Ads = [ | |
// {name: "OAS", shortName: "O", tagTypes: [{name: "MJX", patterns: ["\/4\/.*@", "RealMedia/ads/adstream_mjx.ads"]}, {name: "JX", patterns: ["\/3\/.*@", "RealMedia/ads/adstream_jx.ads"]}, {name: "SX", patterns: ["\/2\/.*@", "RealMedia/ads/adstream_sx.ads"]}, {name: "DX", patterns: ["\/jp\/.*@"]}]}, | |
// {name: "DFP", shortName: "D", tagTypes: [{name: "GPT", patterns: ["g\.doubleclick\.net\/gampad\/ads\?"]}]}, | |
// {name: "Smart", shortName: "S", tagTypes: [{name: "Standard", patterns: ["www6.smartadserver.com//ac?"]}]}, | |
// {name: "AdTech", shortName: "A", tagTypes: [{name: "Standard", patterns: ["adserver\.adtech\.de\/addyn", "adserver\.adtechus\.com\/addyn"]}]} | |
// ]; | |
/* { | |
'.adnxs.com/jpt': 'appnexus', | |
... | |
} | |
*/ | |
var patternsToBidders = {}; | |
// ["*://*.adnxs.com/jpt*"] | |
var reqPatterns = []; | |
for (var b in bidderPatterns) { | |
var patterns = bidderPatterns[b]; | |
for (var i = 0; i < patterns.length; i++) { | |
var p = patterns[i]; | |
patternsToBidders[p] = b; | |
// .adnxs.com/jpt would become *.adnxs.com/jpt | |
// and ad.crwdcntrl.net/ will remain as it is | |
if (p[0] === '.') p = '*' + p; | |
var urlPattern = '*://' + p + '*'; | |
reqPatterns.push(urlPattern); | |
} | |
} | |
/* | |
{ | |
"frameId": 0, | |
"method": "GET", | |
"parentFrameId": -1, | |
"requestId": "153729", | |
"tabId": 2452, | |
"timeStamp": 1449356123237.1, | |
"type": "script", | |
"url": "http:\/\/ib.adnxs.com\/jpt?callback=pbjs.handleCB&callback_uid=1f4c1ca09&psa=0&size=728x90&promo_sizes=970x90&referrer=http%3A%2F%2Flocal%2Fexamples%2Fpbjs_full_example.html" | |
} | |
*/ | |
function getBidderFromURL(url) { | |
if (!url) return; | |
for (var p in patternsToBidders) { | |
var urlRegex; | |
var wildcard = p.indexOf('*'); | |
// '*' in a bidder pattern will match urls provided by Chrome API, but not | |
// the patternsToBidders map using regex syntax. It will match as a regex | |
// by placing '.' before the '*', meaning any character 0 or more times | |
if (wildcard !== -1) { | |
urlRegex = new RegExp(p.slice(0, wildcard) + '.' + p.slice(wildcard)); | |
} | |
if (url.indexOf(p) != -1 || (urlRegex && urlRegex.test(url))) { | |
return patternsToBidders[p]; | |
} | |
} | |
} | |
/* Example: | |
{ | |
2452: { // tab ID | |
'153729': { // request ID | |
bidder: 'appnexus', | |
start: 1449357588485.302, | |
end: 1449357588666.545, | |
}, | |
'234324': ... | |
} | |
} | |
*/ | |
var bidReqs = {}; | |
/* Track the number of bidders in each tab for the icon badge. | |
Example: | |
{ tabId: bidders | |
2452: ['appnexus', 'openx', ...] | |
} */ | |
var bidders = {}; | |
// https://developer.chrome.com/extensions/match_patterns | |
chrome.webRequest.onBeforeRequest.addListener( | |
function(details) { | |
if (!details) return; | |
// Find the bidder | |
var bidder = getBidderFromURL(details.url); | |
if (!bidder) return; | |
var tabId = details.tabId; | |
// Make sure the tabId objects are in bidders and bidReqs | |
if (!(tabId in bidders)) return; | |
if (!(tabId in bidReqs)) return; | |
var tabBidReqs = bidReqs[tabId]; | |
// Record the request ID and the start timestamp | |
tabBidReqs[details.requestId] = { | |
bidder: bidder, | |
start: details.timeStamp, | |
tabId: tabId | |
} | |
// Increment bidders for showing in badge | |
var tabBidders = bidders[tabId]; | |
if (tabBidders && tabBidders.indexOf(bidder) == -1) { | |
tabBidders.push(bidder); | |
var count = tabBidders.length; | |
chrome.browserAction.setBadgeText({text: '' + count, tabId: tabId}); | |
} | |
}, { | |
urls: reqPatterns | |
} | |
); | |
chrome.webRequest.onCompleted.addListener( | |
function(details) { | |
if (!details) return; | |
var reqId = details.requestId; | |
var tabId = details.tabId; | |
if (!(tabId in bidReqs)) return; | |
var tabBidReqs = bidReqs[tabId]; | |
// Find the request based on the request ID. Record the end timestamp | |
if (reqId in tabBidReqs) { | |
tabBidReqs[reqId].end = details.timeStamp; | |
} | |
}, { | |
urls: reqPatterns | |
} | |
); | |
// Users installed this login to understand latency data. | |
// If prebid partners' latency are found, log their latency data. | |
// The server will display the latency data by prebid partner in a UI. | |
// A demo of such latency data are available at: http://api.prebid.org/ | |
function logTabBidReq(tabId, loadId, referrer) { | |
setTimeout(function() { | |
if (!(tabId in bidReqs)) return; | |
var tabBidReqs = bidReqs[tabId]; | |
// If no bidder latency is found, do not log. | |
if (Object.keys(tabBidReqs).length == 0) return; | |
var data = { | |
"loadId": loadId, | |
"referrer": referrer, | |
"bidReqs": tabBidReqs | |
} | |
var xhr = new XMLHttpRequest(); | |
xhr.open('POST', LOG_LOC, true); | |
xhr.setRequestHeader('Content-Type', 'application/json'); | |
xhr.send(JSON.stringify(data)); | |
}, LOG_WAIT_TIME); | |
} | |
// reset table when tab is refreshed | |
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { | |
if (changeInfo.status == "loading") { | |
bidders[tabId] = []; | |
bidReqs[tabId] = {}; | |
chrome.browserAction.setBadgeText({text: "" + 0, tabId: tabId}); | |
var loadId = '' + new Date().getTime(); | |
loadId += Math.floor(Math.random() * 100000); | |
logTabBidReq(tabId, loadId, tab.url); | |
} | |
}) | |
// clean table when tab is closed | |
chrome.tabs.onRemoved.addListener(function(tabId, removeInfo) { | |
delete bidders[tabId]; | |
delete bidReqs[tabId]; | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var bidderPatterns = { | |
'AppNexus': [ | |
'.adnxs.com/jpt' | |
], | |
'Openx': [ | |
//'.servedbyopenx.com/w/1.0/jstag', //CDN | |
'.servedbyopenx.com/w/1.0/acj', | |
'.openx.net/w/1.0/acj' | |
], | |
'Pubmatic': [ | |
//'.pubmatic.com/AdServer/js/gshowad.js', //CDN | |
'.pubmatic.com/AdServer/AdCallAggregator', | |
'.pubmatic.com/AdServer/AdServerServlet' | |
], | |
'Rubicon': [ | |
//'.rubiconproject.com/ad/9707.js', //CDN | |
'.rubiconproject.com/a/api/fastlane.json', | |
'.rubiconproject.com/a/api/ads.json' | |
], | |
'Criteo': [ | |
'.criteo.com/delivery/rta/rta.js' | |
], | |
'Amazon': [ | |
//'.amazon-adsystem.com/aax2/amzn_ads.js', //CDN | |
'.amazon-adsystem.com/e/dtb/bid' | |
], | |
'AOL': [ | |
'.adtechus.com/pubapi*cmd=bid' | |
], | |
'Sovrn': [ | |
'.lijit.com/rtb/bid' | |
], | |
'Yieldbot': [ | |
//'.yldbt.com/js/yieldbot.intent.js', //CDN | |
'.yldbt.com/m/' | |
], | |
'Sonobi': [ | |
'.sonobi.com/trinity.js' | |
], | |
'Index': [ | |
'.casalemedia.com/cygnus', | |
'.casalemedia.com/headertag' | |
], | |
'Proximic': [ | |
'.zqtk.net/' | |
], | |
'Lotame': [ | |
'ad.crwdcntrl.net/' | |
], | |
'AudienceS': [ | |
'.revsci.net/pql' | |
], | |
'Adform': [ | |
'adx.adform.net/adx/?rp=4' | |
], | |
'DFP': [ | |
'.doubleclick.net/gampad/ads' | |
] | |
}; | |
var LOG_WAIT_TIME = 6000; | |
//var LOG_LOC = 'http://localhost:3000/log'; | |
var LOG_LOC = 'http://api.prebid.org/log'; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment