diff --git a/modules/big-richmediaBidAdapter.js b/modules/big-richmediaBidAdapter.js
new file mode 100644
index 00000000000..cd8b2462eb8
--- /dev/null
+++ b/modules/big-richmediaBidAdapter.js
@@ -0,0 +1,117 @@
+import {BANNER, VIDEO} from '../src/mediaTypes.js';
+import {config} from '../src/config.js';
+import {registerBidder} from '../src/adapters/bidderFactory.js';
+import {spec as baseAdapter} from './appnexusBidAdapter.js'; // eslint-disable-line prebid/validate-imports
+
+const BIDDER_CODE = 'big-richmedia';
+
+const metadataByRequestId = {};
+
+export const spec = {
+ version: '1.4.0',
+ code: BIDDER_CODE,
+ gvlid: baseAdapter.GVLID, // use base adapter gvlid
+ supportedMediaTypes: [ BANNER, VIDEO ],
+
+ /**
+ * Determines whether or not the given bid request is valid.
+ *
+ * @param {object} bid The bid to validate.
+ * @return boolean True if this is a valid bid, and false otherwise.
+ */
+ isBidRequestValid: function (bid) {
+ if (!baseAdapter.isBidRequestValid) { return true; }
+ return baseAdapter.isBidRequestValid(bid);
+ },
+
+ /**
+ * Make a server request from the list of BidRequests.
+ *
+ * @param {BidRequest[]} bidRequests A non-empty list of bid requests which should be sent to the Server.
+ * @return ServerRequest Info describing the request to the server.
+ */
+ buildRequests: function (bidRequests, bidderRequest) {
+ if (!baseAdapter.buildRequests) { return []; }
+
+ const publisherId = config.getConfig('bigRichmedia.publisherId');
+ if (typeof publisherId !== 'string') { return []; }
+
+ bidRequests.forEach(bidRequest => {
+ if (bidRequest.params.format === 'skin' && bidRequest.mediaTypes.banner) {
+ bidRequest.mediaTypes.banner.sizes.push([1800, 1000]);
+ }
+ metadataByRequestId[bidRequest.bidId] = { placementId: bidRequest.adUnitCode, bidder: bidRequest.bidder };
+ });
+ return baseAdapter.buildRequests(bidRequests, bidderRequest);
+ },
+
+ /**
+ * Unpack the response from the server into a list of bids.
+ *
+ * @param {*} serverResponse A successful response from the server.
+ * @return {Bid[]} An array of bids which were nested inside the server.
+ */
+ interpretResponse: function (serverResponse, params) {
+ const publisherId = config.getConfig('bigRichmedia.publisherId');
+ if (typeof publisherId !== 'string') { return []; }
+
+ const bids = baseAdapter.interpretResponse(serverResponse, params);
+ bids.forEach(bid => {
+ const { placementId, bidder } = metadataByRequestId[bid.requestId] || {};
+ const { width = 1, height = 1, ad, creativeId = '', cpm, vastXml, vastUrl } = bid;
+ const bidRequest = params.bidderRequest.bids.find(({ bidId }) => bidId === bid.requestId);
+ const format = (bidRequest && bidRequest.params && bidRequest.params.format) || 'video-sticky-footer';
+ const isReplayable = bidRequest && bidRequest.params && bidRequest.params.isReplayable;
+ const customSelector = bidRequest && bidRequest.params && bidRequest.params.customSelector;
+ const renderParams = {
+ adm: ad,
+ vastXml,
+ vastUrl,
+ width,
+ height,
+ placementId,
+ bidId: bid.requestId,
+ creativeId: `${creativeId}`,
+ bidder,
+ cpm,
+ format,
+ customSelector,
+ isReplayable
+ };
+ const encoded = window.btoa(JSON.stringify(renderParams));
+ bid.ad = `
+ `;
+
+ if (bid.mediaType !== 'banner') { // in case this is a video
+ bid.mediaType = 'banner';
+ delete bid.renderer;
+ delete bid.vastUrl;
+ delete bid.vastXml;
+ bid.width = 1;
+ bid.height = 1;
+ }
+ });
+ return bids;
+ },
+
+ getUserSyncs: function (syncOptions, responses, gdprConsent) {
+ if (!baseAdapter.getUserSyncs) { return []; }
+ return baseAdapter.getUserSyncs(syncOptions, responses, gdprConsent);
+ },
+
+ transformBidParams: function (params, isOpenRtb) {
+ if (!baseAdapter.transformBidParams) { return params; }
+ return baseAdapter.transformBidParams(params, isOpenRtb);
+ },
+
+ /**
+ * Add element selector to javascript tracker to improve native viewability
+ * @param {Bid} bid
+ */
+ onBidWon: function (bid) {
+ if (!baseAdapter.onBidWon) { return; }
+ baseAdapter.onBidWon(bid);
+ }
+}
+
+registerBidder(spec);
diff --git a/modules/big-richmediaBidAdapter.md b/modules/big-richmediaBidAdapter.md
new file mode 100644
index 00000000000..26f77e527fb
--- /dev/null
+++ b/modules/big-richmediaBidAdapter.md
@@ -0,0 +1,82 @@
+# Overview
+
+```
+Module Name: BI.Garage Rich Media
+Module Type: Bidder Adapter
+Maintainer: mediaconsortium-develop@bi.garage.co.jp
+```
+
+# Description
+
+Module which renders richmedia demand from a Xandr seat
+
+### Global configuration
+
+```javascript
+pbjs.setConfig({
+ debug: false,
+ // …,
+ bigRichmedia: {
+ publisherId: 'A7FN99NZ98F5ZD4G', // Required
+ },
+});
+```
+
+# AdUnit Configuration
+```javascript
+var adUnits = [
+ // Skin adUnit
+ {
+ code: 'banner-div',
+ mediaTypes: {
+ banner: {
+ sizes: [[300, 250], [300,600]]
+ }
+ },
+ bids: [{
+ bidder: 'big-richmedia',
+ params: {
+ placementId: 12345,
+ format: 'skin' // This will automatically add 1800x1000 size to banner mediaType
+ }
+ }]
+ },
+ // Video outstream adUnit
+ {
+ code: 'video-outstream',
+ sizes: [[300, 250]],
+ mediaTypes: {
+ video: {
+ playerSize: [[300, 250]],
+ context: 'outstream',
+ // Certain ORTB 2.5 video values can be read from the mediatypes object; below are examples of supported params.
+ // To note - appnexus supports additional values for our system that are not part of the ORTB spec. If you want
+ // to use these values, they will have to be declared in the bids[].params.video object instead using the appnexus syntax.
+ // Between the corresponding values of the mediaTypes.video and params.video objects, the properties in params.video will
+ // take precedence if declared; eg in the example below, the `skippable: true` setting will be used instead of the `skip: 0`.
+ minduration: 1,
+ maxduration: 60,
+ skip: 0, // 1 - true, 0 - false
+ skipafter: 5,
+ playbackmethod: [2], // note - we only support options 1-4 at this time
+ api: [1,2,3] // note - option 6 is not supported at this time
+ }
+ },
+ bids: [
+ {
+ bidder: 'big-richmedia',
+ params: {
+ placementId: 12345,
+ video: {
+ skippable: true,
+ playback_method: 'auto_play_sound_off'
+ },
+ format: 'video-sticky-footer', // or 'video-sticky-top'
+ isReplayable: true // Default to false - choose if the video should be replayable or not.
+ customSelector: '#nav-bar' // custom selector for navbar
+ }
+ }
+ ]
+ }
+];
+```
diff --git a/test/spec/modules/big-richmediaBidAdapter_spec.js b/test/spec/modules/big-richmediaBidAdapter_spec.js
new file mode 100644
index 00000000000..1e97e1ac1d7
--- /dev/null
+++ b/test/spec/modules/big-richmediaBidAdapter_spec.js
@@ -0,0 +1,310 @@
+import { expect } from 'chai';
+import { spec } from 'modules/big-richmediaBidAdapter.js';
+import { auctionManager } from 'src/auctionManager.js';
+import * as bidderFactory from 'src/adapters/bidderFactory.js';
+import { config } from 'src/config.js';
+import { deepClone } from 'src/utils.js';
+
+describe('bigRichMediaAdapterTests', function () {
+ before(function () {
+ config.setConfig({
+ bigRichmedia: {
+ publisherId: '123ABC'
+ }
+ });
+ });
+
+ after(function () {
+ config.resetConfig();
+ });
+
+ describe('bidRequestValidity', function () {
+ const bid = {
+ 'bidder': 'bigRichmedia',
+ 'params': {
+ 'placementId': '10433394'
+ },
+ 'adUnitCode': 'adunit-code',
+ 'sizes': [[300, 250], [300, 600]],
+ 'bidId': '30b31c1838de1e',
+ 'bidderRequestId': '22edbae2733bf6',
+ 'auctionId': '1d1a030790a475',
+ };
+
+ it('bidRequest with zoneId and deliveryUrl params', function () {
+ expect(spec.isBidRequestValid(bid)).to.equal(true);
+ });
+
+ it('bidRequest with no params is not valid', function () {
+ const localBid = Object.assign({}, bid);
+ localBid.params = {};
+ expect(spec.isBidRequestValid(localBid)).to.equal(false);
+ });
+ });
+
+ describe('bidRequest', function () {
+ let getAdUnitsStub;
+ const bidRequests = [
+ {
+ 'bidder': 'bigRichmedia',
+ 'params': {
+ 'placementId': '10433394'
+ },
+ 'mediaTypes': {
+ 'banner': {
+ 'sizes': [[300, 250], [300, 600], [1800, 1000]]
+ }
+ },
+ 'adUnitCode': 'adunit-code',
+ 'sizes': [[300, 250], [300, 600], [1800, 1000]],
+ 'bidId': '30b31c1838de1e',
+ 'bidderRequestId': '22edbae2733bf6',
+ 'auctionId': '1d1a030790a475',
+ 'transactionId': '04f2659e-c005-4eb1-a57c-fa93145e3843'
+ }
+ ];
+
+ beforeEach(function() {
+ getAdUnitsStub = sinon.stub(auctionManager, 'getAdUnits').callsFake(function() {
+ return [];
+ });
+ });
+
+ afterEach(function() {
+ getAdUnitsStub.restore();
+ });
+
+ it('should have skin size', function () {
+ const bidRequest = Object.assign({},
+ bidRequests[0],
+ {
+ params: {
+ placementId: '10433394',
+ format: 'skin'
+ }
+ }
+ );
+
+ const request = spec.buildRequests([bidRequest]);
+ const payload = JSON.parse(request.data);
+
+ expect(payload.tags[0].sizes).to.exist;
+ expect(payload.tags[0].sizes).to.have.lengthOf(3);
+ });
+
+ it('should build video bid request', function() {
+ const bidRequest = deepClone(bidRequests[0]);
+ bidRequest.params = {
+ placementId: '1234235',
+ video: {
+ skippable: true,
+ playback_method: ['auto_play_sound_off', 'auto_play_sound_unknown'],
+ context: 'outstream',
+ format: 'sticky-top'
+ }
+ };
+ bidRequest.mediaTypes = {
+ video: {
+ playerSize: [640, 480],
+ context: 'outstream',
+ mimes: ['video/mp4'],
+ skip: 0,
+ minduration: 5,
+ api: [1, 5, 6],
+ playbackmethod: [2, 4]
+ }
+ };
+
+ const request = spec.buildRequests([bidRequest]);
+ const payload = JSON.parse(request.data);
+
+ expect(payload.tags[0].video).to.deep.equal({
+ minduration: 5,
+ playback_method: 2,
+ skippable: true,
+ context: 4
+ });
+ expect(payload.tags[0].video_frameworks).to.deep.equal([1, 4])
+ });
+ });
+
+ describe('interpretResponse', function () {
+ let bfStub;
+
+ before(function() {
+ bfStub = sinon.stub(bidderFactory, 'getIabSubCategory');
+ });
+
+ after(function() {
+ bfStub.restore();
+ });
+
+ const response = {
+ 'version': '3.0.0',
+ 'tags': [
+ {
+ 'uuid': '3db3773286ee59',
+ 'tag_id': 10433394,
+ 'auction_id': '4534722592064951574',
+ 'nobid': false,
+ 'no_ad_url': 'https://lax1-ib.adnxs.com/no-ad',
+ 'timeout_ms': 10000,
+ 'ad_profile_id': 27079,
+ 'ads': [
+ {
+ 'content_source': 'rtb',
+ 'ad_type': 'banner',
+ 'buyer_member_id': 958,
+ 'creative_id': 29681110,
+ 'media_type_id': 1,
+ 'media_subtype_id': 1,
+ 'cpm': 0.5,
+ 'cpm_publisher_currency': 0.5,
+ 'publisher_currency_code': '$',
+ 'client_initiated_ad_counting': true,
+ 'viewability': {
+ 'config': ''
+ },
+ 'rtb': {
+ 'banner': {
+ 'content': '',
+ 'width': 300,
+ 'height': 250
+ },
+ 'trackers': [
+ {
+ 'impression_urls': [
+ 'https://lax1-ib.adnxs.com/impression',
+ 'https://www.test.com/tracker'
+ ],
+ 'video_events': {}
+ }
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ };
+
+ it('should get correct bid response', function () {
+ const expectedResponse = [
+ {
+ 'requestId': '3db3773286ee59',
+ 'cpm': 0.5,
+ 'creativeId': 29681110,
+ 'dealId': undefined,
+ 'width': 300,
+ 'height': 250,
+ 'ad': '',
+ 'mediaType': 'banner',
+ 'currency': 'USD',
+ 'ttl': 300,
+ 'netRevenue': true,
+ 'adUnitCode': 'code',
+ 'appnexus': {
+ 'buyerMemberId': 958
+ },
+ 'meta': {
+ 'dchain': {
+ 'ver': '1.0',
+ 'complete': 0,
+ 'nodes': [{
+ 'bsid': '958'
+ }]
+ }
+ }
+ }
+ ];
+ const bidderRequest = {
+ bids: [{
+ bidId: '3db3773286ee59',
+ adUnitCode: 'code'
+ }]
+ };
+ const result = spec.interpretResponse({ body: response }, {bidderRequest});
+ expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0]));
+ });
+
+ it('handles outstream video responses', function () {
+ const response = {
+ 'tags': [{
+ 'uuid': '84ab500420319d',
+ 'ads': [{
+ 'ad_type': 'video',
+ 'cpm': 0.500000,
+ 'notify_url': 'imptracker.com',
+ 'rtb': {
+ 'video': {
+ 'content': ''
+ }
+ },
+ 'javascriptTrackers': ''
+ }]
+ }]
+ };
+ const bidderRequest = {
+ bids: [{
+ bidId: '84ab500420319d',
+ adUnitCode: 'code',
+ mediaTypes: {
+ video: {
+ context: 'outstream'
+ }
+ }
+ }]
+ }
+
+ const result = spec.interpretResponse({ body: response }, {bidderRequest});
+ expect(result[0]).not.to.have.property('vastXml');
+ expect(result[0]).not.to.have.property('vastUrl');
+ expect(result[0]).to.have.property('width', 1);
+ expect(result[0]).to.have.property('height', 1);
+ expect(result[0]).to.have.property('mediaType', 'banner');
+ });
+ });
+
+ describe('getUserSyncs', function() {
+ const syncOptions = {
+ syncEnabled: false
+ };
+
+ it('should not return sync', function() {
+ const serverResponse = [{ body: '' }];
+ const result = spec.getUserSyncs(syncOptions, serverResponse);
+ expect(result).to.be.undefined;
+ });
+ });
+
+ describe('transformBidParams', function() {
+ it('cast placementId to number', function() {
+ const adUnit = {
+ code: 'adunit-code',
+ params: {
+ placementId: '456'
+ }
+ };
+ const bid = {
+ params: {
+ placementId: '456'
+ },
+ sizes: [[300, 250]],
+ mediaTypes: {
+ banner: { sizes: [[300, 250]] }
+ }
+ };
+
+ const params = spec.transformBidParams({ placementId: '456' }, true, adUnit, [{ bidderCode: 'bigRichmedia', auctionId: bid.auctionId, bids: [bid] }]);
+
+ expect(params.placement_id).to.exist;
+ expect(params.placement_id).to.be.a('number');
+ });
+ });
+
+ describe('onBidWon', function() {
+ it('Should not have any error', function() {
+ const result = spec.onBidWon({});
+ expect(true).to.be.true;
+ });
+ });
+});