diff --git a/modules/ablidaBidAdapter.js b/modules/ablidaBidAdapter.js
new file mode 100644
index 00000000000..33642a1ac9e
--- /dev/null
+++ b/modules/ablidaBidAdapter.js
@@ -0,0 +1,93 @@
+import * as utils from '../src/utils';
+import {config} from '../src/config';
+import {registerBidder} from '../src/adapters/bidderFactory';
+
+const BIDDER_CODE = 'ablida';
+const ENDPOINT_URL = 'https://bidder.ablida.net/prebid';
+
+export const spec = {
+ code: BIDDER_CODE,
+
+ /**
+ * Determines whether or not the given bid request is valid.
+ *
+ * @param {BidRequest} bid The bid params to validate.
+ * @return boolean True if this is a valid bid, and false otherwise.
+ */
+ isBidRequestValid: function (bid) {
+ return !!(bid.params.placementId);
+ },
+
+ /**
+ * Make a server request from the list of BidRequests.
+ *
+ * @return Array Info describing the request to the server.
+ * @param validBidRequests
+ * @param bidderRequest
+ */
+ buildRequests: function (validBidRequests, bidderRequest) {
+ if (validBidRequests.length === 0) {
+ return [];
+ }
+ return validBidRequests.map(bidRequest => {
+ const sizes = utils.parseSizesInput(bidRequest.sizes)[0];
+ const size = sizes.split('x');
+ const jaySupported = 'atob' in window && 'currentScript' in document;
+ const device = getDevice();
+ const payload = {
+ placementId: bidRequest.params.placementId,
+ width: size[0],
+ height: size[1],
+ bidId: bidRequest.bidId,
+ categories: bidRequest.params.categories,
+ referer: bidderRequest.refererInfo.referer,
+ jaySupported: jaySupported,
+ device: device
+ };
+ return {
+ method: 'POST',
+ url: ENDPOINT_URL,
+ data: payload
+ };
+ });
+ },
+
+ /**
+ * Unpack the response from the server into a list of bids.
+ *
+ * @param {ServerResponse} serverResponse A successful response from the server.
+ * @param bidRequest
+ * @return {Bid[]} An array of bids which were nested inside the server.
+ */
+ interpretResponse: function (serverResponse, bidRequest) {
+ const bidResponses = [];
+ const response = serverResponse.body;
+
+ response.forEach(function(bid) {
+ bid.ttl = config.getConfig('_bidderTimeout');
+ bidResponses.push(bid);
+ });
+ return bidResponses;
+ },
+};
+
+function getDevice() {
+ const ua = navigator.userAgent;
+ const topWindow = window.top;
+ if ((/(ipad|xoom|sch-i800|playbook|silk|tablet|kindle)|(android(?!.*mobi))/i).test(ua)) {
+ return 'tablet';
+ }
+ if ((/(smart[-]?tv|hbbtv|appletv|googletv|hdmi|netcast\.tv|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b)/i).test(ua)) {
+ return 'connectedtv';
+ }
+ if ((/Mobile|iP(hone|od|ad)|Android|BlackBerry|IEMobile|Kindle|NetFront|Windows\sCE|Silk-Accelerated|(hpw|web)OS|Fennec|Minimo|Opera M(obi|ini)|Blazer|Dolfin|Dolphin|Skyfire|Zune/i).test(ua)) {
+ return 'smartphone';
+ }
+ const width = topWindow.innerWidth || topWindow.document.documentElement.clientWidth || topWindow.document.body.clientWidth;
+ if (width > 320) {
+ return 'desktop';
+ }
+ return 'other';
+}
+
+registerBidder(spec);
diff --git a/modules/ablidaBidAdapter.md b/modules/ablidaBidAdapter.md
new file mode 100644
index 00000000000..70e6576cd30
--- /dev/null
+++ b/modules/ablidaBidAdapter.md
@@ -0,0 +1,32 @@
+# Overview
+
+**Module Name**: Ablida Bidder Adapter
+**Module Type**: Bidder Adapter
+**Maintainer**: d.kuster@ablida.de
+
+# Description
+
+Module that connects to Ablida's bidder for bids.
+
+# Test Parameters
+```
+ var adUnits = [
+ {
+ code: 'ad-div',
+ mediaTypes: {
+ banner: {
+ sizes: [[300, 250]],
+ }
+ },
+ bids: [
+ {
+ bidder: 'ablida',
+ params: {
+ placementId: 'mediumrectangle-demo',
+ categories: ['automotive', 'news-and-politics'] // optional: categories of page
+ }
+ }
+ ]
+ }
+ ];
+```
diff --git a/test/spec/modules/ablidaBidAdapter_spec.js b/test/spec/modules/ablidaBidAdapter_spec.js
new file mode 100644
index 00000000000..8e0424aee23
--- /dev/null
+++ b/test/spec/modules/ablidaBidAdapter_spec.js
@@ -0,0 +1,102 @@
+import {assert, expect} from 'chai';
+import {spec} from 'modules/ablidaBidAdapter';
+import {newBidder} from 'src/adapters/bidderFactory';
+
+const ENDPOINT_URL = 'https://bidder.ablida.net/prebid';
+
+describe('ablidaBidAdapter', function () {
+ const adapter = newBidder(spec);
+ describe('isBidRequestValid', function () {
+ let bid = {
+ bidder: 'ablida',
+ params: {
+ placementId: 123
+ },
+ adUnitCode: 'adunit-code',
+ sizes: [
+ [300, 250]
+ ],
+ bidId: '1234asdf1234',
+ bidderRequestId: '1234asdf1234asdf',
+ auctionId: '69e8fef8-5105-4a99-b011-d5669f3bc7f0'
+ };
+ it('should return true where required params found', function () {
+ expect(spec.isBidRequestValid(bid)).to.equal(true);
+ });
+ });
+ describe('buildRequests', function () {
+ let bidRequests = [
+ {
+ bidder: 'ablida',
+ params: {
+ placementId: 123
+ },
+ sizes: [
+ [300, 250]
+ ],
+ adUnitCode: 'adunit-code',
+ bidId: '23beaa6af6cdde',
+ bidderRequestId: '14d2939272a26a',
+ auctionId: '69e8fef8-5105-4a99-b011-d5669f3bc7f0',
+ }
+ ];
+
+ let bidderRequests = {
+ refererInfo: {
+ numIframes: 0,
+ reachedTop: true,
+ referer: 'http://example.com',
+ stack: ['http://example.com']
+ }
+ };
+
+ const request = spec.buildRequests(bidRequests, bidderRequests);
+ it('sends bid request via POST', function () {
+ expect(request[0].method).to.equal('POST');
+ });
+ });
+
+ describe('interpretResponse', function () {
+ let bidRequest = {
+ method: 'POST',
+ url: ENDPOINT_URL,
+ data: {
+ placementId: 'testPlacementId',
+ width: 300,
+ height: 200,
+ bidId: '2b8c4de0116e54',
+ jaySupported: true,
+ device: 'desktop',
+ referer: 'www.example.com'
+ }
+ };
+ let serverResponse = {
+ body: [{
+ requestId: '2b8c4de0116e54',
+ cpm: 1.00,
+ width: 300,
+ height: 250,
+ creativeId: '2b8c4de0116e54',
+ currency: 'EUR',
+ netRevenue: true,
+ ttl: 3000,
+ ad: ''
+ }]
+ };
+ it('should get the correct bid response', function () {
+ let expectedResponse = [{
+ requestId: '2b8c4de0116e54',
+ cpm: 1.00,
+ width: 300,
+ height: 250,
+ creativeId: '2b8c4de0116e54',
+ currency: 'EUR',
+ netRevenue: true,
+ ttl: 3000,
+ ad: ''
+ }];
+ let result = spec.interpretResponse(serverResponse, bidRequest[0]);
+ expect(Object.keys(result)).to.deep.equal(Object.keys(expectedResponse));
+ });
+ });
+});