diff --git a/modules/connatixBidAdapter.js b/modules/connatixBidAdapter.js
new file mode 100644
index 00000000000..5a1e71258e0
--- /dev/null
+++ b/modules/connatixBidAdapter.js
@@ -0,0 +1,190 @@
+import {
+ deepAccess,
+ isFn,
+ logError,
+ logMessage
+} from '../src/utils.js';
+
+import {
+ registerBidder
+} from '../src/adapters/bidderFactory.js';
+import {
+ config
+} from '../src/config.js';
+import {
+ BANNER,
+} from '../src/mediaTypes.js';
+
+const BIDDER_CODE = 'connatix';
+const AD_URL = 'https://placeholder.com/pbjs';
+const SYNC_URL = 'https://placeholder.com/sync';
+const DEFAULT_MAX_TTL = '3600';
+const DEFAULT_CURRENCY = 'USD';
+
+/* Get the bid floor value from the bid object,
+ either using the getFloor function or by accessing the 'params.bidfloor' property.
+ If the bid floor cannot be determined, return 0 as a fallback value.
+*/
+function getBidFloor(bid) {
+ if (!isFn(bid.getFloor)) {
+ return deepAccess(bid, 'params.bidfloor', 0);
+ }
+
+ try {
+ const bidFloor = bid.getFloor({
+ currency: DEFAULT_CURRENCY,
+ mediaType: '*',
+ size: '*',
+ });
+ return bidFloor.floor;
+ } catch (err) {
+ logError(err);
+ return 0;
+ }
+}
+
+/* Wrap the provided bid, playerId, customerId, and scriptId in an HTML string
+ that includes the Connatix player script and related data.
+ This HTML string will be used as the ad content.
+ */
+function wrapAd(bid, playerId, customerId, scriptId, isInApp) {
+ const scriptSrc = isInApp ? `'//cd.connatix.com/connatix.player.omid.js?cid=${customerId}'` : `'//cd.connatix.com/connatix.player.js?cid=${customerId}'`;
+ return `
+
+
+
+
+
+
+
+
+
+
+ `;
+}
+
+export const spec = {
+ code: BIDDER_CODE,
+ gvlid: 143,
+ supportedMediaTypes: [BANNER],
+
+ /* Check if a bid request is valid by verifying if the bidId, params,
+ and placementId properties are present,
+ and if the mediaTypes object contains a BANNER object with a sizes property. */
+ isBidRequestValid: (bid = {}) => {
+ const {
+ params,
+ bidId,
+ mediaTypes
+ } = bid;
+ if (!(bidId && params && params.placementId)) {
+ return false;
+ };
+
+ return Boolean(mediaTypes[BANNER] && mediaTypes[BANNER].sizes);
+ },
+
+ /* Build the request payload by processing valid bid requests and extracting the necessary information.
+ Determine the host and page from the bidderRequest's refferUrl, and include ccpa and gdpr consents.
+ Return an object containing the request method, url, and the constructed payload. */
+ buildRequests: (validBidRequests = [], bidderRequest = {}) => {
+ const ccpa = bidderRequest.uspConsent || undefined;
+ const gdpr = bidderRequest.gdprConsent || undefined;
+
+ let refferLocation;
+ try {
+ refferLocation = bidderRequest.refferUrl && new URL(bidderRequest.refferUrl);
+ } catch (e) {
+ logMessage(e);
+ }
+
+ const host = refferLocation ? refferLocation.host : window.top.location.host;
+ const page = refferLocation ? refferLocation.pathname : window.top.location.pathname;
+
+ const bidRequests = validBidRequests.map(bid => {
+ const {
+ bidId,
+ mediaTypes,
+ params,
+ sizes
+ } = bid;
+ return {
+ bidId,
+ sizes,
+ mediaTypes,
+ placementId: params.placementId,
+ floor: getBidFloor(bid),
+ };
+ });
+
+ const requestPayload = {
+ host,
+ page,
+ bidRequests,
+ ccpa,
+ gdpr,
+ }
+
+ return {
+ method: 'POST',
+ url: AD_URL,
+ data: requestPayload
+ };
+ },
+
+ /* Interpret the server response and create an array of bid responses by extracting and formatting
+ relevant information such as requestId, cpm, width, height, creativeId,
+ and ad content (wrapped using the wrapAd function). */
+ interpretResponse: (serverResponse) => {
+ const bidResponses = serverResponse.body[0].bids.map(bidResponse => {
+ return {
+ requestId: bidResponse.bidId,
+ cpm: bidResponse.cpm,
+ width: bidResponse.width,
+ height: bidResponse.height,
+ creativeId: bidResponse.creativeId,
+ // TODO: check if we'll get netRevenue from the server
+ netRevenue: true,
+ ttl: bidResponse.ttl || DEFAULT_MAX_TTL,
+ referrer: bidResponse.referrer,
+ ad: wrapAd(bidResponse.ad, bidResponse.width, bidResponse.height),
+ };
+ });
+
+ return bidResponses;
+ },
+
+ /* Determine the user sync type (either 'iframe' or 'image') based on syncOptions.
+ Construct the sync URL by appending required query parameters such as gdpr, ccpa, and coppa consents.
+ Return an array containing an object with the sync type and the constructed URL. */
+ getUserSyncs: (syncOptions, serverResponses, gdprConsent, uspConsent) => {
+ let syncType = syncOptions.iframeEnabled ? 'iframe' : 'image';
+ let syncUrl = SYNC_URL + `/${syncType}?pbjs=1`;
+ if (gdprConsent && gdprConsent.consentString) {
+ if (typeof gdprConsent.gdprApplies === 'boolean') {
+ syncUrl += `&gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`;
+ } else {
+ syncUrl += `&gdpr=0&gdpr_consent=${gdprConsent.consentString}`;
+ }
+ }
+ if (uspConsent && uspConsent.consentString) {
+ syncUrl += `&ccpa_consent=${uspConsent.consentString}`;
+ }
+
+ const coppa = config.getConfig('coppa') ? 1 : 0;
+ syncUrl += `&coppa=${coppa}`;
+
+ return [{
+ type: syncType,
+ url: syncUrl
+ }];
+ }
+
+};
+
+registerBidder(spec);