OpenAds wrapper synchronization

When multiple ad wrappers run on the same page, each wrapper can generate a unique transaction ID (TID), making it hard to track impressions and reconcile bids. OpenAds follows IAB Tech Lab guidelines, which recommend assigning a single, shared TID per impression so all wrappers reference the same ID. This ensures consistent reporting, simplifies auditing, and keeps setups compliant across multiple libraries. The process of synchronization attributes all bids for an impression to a single ID instead of one per wrapper.

IMPORTANT: Improper wrapper configuration can result in lower win rates, or missing signals in the auction.

What you need to know

Here's what you need to know about wrapper synchronization:

For a code sample that illustrates how you can sync an impression TID across multiple libraries, see Run Prebid.js and OpenAds.js concurrently.

Prebid

To use OpenAds alongside Prebid, configure the following Prebid settings to mirror OpenAds:

Add ad units that point to the OpenAds thetradedesk bidder and the Prebid thetradedesk bidder.
Remove Prebid namespaces—no foreign bidder is firing inside the OpenAds auction.
Set the Prebid configuration to match the CPM rounding used in OpenAds.
Update consent management in pbjs to match oajs based on location settings.
Set price granularity to the custom value in both Prebid and OpenAds.
Remove parallel OpenPath and pbjs requests with same slot conflicts.

Run Prebid.js and OpenAds.js concurrently

The following sample JavaScript code shows the pb.js and oa.js scripts running concurrently on a webpage that runs Google Publisher Tag (GPT).

TIP: If your page runs both wrappers inside the script, wait for bids from each wrapper before sending the ad server request. For details, see the trySendAdserverRequest() function.

<script>
  var pbjs = pbjs || {};
  pbjs.que = pbjs.que || [];

  var oajs = oajs || {};
  oajs.que = oajs.que || [];

  var googletag = googletag || {};
  googletag.cmd = googletag.cmd || [];

  var TIMEOUT = 700;
  var adServerRequestSent = false;

  var pbjsBidsBack = false;
  var oajsBidsBack = false;

  googletag.cmd.push(function() {
    googletag.pubads().disableInitialLoad();
  });

  // Helper to ensure we call GPT exactly one time.
  function sendAdserverRequest() {
    if (adServerRequestSent) return;
    adServerRequestSent = true;

    googletag.cmd.push(function() {
      // Apply targeting from both Prebid instances.
      oajs.setTargetingForGPTAsync();
      pbjs.setTargetingForGPTAsync();

      googletag.pubads().refresh();
    });
  }

  function trySendAdserverRequest() {
    if (pbjsBidsBack && oajsBidsBack) {
      sendAdserverRequest();
    }
  }

  // Generate a TID to be synced across OpenAds and Prebid.
  const slots = [
    {
      id: 'TID_PLACEHOLDER',
      tid: oajs.generateTID(),
      sizes: [
        [300, 250]
      ]
    }
  ]

  oajs.que.push(function() {
    oajs.requestBids({
      adUnits: slots.map((slot) => ({
        code: slot.id,
        mediaTypes: {
          banner: {
            sizes: slot.sizes,
          },
        },
        ortb2Imp: {
          ext: {
            // Sync TID to OpenAds.
            tid: slot.tid 
          }
        }
      })),
      bidsBackHandler: function() {
        oajsBidsBack = true;
        trySendAdserverRequest();
      },
      timeout: TIMEOUT
    });
  });

  pbjs.que.push(function() {
    pbjs.requestBids({
      adUnits: slots.map((slot) => ({
        code: slot.id,
        mediaTypes: {
          banner: {
            sizes: slot.sizes,
          },
        },
        ortb2Imp: {
          ext: {
            // Sync TID to Prebid.
            tid: slot.tid
          }
        }
      })),
      bidsBackHandler: function() {
        pbjsBidsBack = true;
        trySendAdserverRequest();
      },
      timeout: TIMEOUT
    });
  });

  // Timeout safeguard
  setTimeout(function() {
    sendAdserverRequest();
  }, TIMEOUT);

  googletag.cmd.push(function() {
    googletag.defineSlot('/1234567/homepage', [300, 250], 'TID_PLACEHOLDER')
      .addService(googletag.pubads());
    googletag.pubads().enableSingleRequest();
    googletag.enableServices();
  });
</script>