Skip to main content

Unity SDK Integration

Unity SDK 1.x

This guide covers the 1.x line of the AscendX Unity SDK. The 2.x line is a separate SDK, used only by the LevelPlay Backfill Example — switch to v2.x in the Versions menu. Do not mix the two in one project. See the Unity SDK 1.x release notes.

1. Import and Setup the SDK​

1.1. Note​

  • The current version supports Banner, MREC, Interstitial, and Rewarded ad formats

1.2. Requirements​

  • Min Android SDK version: 24
  • Min iOS version: 12

1.3. Install the SDK​

Choose one of the two options below.

1.3.1. Option 1: Unity Package Manager (UPM) - Recommended​

  1. For first installation, add the scoped registry and the dependency to your Packages/manifest.json:

    {
    "scopedRegistries": [
    {
    "name": "AscendX Unity",
    "url": "https://asia-southeast1-npm.pkg.dev/ascendx-463208/asx-upm-prod/",
    "scopes": [
    "com.ascendxnow"
    ]
    }
    ],
    "dependencies": {
    "com.ascendxnow.unity-sdk": "1.22.0"
    }
    }

    If your project already has a scopedRegistries entry for AscendX Unity — for example from a Custom Adapter — reuse it and only add the com.ascendxnow.unity-sdk dependency.

  2. Back in Unity, the package is resolved automatically. You can verify it under Window → Package Manager → My Registries → AscendX Unity.

  3. To update to a newer 1.x version later, change the com.ascendxnow.unity-sdk version in Packages/manifest.json, or open Window → Package Manager, select AscendX Unity SDK and pick the version from its version list.

    warning

    Do not use the Update button in Package Manager. It offers the newest release of the package, which is on the separate 2.x line.

1.3.2. Option 2: Import the .unitypackage manually​

  1. Download the plugin: Knorex-Unity-Plugin - 1.22.0
  2. In Unity, select Assets > Import Package > Custom Package…
  3. Choose the Knorex Unity Plugin file you downloaded.
  4. In the Import Unity Package dialog, click Import.

Unity project structure after importing Knorex Unity Plugin

1.4. External Dependency Manager (Play Services Resolver)​

Required for both installation options — it pulls in the native Android / iOS dependencies of the SDK.

1.4.1. Android​

Follow these steps to resolve Knorex’s dependencies:

  1. Configure Gradle Template:
    • Enable the setting Custom Main Gradle Template (Navigate to Build Settings → Player Settings → Publishing settings).
  2. Enable Required Settings:
    • Enable the setting Patch mainTemplate.gradle (Navigate to Assets → External Dependency Manager → Android Resolver → Settings).
    • Enable the setting Use Jetifier (Navigate to Assets → External Dependency Manager → Android Resolver → Settings).
  3. Resolve Dependencies:
    • Run Assets → External Dependency Manager → Android Resolver and press Resolve or Force Resolve.

As a result, the modules required for Knorex SDK support will be imported into the project's mainTemplate.gradle file.

1.4.2. iOS​

Follow these steps to resolve dependencies:

  1. Install CocoaPods:
    • Run Assets → External Dependency Manager → iOS Resolver → Install Cocoapods.
  2. Enable Required Settings:
    • Enable the setting Allow the same pod to be in multiple targets (Navigate to Assets → External Dependency Manager → iOS Resolver → Settings).

2. Integration​

2.1. Initialize the SDK​

// 1. Attach handler to initialzation event
PrebidSdkCallbacks.OnSdkInitializedEvent += () => {
Debug.Log("Prebid SDK initialized");
};

// 2. Setup require params
PrebidSdk.SetServerHost("«SERVER_URL»");
PrebidSdk.SetAccountId("«ACCOUNT_ID»");

// 3. initialize the SDK as soon as your app launches
PrebidSdk.InitializeSdk();

2.2. Auction Result​

ParameterTypeDescriptionExample
BidIDStringBid ID of the 1st winner provided in the auction."cc5bd14b-aaef-4037-b4f8-879913366e3c"
Demand SourceStringSource name of the 1st winner."Knorex"
AdDomainStringAdvertiser domain of the 1st winner (top levels only e.g., “knorex.com ").“knorex.com"
PricedoubleDeprecated. Please use PriceCPM
Winner price expressed as CPM.
0.23
PriceCPMdoubleTotal of winners’ bid price expressed as CPM.0.23
PriceValuedoubleTotal of winners’ bid price expressed in USD.0.00023
AuctionID*StringThe unique identifier for the auction."cc5bd14b-aaef-4037-b4f8-879913366e3c"
CreativeID*StringThe unique identifier for the winning creative.“hgcyge12”
WinningBids*Array ObjectA list of details about the winning bids.

(*) Note: Those new fields are only available since Android 1.10.1 and iOS 1.5.0

2.3. WinningBid​

ParameterTypeDescriptionExample
BidIDStringThe unique identifier for the winning bid."cc5bd14b-aaef-4037-b4f8-879913366e3c"
Demand SourceStringSource name of the winner."Knorex"
AdDomainStringAdvertiser domain of the 1st winner (top levels only e.g., “knorex.com ").“knorex.com"
PriceCPMdoubleTotal of winners’ bid price expressed as CPM.0.23
PriceValuedoubleTotal of winners’ bid price expressed in USD.0.00023
CreativeIDStringThe unique identifier for the winning creative.“hgcyge12”

2.4. Ad Info​

ParameterTypeDescriptionExample
AdUnitIdStringAd Unit ID"0689a263-318d-448b-a3d4-b02e8a709d9d"
BidIDStringBid ID of the 1st winner provided in the auction."cc5bd14b-aaef-4037-b4f8-879913366e3c"
Demand SourceStringSource name of the 1st winner."Knorex"
AdDomainStringAdvertiser domain of the 1st winner (top levels only e.g., “knorex.com ").“knorex.com"
PricedoubleDeprecated. Please use PriceCPM
Winner price expressed as CPM.
0.23
PriceCPMdoubleTotal of winners’ bid price expressed as CPM.0.23
PriceValuedoubleTotal of winners’ bid price expressed in USD.0.00023
AdRevenueCPM*doubleThe total revenue of the ad is expressed as CPM.10.0
AdRevenue*doubleThe total revenue of the ad is expressed as USD.0.01
CreativeID*StringThe unique identifier for the winning creative“hgcyge12”
WinningBids*Array ObjectA list of details about the winning bids
DisplayedBidsArray ObjectA list of details about the displayed bids in the ad session

(*) Note: Those new fields are only available since Android 1.10.1 and iOS 1.5.0

2.5. Error Info​

ParameterTypeDescriptionExample
AdUnitId*StringThe ad unit id the error came from. Use it to tell which ad unit a shared callback — e.g. PrebidSdkCallbacks.Interstitial.OnAdLoadFailedEvent — is reporting on."0689a263-318d-448b-a3d4-b02e8a709d9d"
MessageStringA human-readable description of the error."No bid"

(*) Note: AdUnitId is only available since Unity Plugin v1.20.0

2.6. Banner Size​

TypeSizeDescription
Size_320x50width: 320 height: 50Regular banner size.
Size_728x90width: 728 height: 90Banner size for tablets
Size_300x250width: 300 height: 250MREC banenr size

2.7. Banner position​

The supported list of position options is as follows:

  • TopLeft
  • TopCenter
  • TopRight
  • Centered
  • CenterLeft
  • CenterRight
  • BottomLeft
  • BottomCenter
  • BottomRight

You can also position an ad at a specific (x, y) coordinate on the screen by calling PrebidSdk.CreateBannerAd(BANNER_AD_UNIT_ID, bannerSize, x, y); or PrebidSdk.CreateMREC(MREC_AD_UNIT_ID, x, y);. This sets the position of the top-left corner of the ad. The coordinate system represents the safe area bounds of the screen. Ensure that you account for the width and height of the ad when setting these coordinates. The position (0, 0) is equivalent to TopLeft; the bottom-right corner of the safe area is (safeAreaWidth, safeAreaHeight).

Note that (x, y) coordinates should be provided in density-independent pixels (dp).

2.8. Passing a client-side A/B test flag​

Allow publishers to pass an A/B test flag to the SDK. The server will use this flag to determine whether to apply the configured bidder list for A/B testing scenarios.

public static void SetAbTestFlag(int abTestFlag)

// Usage:
PrebidSdk.SetAbTestFlag(1);

2.9. Set Ad Request Listener​

When an ad request is made, one of the following callbacks will be triggered depending on the outcome:

  • OnRequestSuccessEvent is called when

    • Ad request is successfully made, and server returns a qualified bid response
    • If an ad request comes with a floor price, the event is fired when server responds with a higher bid than the specified floor price. (This requires the floor enforcement feature enabled on the server-side)
  • OnRequestFailedEvent is called when

    • Any failure occurs when making the ad request
    • Request times out
    • Server does not return a bid, or cannot bid higher than the floor price (This requires the floor enforcement feature enabled on the server-side)
// Fired in the following scenarios:
// - Ad request is successfully made, and server returns a qualified bid response.
// - If ad request comes with a floor price, fired when server responds
// with a higher bid than the specified floor price
PrebidSdkCallbacks.OnRequestSuccessEvent += (adUnitId, auctionResult) => {
if (adUnitId == "YOUR_BANNER_AD_UNIT_ID") {
// Handle successful bid for banner ad
} else if (adUnitId == "YOUR_INTERSTITIAL_AD_UNIT_ID") {
// Handle successful bid for interstitial ad
} else if (adUnitId == "YOUR_REWARDED_AD_UNIT_ID") {
// Handle successful bid for rewarded ad
} else {
// Handle other ad unit types if necessary
}
};
// Fired in the following scenarios:
// - When any failure occurs when making the ad request
// - Request times out
// - Server does not return a bid, or cannot bid higher than the floor price.
PrebidSdkCallbacks.OnRequestFailedEvent += (adUnitId, error) => {
if (adUnitId == "YOUR_BANNER_AD_UNIT_ID") {
// Handle failure for banner ad
} else if (adUnitId == "YOUR_INTERSTITIAL_AD_UNIT_ID") {
// Handle failure for interstitial ad
} else if (adUnitId == "YOUR_REWARDED_AD_UNIT_ID") {
// Handle failure for rewarded ad
} else {
// Handle other ad unit types if necessary
}
};

Note: If these callbacks are where you decide whether the S2S demand wins or loses, fire the corresponding win / loss notification accordingly — see 6. Win/Loss Notifications.

3. Ad Formats​

3.1. Banner Ads​

3.1.1. Create a BANNER​

PrebidSdkCallbacks.Banner.OnAdLoadedEvent += (PrebidSdkBase.AdInfo adInfo) => {};
PrebidSdkCallbacks.Banner.OnAdClickedEvent += (PrebidSdkBase.AdInfo adInfo) => {};
PrebidSdkCallbacks.Banner.OnAdLoadFailedEvent += (PrebidSdkBase.ErrorInfo errorInfo) => {};
PrebidSdkCallbacks.Banner.OnAdDisplayedEvent += (PrebidSdkBase.AdInfo adInfo) => {
// adInfo.PriceCPM is now available to retrieve
};

PrebidSdk.CreateBannerAd("«BANNER_AD_UNIT_ID»", PrebidSdkBase.BannerSize.Size_320x50, PrebidSdkBase.BannerPosition.BottomCenter);
warning

Deprecated in v1.7.0. Use CreateBannerAd(…) instead

PrebidSdkCallbacks.Banner.OnAdLoadedEvent += (PrebidSdkBase.AdInfo adInfo) => {};
PrebidSdkCallbacks.Banner.OnAdClickedEvent += (PrebidSdkBase.AdInfo adInfo) => {};
PrebidSdkCallbacks.Banner.OnAdLoadFailedEvent += (PrebidSdkBase.ErrorInfo errorInfo) => {};
PrebidSdkCallbacks.Banner.OnAdDisplayedEvent += (PrebidSdkBase.AdInfo adInfo) => {
// adInfo.price is now available to retrieve
};

PrebidSdk.CreateBanner("«BANNER_AD_UNIT_ID»", PrebidSdkBase.BannerSize.Size_320x50, PrebidSdkBase.BannerPosition.BottomCenter);

3.1.2. Load BANNER​

PrebidSdk.LoadBannerAd(adUnitId);
warning

Deprecated in v1.7.0. Use LoadBannerAd(…) instead

PrebidSdk.LoadBanner();

3.1.3. Show BANNER​

PrebidSdk.ShowBannerAd(adUnitId);
warning

Deprecated in v1.7.0. Use ShowBannerAd(…) instead

PrebidSdk.ShowBanner();

3.1.4. Hide BANNER​

PrebidSdk.HideBannerAd(adUnitId);
warning

Deprecated in v1.7.0. Use HideBannerAd(…) instead

PrebidSdk.HideBanner();

3.1.5. Destroy BANNER​

PrebidSdk.DestroyBannerAd(adUnitId);
warning

Deprecated in v1.7.0. Use DestroyBannerAd(…) instead

PrebidSdk.DestroyBanner();

3.2. MREC Ads​

3.2.1. Create a MREC​

PrebidSdkCallbacks.MREC.OnAdLoadedEvent += (PrebidSdkBase.AdInfo adInfo) => {};
PrebidSdkCallbacks.MREC.OnAdClickedEvent += (PrebidSdkBase.AdInfo adInfo) => {};
PrebidSdkCallbacks.MREC.OnAdLoadFailedEvent += (PrebidSdkBase.ErrorInfo errorInfo) => {};
PrebidSdkCallbacks.MREC.OnAdDisplayedEvent += (PrebidSdkBase.AdInfo adInfo) => {
// adInfo.PriceCPM is now available to retrieve
};

PrebidSdk.CreateMREC("«MREC_AD_UNIT_ID»", PrebidSdkBase.BannerPosition.BottomCenter);

3.2.2. Load MREC​

PrebidSdk.LoadMREC(adUnitId);

3.2.3. Show MREC​

PrebidSdk.ShowMREC(adUnitId);

3.2.4. Hide MREC​

PrebidSdk.HideMREC(adUnitId);

3.2.5. Destroy MREC​

PrebidSdk.DestroyMREC(adUnitId);

3.3. Interstitial Ads​

warning

API change in v1.20.0. You can now create and manage more than one interstitial ad unit in the same app — see 3.3.5. Multiple Interstitial Ad Units. Every interstitial API has an overload that takes the adUnitId it applies to. Use these overloads from now on.

The overloads without adUnitId are deprecated since v1.20.0. They keep working — they operate on the ad unit passed to the most recent CreateInterstitial call — but they become ambiguous as soon as your app has more than one interstitial ad unit, so migrate at your earliest convenience.

⚠️ Deprecated in v1.20.0Use instead
FetchInterstitialDemand()FetchInterstitialDemand(adUnitId)
FetchInterstitialAd()FetchInterstitialAd(adUnitId)
IsInterstitialReady()IsInterstitialReady(adUnitId)
ShowInterstitial()ShowInterstitial(adUnitId)
SetInterstitialImpExtraParameter(key, value)SetInterstitialImpExtraParameter(adUnitId, key, value)
NotifyDemandWinInterstitial(secondHighestPriceInCpm)NotifyDemandWinInterstitial(adUnitId, secondHighestPriceInCpm)
NotifyDemandLossInterstitial(highestPriceInCpm)NotifyDemandLossInterstitial(adUnitId, highestPriceInCpm)

Note: the PrebidSdkCallbacks.Interstitial.* events are shared by all interstitial ad units. When you run several of them, use adInfo.AdUnitId — and errorInfo.AdUnitId, available since v1.20.0 — to tell which ad unit the event came from.

3.3.1. Create and set up an Interstitial Ad​

Note: PrebidSdkCallbacks.Interstitial.OnAdDisplayedEvent is deprecated for revenue tracking starting from v1.16.0. Revenue information will be removed from OnAdDisplayedEvent in a future release, and repurposed the callback for tracking display events only. You should migrate to OnAdImpressionEvent to ensure continuous revenue tracking.

#if UNITY_IOS
string InterstitialAdUnitId = "«IOS_INTERSTITIAL_AD_UNIT_ID»";
#else // UNITY_ANDROID
string InterstitialAdUnitId = "«ANDROID_INTERSTITIAL_AD_UNIT_ID»";
#endif

int interstitialRetryAttempt;

void InitializeInterstitialAds()
{
PrebidSdk.CreateInterstitial(InterstitialAdUnitId);

PrebidSdkCallbacks.Interstitial.OnAdLoadedEvent += (PrebidSdkBase.AdInfo adInfo) =>
{
interstitialRetryAttempt = 0;
};
PrebidSdkCallbacks.Interstitial.OnAdLoadFailedEvent += (PrebidSdkBase.ErrorInfo errorInfo) =>
{
// errorInfo.AdUnitId tells you which interstitial ad unit failed, since v1.20.0
Debug.Log("Interstitial ad load failed for " + errorInfo.AdUnitId + ": " + errorInfo.Message);

// Interstitial ad failed to load. We recommend retrying with exponentially higher delays up to a maximum delay (in this case 64 seconds).
interstitialRetryAttempt++;
double retryDelay = Math.Pow(2, Math.Min(6, interstitialRetryAttempt));

// Invoke("LoadInterstitial", (float) retryDelay); // before 1.9.0
Invoke("FetchInterstitialDemand", (float) retryDelay); // since v1.9.0
};
PrebidSdkCallbacks.Interstitial.OnAdClickedEvent += (PrebidSdkBase.AdInfo adInfo) =>
{
Debug.Log("Interstitial ad clicked");
};
// DEPRECATED for revenue tracking since v1.16.0.
// Revenue info will be removed in a future release—migrate to OnAdImpressionEvent.
PrebidSdkCallbacks.Interstitial.OnAdDisplayedEvent += (PrebidSdkBase.AdInfo adInfo) =>
{
Debug.Log("Interstitial ad displayed.");
};
// Fired when a fullscreen ad cannot be displayed, since v1.15.0
PrebidSdkCallbacks.Interstitial.OnAdDisplayFailedEvent += (PrebidSdkBase.ErrorInfo errorInfo) =>
{
Debug.Log("Interstitial ad display failed for " + errorInfo.AdUnitId + ": " + errorInfo.Message);
// The ad is consumed and cannot be shown again — load the next one
FetchInterstitialDemand();
};
PrebidSdkCallbacks.Interstitial.OnAdClosedEvent += (PrebidSdkBase.AdInfo adInfo) =>
{
// adInfo.AdUnitId tells you which interstitial ad unit was closed
Debug.Log("Interstitial ad closed");
// LoadInterstitial(); // before 1.9.0
FetchInterstitialDemand(); // Load next ad, since v1.9.0
};
// Use this callback for reliable impression revenue tracking.
PrebidSdkCallbacks.Interstitial.OnAdImpressionEvent += (PrebidSdkBase.AdInfo adInfo) =>
{
Debug.Log("Interstitial ad impression recorded. Revenue=" + adInfo.PriceCPM + ", details:");
Debug.Log(GetDetails(adInfo));
};

// LoadInterstitial(); // before 1.9.0
FetchInterstitialDemand(); // ‼️ since v1.9.0
}

void FetchInterstitialDemand()
{
// PrebidSdk.FetchInterstitialDemand(); // ⚠️ deprecated in v1.20.0
PrebidSdk.FetchInterstitialDemand(InterstitialAdUnitId); // since v1.20.0
}

3.3.2. Fetch Demand for an Interstitial Ad​

When you need to request an ad and get an AuctionResult, it will trigger one of these events when the result is available:

  • OnRequestSuccessEvent — when at least one demand source successfully returns an ad response.
  • OnRequestFailedEvent — when all demand sources fail to return a valid ad response.
PrebidSdk.FetchInterstitialDemand(InterstitialAdUnitId); // since v1.20.0
warning

Deprecated in v1.20.0. Use FetchInterstitialDemand(adUnitId) instead

PrebidSdk.FetchInterstitialDemand();

3.3.3. Load an Interstitial Ad​

Once demand has been fetched, the next step is to load and prepare the ad content and make it available for display

void LoadInterstitial() {
PrebidSdk.FetchInterstitialAd(InterstitialAdUnitId); // since v1.20.0
}
warning

Deprecated in v1.20.0. Use FetchInterstitialAd(adUnitId) instead

void LoadInterstitial() {
PrebidSdk.FetchInterstitialAd();
}
warning

Deprecated in v1.8.0. Use FetchInterstitialAd(…) instead

void LoadInterstitial() {
PrebidSdk.LoadInterstitial();
}

3.3.4. Show an Interstitial Ad​

void ShowInterstitial() {
// since v1.20.0
if (PrebidSdk.IsInterstitialReady(InterstitialAdUnitId)) {
PrebidSdk.ShowInterstitial(InterstitialAdUnitId);
}
}
warning

Deprecated in v1.20.0. Use IsInterstitialReady(adUnitId) / ShowInterstitial(adUnitId) instead

void ShowInterstitial() {
if (PrebidSdk.IsInterstitialReady()) {
PrebidSdk.ShowInterstitial();
}
}

3.3.5. Multiple Interstitial Ad Units​

Available since v1.20.0

You can run several interstitial ad units side by side in the same app — for example one per placement — each with its own demand, floor price and win/loss result.

To do so:

  1. Call CreateInterstitial once per ad unit.
  2. Pass the adUnitId to every interstitial API you call, so the SDK knows which ad unit you mean.
  3. In the shared PrebidSdkCallbacks.Interstitial.* events, read adInfo.AdUnitId (or errorInfo.AdUnitId) to know which ad unit the event belongs to.
#if UNITY_IOS
string InterstitialAdUnitId1 = "«IOS_INTERSTITIAL_AD_UNIT_ID_1»";
string InterstitialAdUnitId2 = "«IOS_INTERSTITIAL_AD_UNIT_ID_2»";
#else // UNITY_ANDROID
string InterstitialAdUnitId1 = "«ANDROID_INTERSTITIAL_AD_UNIT_ID_1»";
string InterstitialAdUnitId2 = "«ANDROID_INTERSTITIAL_AD_UNIT_ID_2»";
#endif

void InitializeInterstitialAds()
{
// 1. Create one instance per ad unit
PrebidSdk.CreateInterstitial(InterstitialAdUnitId1);
PrebidSdk.CreateInterstitial(InterstitialAdUnitId2);

// 2. The callbacks are shared — dispatch on the ad unit id
PrebidSdkCallbacks.Interstitial.OnAdLoadedEvent += (PrebidSdkBase.AdInfo adInfo) =>
{
Debug.Log("Interstitial ad loaded for " + adInfo.AdUnitId);
};
PrebidSdkCallbacks.Interstitial.OnAdLoadFailedEvent += (PrebidSdkBase.ErrorInfo errorInfo) =>
{
// errorInfo.AdUnitId is available since v1.20.0
Debug.Log("Interstitial ad load failed for " + errorInfo.AdUnitId + ": " + errorInfo.Message);
};
PrebidSdkCallbacks.Interstitial.OnAdDisplayFailedEvent += (PrebidSdkBase.ErrorInfo errorInfo) =>
{
Debug.Log("Interstitial ad display failed for " + errorInfo.AdUnitId + ": " + errorInfo.Message);
PrebidSdk.FetchInterstitialDemand(errorInfo.AdUnitId);
};
PrebidSdkCallbacks.Interstitial.OnAdClosedEvent += (PrebidSdkBase.AdInfo adInfo) =>
{
// Load the next ad for the ad unit that was just closed
PrebidSdk.FetchInterstitialDemand(adInfo.AdUnitId);
};
PrebidSdkCallbacks.Interstitial.OnAdImpressionEvent += (PrebidSdkBase.AdInfo adInfo) =>
{
Debug.Log("Impression on " + adInfo.AdUnitId + ". Revenue=" + adInfo.PriceCPM);
};

// 3. Fetch demand for each ad unit independently
PrebidSdk.FetchInterstitialDemand(InterstitialAdUnitId1);
PrebidSdk.FetchInterstitialDemand(InterstitialAdUnitId2);
}

// Each ad unit is loaded, shown and notified on its own
void ShowInterstitial1()
{
if (PrebidSdk.IsInterstitialReady(InterstitialAdUnitId1)) {
PrebidSdk.ShowInterstitial(InterstitialAdUnitId1);
}
}

void ShowInterstitial2()
{
if (PrebidSdk.IsInterstitialReady(InterstitialAdUnitId2)) {
PrebidSdk.ShowInterstitial(InterstitialAdUnitId2);
}
}

The auction result for each ad unit arrives in OnRequestSuccessEvent / OnRequestFailedEvent, which already carry the adUnitId — see 2.9. Set Ad Request Listener. Floor prices (5.3.2) and win/loss notifications (6.3) are also set per ad unit.

warning

Do not mix the deprecated overloads without adUnitId into a multi-ad-unit setup. They always act on the ad unit from the most recent CreateInterstitial call — in the example above that would be InterstitialAdUnitId2, which is unlikely to be what you intend.

3.4. Rewarded Ads​

warning

API change in v1.20.0. You can now create and manage more than one rewarded ad unit in the same app — see 3.4.5. Multiple Rewarded Ad Units. Every rewarded API has an overload that takes the adUnitId it applies to. Use these overloads from now on.

The overloads without adUnitId are deprecated since v1.20.0. They keep working — they operate on the ad unit passed to the most recent CreateRewardedAd call — but they become ambiguous as soon as your app has more than one rewarded ad unit, so migrate at your earliest convenience.

⚠️ Deprecated in v1.20.0Use instead
FetchRewardedDemand()FetchRewardedDemand(adUnitId)
FetchRewardedAd()FetchRewardedAd(adUnitId)
IsRewardedAdReady()IsRewardedAdReady(adUnitId)
ShowRewardedAd()ShowRewardedAd(adUnitId)
SetRewardedAdImpExtraParameter(key, value)SetRewardedAdImpExtraParameter(adUnitId, key, value)
NotifyDemandWinRewardedAd(secondHighestPriceInCpm)NotifyDemandWinRewardedAd(adUnitId, secondHighestPriceInCpm)
NotifyDemandLossRewardedAd(highestPriceInCpm)NotifyDemandLossRewardedAd(adUnitId, highestPriceInCpm)

Note: the PrebidSdkCallbacks.Rewarded.* events are shared by all rewarded ad units. When you run several of them, use adInfo.AdUnitId — and errorInfo.AdUnitId, available since v1.20.0 — to tell which ad unit the event came from.

3.4.1. Create and set up a Rewarded Ad​

Note: PrebidSdkCallbacks.Rewarded.OnAdDisplayedEvent is deprecated for revenue tracking starting from v1.16.0. Revenue information will be removed from OnAdDisplayedEvent in a future release, and repurposed the callback for tracking display events only. You should migrate to OnAdImpressionEvent to ensure continuous revenue tracking.

#if UNITY_IOS
string RewardedAdUnitId = "«IOS_REWARDED_AD_UNIT_ID»";
#else // UNITY_ANDROID
string RewardedAdUnitId = "«ANDROID_REWARDED_AD_UNIT_ID»";
#endif

int rewardedRetryAttempt;

void InitializeRewardedAds()
{
PrebidSdk.CreateRewardedAd(RewardedAdUnitId);

PrebidSdkCallbacks.Rewarded.OnAdLoadedEvent += (PrebidSdkBase.AdInfo adInfo) =>
{
DebugLog("Rewarded ad loaded");
rewardedStatusText.text = "Loaded";

rewardedRetryAttempt = 0;
};
PrebidSdkCallbacks.Rewarded.OnAdLoadFailedEvent += (PrebidSdkBase.ErrorInfo errorInfo) =>
{
// errorInfo.AdUnitId tells you which rewarded ad unit failed, since v1.20.0
DebugLog("Rewarded ad load failed for " + errorInfo.AdUnitId + ": " + errorInfo.Message);

// Rewarded ad failed to load. We recommend retrying with exponentially higher delays up to a maximum delay (in this case 64 seconds).
rewardedRetryAttempt++;
double retryDelay = Math.Pow(2, Math.Min(6, rewardedRetryAttempt));
rewardedStatusText.text = "Load failed. Retrying in " + retryDelay + "s...";

// Invoke("LoadRewardedAd", (float) retryDelay); // before v1.9.0
Invoke("FetchRewardedDemand", (float)retryDelay); // since v1.9.0
};
PrebidSdkCallbacks.Rewarded.OnAdClickedEvent += (PrebidSdkBase.AdInfo adInfo) =>
{
DebugLog("Rewarded ad clicked");
};
// DEPRECATED for revenue tracking since v1.16.0.
// Revenue info will be removed in a future release—migrate to OnAdImpressionEvent.
PrebidSdkCallbacks.Rewarded.OnAdDisplayedEvent += (PrebidSdkBase.AdInfo adInfo) =>
{
DebugLog("Rewarded ad displayed.");
};
// Fired when a fullscreen ad cannot be displayed, since v1.15.0
PrebidSdkCallbacks.Rewarded.OnAdDisplayFailedEvent += (PrebidSdkBase.ErrorInfo errorInfo) =>
{
DebugLog("Rewarded ad display failed for " + errorInfo.AdUnitId + ": " + errorInfo.Message);
// The ad is consumed and cannot be shown again — load the next one
FetchRewardedDemand();
};
PrebidSdkCallbacks.Rewarded.OnAdClosedEvent += (PrebidSdkBase.AdInfo adInfo) =>
{
// adInfo.AdUnitId tells you which rewarded ad unit was closed
DebugLog("Rewarded ad closed");
// LoadRewardedAd(); // before v1.9.0
FetchRewardedDemand(); // Load next ad, since v1.9.0
};
PrebidSdkCallbacks.Rewarded.OnAdReceivedRewardEvent += (PrebidSdkBase.AdInfo adInfo, PrebidSdkBase.Reward reward) =>
{
DebugLog("Rewarded ad received reward");
};
// Use this callback for reliable impression revenue tracking.
PrebidSdkCallbacks.Rewarded.OnAdImpressionEvent += (PrebidSdkBase.AdInfo adInfo) =>
{
DebugLog("Rewarded ad impression recorded. Revenue=" + adInfo.PriceCPM + ", details:");
DebugLog(GetDetails(adInfo));
};

// LoadRewardedAd(); // before v1.9.0
FetchRewardedDemand(); // ‼️ since v1.9.0
}

void FetchRewardedDemand()
{
// PrebidSdk.FetchRewardedDemand(); // ⚠️ deprecated in v1.20.0
PrebidSdk.FetchRewardedDemand(RewardedAdUnitId); // since v1.20.0
}

3.4.2. Fetch Demand for a Rewarded Ad​

When you need to request an ad and get an AuctionResult, it will trigger one of these events when the result is available:

  • OnRequestSuccessEvent — when at least one demand source successfully returns an ad response.
  • OnRequestFailedEvent — when all demand sources fail to return a valid ad response.
PrebidSdk.FetchRewardedDemand(RewardedAdUnitId); // since v1.20.0
warning

Deprecated in v1.20.0. Use FetchRewardedDemand(adUnitId) instead

PrebidSdk.FetchRewardedDemand();

3.4.3. Load a Rewarded Ad​

Once demand has been fetched, the next step is to load and prepare the ad content and make it available for display

void LoadRewardedAd() {
PrebidSdk.FetchRewardedAd(RewardedAdUnitId); // since v1.20.0
}
warning

Deprecated in v1.20.0. Use FetchRewardedAd(adUnitId) instead

void LoadRewardedAd() {
PrebidSdk.FetchRewardedAd();
}
warning

Deprecated in v1.8.0. Use FetchRewardedAd(…) instead

void LoadRewarded() {
PrebidSdk.LoadRewardedAd();
}

3.4.4. Show a Rewarded Ad​

void ShowRewarded()
{
// since v1.20.0
if (PrebidSdk.IsRewardedAdReady(RewardedAdUnitId))
{
PrebidSdk.ShowRewardedAd(RewardedAdUnitId);
}
}
warning

Deprecated in v1.20.0. Use IsRewardedAdReady(adUnitId) / ShowRewardedAd(adUnitId) instead

void ShowRewarded()
{
if (PrebidSdk.IsRewardedAdReady())
{
PrebidSdk.ShowRewardedAd();
}
}

3.4.5. Multiple Rewarded Ad Units​

Available since v1.20.0

You can run several rewarded ad units side by side in the same app — for example one per placement — each with its own demand, floor price and win/loss result.

To do so:

  1. Call CreateRewardedAd once per ad unit.
  2. Pass the adUnitId to every rewarded API you call, so the SDK knows which ad unit you mean.
  3. In the shared PrebidSdkCallbacks.Rewarded.* events, read adInfo.AdUnitId (or errorInfo.AdUnitId) to know which ad unit the event belongs to.
#if UNITY_IOS
string RewardedAdUnitId1 = "«IOS_REWARDED_AD_UNIT_ID_1»";
string RewardedAdUnitId2 = "«IOS_REWARDED_AD_UNIT_ID_2»";
#else // UNITY_ANDROID
string RewardedAdUnitId1 = "«ANDROID_REWARDED_AD_UNIT_ID_1»";
string RewardedAdUnitId2 = "«ANDROID_REWARDED_AD_UNIT_ID_2»";
#endif

void InitializeRewardedAds()
{
// 1. Create one instance per ad unit
PrebidSdk.CreateRewardedAd(RewardedAdUnitId1);
PrebidSdk.CreateRewardedAd(RewardedAdUnitId2);

// 2. The callbacks are shared — dispatch on the ad unit id
PrebidSdkCallbacks.Rewarded.OnAdLoadedEvent += (PrebidSdkBase.AdInfo adInfo) =>
{
DebugLog("Rewarded ad loaded for " + adInfo.AdUnitId);
};
PrebidSdkCallbacks.Rewarded.OnAdLoadFailedEvent += (PrebidSdkBase.ErrorInfo errorInfo) =>
{
// errorInfo.AdUnitId is available since v1.20.0
DebugLog("Rewarded ad load failed for " + errorInfo.AdUnitId + ": " + errorInfo.Message);
};
PrebidSdkCallbacks.Rewarded.OnAdDisplayFailedEvent += (PrebidSdkBase.ErrorInfo errorInfo) =>
{
DebugLog("Rewarded ad display failed for " + errorInfo.AdUnitId + ": " + errorInfo.Message);
PrebidSdk.FetchRewardedDemand(errorInfo.AdUnitId);
};
PrebidSdkCallbacks.Rewarded.OnAdClosedEvent += (PrebidSdkBase.AdInfo adInfo) =>
{
// Load the next ad for the ad unit that was just closed
PrebidSdk.FetchRewardedDemand(adInfo.AdUnitId);
};
PrebidSdkCallbacks.Rewarded.OnAdReceivedRewardEvent += (PrebidSdkBase.AdInfo adInfo, PrebidSdkBase.Reward reward) =>
{
// Grant the reward that belongs to this ad unit
if (adInfo.AdUnitId == RewardedAdUnitId1) {
// grant the reward of the 1st ad unit
} else if (adInfo.AdUnitId == RewardedAdUnitId2) {
// grant the reward of the 2nd ad unit
}
};
PrebidSdkCallbacks.Rewarded.OnAdImpressionEvent += (PrebidSdkBase.AdInfo adInfo) =>
{
DebugLog("Impression on " + adInfo.AdUnitId + ". Revenue=" + adInfo.PriceCPM);
};

// 3. Fetch demand for each ad unit independently
PrebidSdk.FetchRewardedDemand(RewardedAdUnitId1);
PrebidSdk.FetchRewardedDemand(RewardedAdUnitId2);
}

// Each ad unit is loaded, shown and notified on its own
void ShowRewardedAd1()
{
if (PrebidSdk.IsRewardedAdReady(RewardedAdUnitId1)) {
PrebidSdk.ShowRewardedAd(RewardedAdUnitId1);
}
}

void ShowRewardedAd2()
{
if (PrebidSdk.IsRewardedAdReady(RewardedAdUnitId2)) {
PrebidSdk.ShowRewardedAd(RewardedAdUnitId2);
}
}

The auction result for each ad unit arrives in OnRequestSuccessEvent / OnRequestFailedEvent, which already carry the adUnitId — see 2.9. Set Ad Request Listener. Floor prices (5.3.3) and win/loss notifications (6.4) are also set per ad unit.

warning

Do not mix the deprecated overloads without adUnitId into a multi-ad-unit setup. They always act on the ad unit from the most recent CreateRewardedAd call — in the example above that would be RewardedAdUnitId2, which is unlikely to be what you intend.

4. Data & Keyword passing​

4.1. Unified Identifiers​

You can pass UID2 tokens in the bid stream. Buyers use these tokens to target and accurately bid on app inventory. You are responsible for tokenizing and for passing the token to S2S. The code examples below show how you pass the tokens:

PrebidSdk.SetExternalUserId(PrebidSdkBase.UID2_SOURCE, "<YOUR_UID2_TOKEN>");

5. Dynamic Floor Pricing (optional)​

This is a supplement feature and is disabled by default

5.1. Overview​

A ‘floor’ is defined as the lowest price a bid that will be accepted for each auction. It’s a way for publishers to signal to bidders the price to beat, thereby protecting the value of their inventory. Proper floors are dynamic and determined based on detailed factors like mediaType, adSlot, size, and other factors.

5.2. How does it contribute to your app monetization?​

  • Server-side ensure all bidder’s bidding prices are higher than the acceptable price (price floor)
  • Reduce dust bidding and protect the value of your inventory
  • Reduce application complicated logic and save users’ resources from checking unqualified bids

5.3. Setup steps​

  1. Request KNOREX enable the Floors feature on the server for your account
  2. On client-side, set up price floors for your ad units

5.3.1. Banner / MREC Ads​

void LoadBanner() {
// 1. Add dynamic floor value or mediation bidding price
PrebidSdk.SetBannerAdImpExtraParameter(adUnitId, PrebidSdkBase.BID_FLOOR_KEY, 10.5);

// 2. Add floor currency code
PrebidSdk.SetBannerAdImpExtraParameter(adUnitId, PrebidSdkBase.BID_FLOOR_CUR_KEY, "USD");

// 3. load ad
PrebidSdk.LoadBannerAd(adUnitId);
}

5.3.2. Interstitial Ads​

void LoadInterstitial() {
// 1. Add dynamic floor value or mediation bidding price
PrebidSdk.SetInterstitialImpExtraParameter(adUnitId, PrebidSdkBase.BID_FLOOR_KEY, 2.5);

// 2. Add floor currency code
PrebidSdk.SetInterstitialImpExtraParameter(adUnitId, PrebidSdkBase.BID_FLOOR_CUR_KEY, "USD");

// 3. load ad
PrebidSdk.FetchInterstitialDemand(adUnitId);
}
warning

Deprecated in v1.20.0. Use SetInterstitialImpExtraParameter(adUnitId, …) instead

void LoadInterstitial() {
PrebidSdk.SetInterstitialImpExtraParameter(PrebidSdkBase.BID_FLOOR_KEY, 2.5);
PrebidSdk.SetInterstitialImpExtraParameter(PrebidSdkBase.BID_FLOOR_CUR_KEY, "USD");
PrebidSdk.LoadInterstitial();
}

5.3.3. Rewarded Ads​

void LoadRewardedAd() {
// 1. Add dynamic floor value or mediation bidding price
PrebidSdk.SetRewardedAdImpExtraParameter(adUnitId, PrebidSdkBase.BID_FLOOR_KEY, 10.5);

// 2. Add floor currency code
PrebidSdk.SetRewardedAdImpExtraParameter(adUnitId, PrebidSdkBase.BID_FLOOR_CUR_KEY, "USD");

// 3. load ad
PrebidSdk.FetchRewardedDemand(adUnitId);
}
warning

Deprecated in v1.20.0. Use SetRewardedAdImpExtraParameter(adUnitId, …) instead

void LoadRewardedAd() {
PrebidSdk.SetRewardedAdImpExtraParameter(PrebidSdkBase.BID_FLOOR_KEY, 10.5);
PrebidSdk.SetRewardedAdImpExtraParameter(PrebidSdkBase.BID_FLOOR_CUR_KEY, "USD");
PrebidSdk.LoadRewardedAd();
}

5.4. Note​

  • Currently, the value of BID_FLOOR_CUR_KEY only accepts the string “USD”
  • When this feature is not enabled on the server side or no floors are added, any value of the bidding price is accepted and forwarded to the client SDK

6. Win/Loss Notifications​

Available since v1.18.0

After an auction, your app typically compares the S2S demand against your mediation(s) and decides which ad to display. Once that decision is final, fire the corresponding win notice or loss notice to help optimize your fill over time.

NotificationPrice you must pass
WinsecondHighestPriceInCpm — runner-up CPM.
LosshighestPriceInCpm — winning competitor's CPM.

The exact method and an example for each format are given in 6.2 Banner / MREC, 6.3 Interstitial, and 6.4 Rewarded below.

6.1. Rules​

  • The win / loss result is tracked per ad unit — for banner / MREC, and (since v1.20.0) for each interstitial and rewarded ad unit as well.
  • Once you fire loss for an ad, that ad can no longer be shown — so only fire loss when you have decided not to display it.
  • Fire win as soon as the decision is final, instead of waiting until the ad is about to be shown.

6.2. Banner / MREC Ads​

Banner and MREC share the same methods, pass the corresponding adUnitId.

// Pass the second-highest-price (runner-up) in CPM to the SDK when your S2S demand wins
PrebidSdk.NotifyDemandWinBannerAd(adUnitId, secondHighestPriceInCpm);

// Pass the final winning price (highest-price) in CPM to the SDK when your S2S demand loses
PrebidSdk.NotifyDemandLossBannerAd(adUnitId, highestPriceInCpm);

Fire the win / loss notification right when your decision is final. Here is an example:

// Earlier in your flow:
// - Load your mediation banner
// - Create and load an S2S Banner Ad (Section 3.1)
// The S2S demand auction result then arrives in OnRequestSuccessEvent below.
PrebidSdkCallbacks.OnRequestSuccessEvent += (string adUnitId, PrebidSdkBase.AuctionResult auctionResult) => {
// perform user ad decision to show either your S2S demand or Mediation Ad
// You can use auctionResult.PriceCPM to compare against your mediation's price and decide the winner
if (adUnitId == PrebidBannerAdUnitId && adUnitId == MrecAdUnit) {
AdWinner winner = ...; // decide winner: S2S or Mediation
if (winner == S2S) {
// Notify win with the second-highest-price (runner-up) in CPM
PrebidSdk.NotifyDemandWinBannerAd(adUnitId, secondHighestPriceInCpm); // since v1.18.0
if (adUnitId == PrebidBannerAdUnitId) {
PrebidSdk.ShowBannerAd(adUnitId);
} else if (adUnitId == MrecAdUnit) {
PrebidSdk.ShowMREC(adUnitId);
}
} else {
// Notify loss with the final winning price (highest-price) in CPM
PrebidSdk.NotifyDemandLossBannerAd(adUnitId, highestPriceInCpm); // since v1.18.0
// show your mediation banner
}
}
};

6.3. Interstitial Ads​

// Pass the second-highest-price (runner-up) in CPM to the SDK when your S2S demand wins
PrebidSdk.NotifyDemandWinInterstitial(adUnitId, secondHighestPriceInCpm); // since v1.20.0

// Pass the final winning price (highest-price) in CPM to the SDK when your S2S demand loses
PrebidSdk.NotifyDemandLossInterstitial(adUnitId, highestPriceInCpm); // since v1.20.0
warning

Deprecated in v1.20.0. Use NotifyDemandWinInterstitial(adUnitId, …) / NotifyDemandLossInterstitial(adUnitId, …) instead

PrebidSdk.NotifyDemandWinInterstitial(secondHighestPriceInCpm);
PrebidSdk.NotifyDemandLossInterstitial(highestPriceInCpm);

Fire the win / loss notification right when your decision is final. Here is an example:

// Earlier in your flow:
// - Load your mediation interstitial
// - Create and set up an S2S Interstitial Ad (Section 3.3.1)
// - Fetch demand for S2S Interstitial Ad (Section 3.3.2)
// The S2S demand auction result then arrives in OnRequestSuccessEvent below.
PrebidSdkCallbacks.OnRequestSuccessEvent += (string adUnitId, PrebidSdkBase.AuctionResult auctionResult) => {
// perform user ad decision to show either your S2S demand or Mediation Ad
// You can use auctionResult.PriceCPM to compare against your mediation's price and decide the winner
if (adUnitId == PrebidInterstitialAdUnitId) {
interstitialWinner = ...; // decide winner: S2S or Mediation
if (interstitialWinner == S2S) {
// Notify win with the second-highest-price (runner-up) in CPM
PrebidSdk.NotifyDemandWinInterstitial(adUnitId, secondHighestPriceInCpm); // since v1.20.0
PrebidSdk.FetchInterstitialAd(adUnitId); // since v1.20.0
} else {
// Notify loss with the final winning price (highest-price) in CPM
PrebidSdk.NotifyDemandLossInterstitial(adUnitId, highestPriceInCpm); // since v1.20.0
}
}
};

6.4. Rewarded Ads​

// Pass the second-highest-price (runner-up) in CPM to the SDK when your S2S demand wins
PrebidSdk.NotifyDemandWinRewardedAd(adUnitId, secondHighestPriceInCpm); // since v1.20.0

// Pass the final winning price (highest-price) in CPM to the SDK when your S2S demand loses
PrebidSdk.NotifyDemandLossRewardedAd(adUnitId, highestPriceInCpm); // since v1.20.0
warning

Deprecated in v1.20.0. Use NotifyDemandWinRewardedAd(adUnitId, …) / NotifyDemandLossRewardedAd(adUnitId, …) instead

PrebidSdk.NotifyDemandWinRewardedAd(secondHighestPriceInCpm);
PrebidSdk.NotifyDemandLossRewardedAd(highestPriceInCpm);

Fire the win / loss notification right when your decision is final. Here is an example:

// Earlier in your flow:
// - Load your mediation rewarded ad
// - Create and set up an S2S Rewarded Ad (Section 3.4.1)
// - Fetch demand for S2S Rewarded Ad (Section 3.4.2)
// The S2S demand auction result then arrives in OnRequestSuccessEvent below.
PrebidSdkCallbacks.OnRequestSuccessEvent += (string adUnitId, PrebidSdkBase.AuctionResult auctionResult) => {
// perform user ad decision to show either your S2S demand or Mediation Ad
// You can use auctionResult.PriceCPM to compare against your mediation's price and decide the winner
if (adUnitId == PrebidRewardedAdUnitId) {
rewardedWinner = ...; // decide winner: S2S or Mediation
if (rewardedWinner == S2S) {
// Notify win with the second-highest-price (runner-up) in CPM
PrebidSdk.NotifyDemandWinRewardedAd(adUnitId, secondHighestPriceInCpm); // since v1.20.0
PrebidSdk.FetchRewardedAd(adUnitId); // since v1.20.0
} else {
// Notify loss with the final winning price (highest-price) in CPM
PrebidSdk.NotifyDemandLossRewardedAd(adUnitId, highestPriceInCpm); // since v1.20.0
}
}
};

7. Integration example​

7.1. Use case: Knorex Unity Plugin + Applovin MAX​

void Start()
{
MaxSdkCallbacks.OnSdkInitializedEvent += sdkConfiguration =>
{
// AppLovin SDK is initialized, configure and start loading ads.

// --- Banner (MAX) ---
MaxSdkCallbacks.Banner.OnAdLoadedEvent += (string adUnitId, MaxSdkBase.AdInfo adInfo) => {
PrebidSdk.LoadBannerAd(PrebidBannerAdUnitId);
};
MaxSdkCallbacks.Banner.OnAdLoadFailedEvent += (string adUnitId, MaxSdkBase.ErrorInfo errorInfo) => {
PrebidSdk.LoadBannerAd(PrebidBannerAdUnitId);
};
MaxSdkCallbacks.Banner.OnAdClickedEvent += OnBannerAdClickedEvent;
MaxSdkCallbacks.Banner.OnAdRevenuePaidEvent += OnBannerAdRevenuePaidEvent;

MaxSdk.CreateBanner(BannerAdUnitId, MaxSdkBase.BannerPosition.TopCenter);
MaxSdk.SetBannerBackgroundColor(BannerAdUnitId, Color.white);

// --- Interstitial (MAX) ---
MaxSdkCallbacks.Interstitial.OnAdLoadedEvent += (string adUnitId, MaxSdkBase.AdInfo adInfo) => {
// PrebidSdk.LoadInterstitial(); // before 1.9.0
// PrebidSdk.FetchInterstitialDemand(); // ⚠️ deprecated in v1.20.0
PrebidSdk.FetchInterstitialDemand(PrebidInterstitialAdUnitId); // since v1.20.0
};
MaxSdkCallbacks.Interstitial.OnAdLoadFailedEvent += (string adUnitId, MaxSdkBase.ErrorInfo errorInfo) => {
// PrebidSdk.LoadInterstitial(); // before 1.9.0
// PrebidSdk.FetchInterstitialDemand(); // ⚠️ deprecated in v1.20.0
PrebidSdk.FetchInterstitialDemand(PrebidInterstitialAdUnitId); // since v1.20.0
};
MaxSdk.LoadInterstitial(MaxInterstitialAdUnitId);

// --- Rewarded (MAX) ---
MaxSdkCallbacks.Rewarded.OnAdLoadedEvent += (string adUnitId, MaxSdkBase.AdInfo adInfo) => {
// PrebidSdk.LoadRewardedAd(); // before v1.9.0
// PrebidSdk.FetchRewardedDemand(); // ⚠️ deprecated in v1.20.0
PrebidSdk.FetchRewardedDemand(PrebidRewardedAdUnitId); // since v1.20.0
};
MaxSdkCallbacks.Rewarded.OnAdLoadFailedEvent += (string adUnitId, MaxSdkBase.ErrorInfo errorInfo) => {
// PrebidSdk.LoadRewardedAd(); // before v1.9.0
// PrebidSdk.FetchRewardedDemand(); // ⚠️ deprecated in v1.20.0
PrebidSdk.FetchRewardedDemand(PrebidRewardedAdUnitId); // since v1.20.0
};
MaxSdk.LoadRewardedAd(MaxRewardedAdUnitId);
};
MaxSdk.SetSdkKey(MaxSdkKey);
MaxSdk.InitializeSdk();

// Initialize Knorex SDK
PrebidSdkCallbacks.OnSdkInitializedEvent += () =>
{
if (isTablet) {
PrebidSdk.CreateBannerAd(PrebidBannerAdUnitId, PrebidSdkBase.BannerSize.Size_728x90, PrebidSdkBase.BannerPosition.TopCenter);
} else {
PrebidSdk.CreateBannerAd(PrebidBannerAdUnitId, PrebidSdkBase.BannerSize.Size_320x50, PrebidSdkBase.BannerPosition.TopCenter);
}
PrebidSdk.CreateInterstitial(PrebidInterstitialAdUnitId);
PrebidSdk.CreateRewardedAd(PrebidRewardedAdUnitId);
};
PrebidSdk.SetServerHost("https://prebid-staging.knorex.com/openrtb2/auction");
PrebidSdk.SetAccountId("0689a263-318d-448b-a3d4-b02e8a709d9d");
PrebidSdk.InitializeSdk();

PrebidSdkCallbacks.OnRequestSuccessEvent += (string adUnitId, PrebidSdkBase.AuctionResult auctionResult) => {
// perform user ad decision to show either your S2S demand or Mediation Ad
// You can use auctionResult.PriceCPM to compare against your mediation's price and decide the winner
if (adUnitId == PrebidBannerAdUnitId || adUnitId == MrecAdUnit) {
AdWinner winner = ...; // decide winner: AdWinner.S2S or AdWinner.Mediation
if (winner == AdWinner.S2S) {
// Notify win with the second-highest-price (runner-up) in CPM
PrebidSdk.NotifyDemandWinBannerAd(adUnitId, secondHighestPriceInCpm); // since v1.18.0
if (adUnitId == PrebidBannerAdUnitId) {
PrebidSdk.ShowBannerAd(adUnitId);
} else if (adUnitId == MrecAdUnit) {
PrebidSdk.ShowMREC(adUnitId);
}
} else {
// Notify loss with the final winning price (highest-price) in CPM
PrebidSdk.NotifyDemandLossBannerAd(adUnitId, highestPriceInCpm); // since v1.18.0
MaxSdk.ShowBanner(BannerAdUnitId);
}
} else if (adUnitId == PrebidInterstitialAdUnitId) {
interstitialWinner = ...; // decide winner: AdWinner.S2S or AdWinner.Mediation
if (interstitialWinner == AdWinner.S2S) {
// Notify win with the second-highest-price (runner-up) in CPM
PrebidSdk.NotifyDemandWinInterstitial(adUnitId, secondHighestPriceInCpm); // since v1.20.0
PrebidSdk.FetchInterstitialAd(adUnitId); // since v1.20.0
} else {
// Notify loss with the final winning price (highest-price) in CPM
PrebidSdk.NotifyDemandLossInterstitial(adUnitId, highestPriceInCpm); // since v1.20.0
}
} else if (adUnitId == PrebidRewardedAdUnitId) {
rewardedWinner = ...; // decide winner: AdWinner.S2S or AdWinner.Mediation
if (rewardedWinner == AdWinner.S2S) {
// Notify win with the second-highest-price (runner-up) in CPM
PrebidSdk.NotifyDemandWinRewardedAd(adUnitId, secondHighestPriceInCpm); // since v1.20.0
PrebidSdk.FetchRewardedAd(adUnitId); // since v1.20.0
} else {
// Notify loss with the final winning price (highest-price) in CPM
PrebidSdk.NotifyDemandLossRewardedAd(adUnitId, highestPriceInCpm); // since v1.20.0
}
}
};
PrebidSdkCallbacks.OnRequestFailedEvent += (string adUnitId, PrebidSdkBase.ErrorInfo errorInfo) => {
// No S2S bid
if (adUnitId == PrebidBannerAdUnitId || adUnitId == MrecAdUnit) {
// show Mediation Banner
MaxSdk.ShowBanner(BannerAdUnitId);
} else if (adUnitId == PrebidInterstitialAdUnitId) {
// Record the mediation as winner
interstitialWinner = AdWinner.Mediation;
} else if (adUnitId == PrebidRewardedAdUnitId) {
// Record the mediation as winner
rewardedWinner = AdWinner.Mediation;
}
};
}

// Records which demand won the latest auction, so the ad can be shown later
enum AdWinner { None, S2S, Mediation }
AdWinner interstitialWinner = AdWinner.None;
AdWinner rewardedWinner = AdWinner.None;

void ShowInterstitial()
{
if (interstitialWinner == AdWinner.None) {
// No ad to show
return;
}
// since v1.20.0, pass the ad unit id you want to check / show
if (interstitialWinner == AdWinner.S2S && PrebidSdk.IsInterstitialReady(PrebidInterstitialAdUnitId)) {
PrebidSdk.ShowInterstitial(PrebidInterstitialAdUnitId);
} else if (MaxSdk.IsInterstitialReady(MaxInterstitialAdUnitId)) {
MaxSdk.ShowInterstitial(MaxInterstitialAdUnitId);
} else {
// Ad not ready to show
}
}

void ShowRewardedAd()
{
if (rewardedWinner == AdWinner.None) {
// No ad to show
return;
}
// since v1.20.0, pass the ad unit id you want to check / show
if (rewardedWinner == AdWinner.S2S && PrebidSdk.IsRewardedAdReady(PrebidRewardedAdUnitId)) {
PrebidSdk.ShowRewardedAd(PrebidRewardedAdUnitId);
} else if (MaxSdk.IsRewardedAdReady(MaxRewardedAdUnitId)) {
MaxSdk.ShowRewardedAd(MaxRewardedAdUnitId);
} else {
// Ad not ready to show
}
}

7.2. Use case: Knorex Unity Plugin + LevelPlay​

void Start()
{
LevelPlay.Init(appKey,uniqueUserId);
LevelPlay.OnInitSuccess += OnInitializationCompleted;
LevelPlay.OnInitFailed += (error => Debug.Log("Initialization error: " + error));
}
void OnInitializationCompleted(LevelPlayConfiguration configuration)
{
// Initialize Knorex SDK
PrebidSdkCallbacks.OnSdkInitializedEvent += () =>
{
if (isTablet) {
PrebidSdk.CreateBannerAd(PrebidBannerAdUnitId, PrebidSdkBase.BannerSize.Size_728x90, PrebidSdkBase.BannerPosition.TopCenter);
} else {
PrebidSdk.CreateBannerAd(PrebidBannerAdUnitId, PrebidSdkBase.BannerSize.Size_320x50, PrebidSdkBase.BannerPosition.TopCenter);
}
PrebidSdk.CreateInterstitial(PrebidInterstitialAdUnitId);
PrebidSdk.CreateRewardedAd(PrebidRewardedAdUnitId);
};
PrebidSdk.SetServerHost("https://prebid-staging.knorex.com/openrtb2/auction");
PrebidSdk.SetAccountId("0689a263-318d-448b-a3d4-b02e8a709d9d");
PrebidSdk.InitializeSdk();

// Attach handler to ad response events
PrebidSdkCallbacks.OnRequestSuccessEvent += (string adUnitId, PrebidSdkBase.AuctionResult auctionResult) => {
// perform user ad decision to show either your S2S demand or Mediation Ad
// You can use auctionResult.PriceCPM to compare against your mediation's price and decide the winner
if (adUnitId == PrebidBannerAdUnitId || adUnitId == MrecAdUnit) {
AdWinner winner = ...; // decide winner: AdWinner.S2S or AdWinner.Mediation
if (winner == AdWinner.S2S) {
// Notify win with the second-highest-price (runner-up) in CPM
PrebidSdk.NotifyDemandWinBannerAd(adUnitId, secondHighestPriceInCpm); // since v1.18.0
if (adUnitId == PrebidBannerAdUnitId) {
PrebidSdk.ShowBannerAd(adUnitId);
} else if (adUnitId == MrecAdUnit) {
PrebidSdk.ShowMREC(adUnitId);
}
} else {
// Notify loss with the final winning price (highest-price) in CPM
PrebidSdk.NotifyDemandLossBannerAd(adUnitId, highestPriceInCpm); // since v1.18.0
bannerAd.ShowAd();
}
} else if (adUnitId == PrebidInterstitialAdUnitId) {
interstitialWinner = ...; // decide winner: AdWinner.S2S or AdWinner.Mediation
if (interstitialWinner == AdWinner.S2S) {
// Notify win with the second-highest-price (runner-up) in CPM
PrebidSdk.NotifyDemandWinInterstitial(adUnitId, secondHighestPriceInCpm); // since v1.20.0
PrebidSdk.FetchInterstitialAd(adUnitId); // since v1.20.0
} else {
// Notify loss with the final winning price (highest-price) in CPM
PrebidSdk.NotifyDemandLossInterstitial(adUnitId, highestPriceInCpm); // since v1.20.0
}
} else if (adUnitId == PrebidRewardedAdUnitId) {
rewardedWinner = ...; // decide winner: AdWinner.S2S or AdWinner.Mediation
if (rewardedWinner == AdWinner.S2S) {
// Notify win with the second-highest-price (runner-up) in CPM
PrebidSdk.NotifyDemandWinRewardedAd(adUnitId, secondHighestPriceInCpm); // since v1.20.0
PrebidSdk.FetchRewardedAd(adUnitId); // since v1.20.0
} else {
// Notify loss with the final winning price (highest-price) in CPM
PrebidSdk.NotifyDemandLossRewardedAd(adUnitId, highestPriceInCpm); // since v1.20.0
}
}
};
PrebidSdkCallbacks.OnRequestFailedEvent += (string adUnitId, PrebidSdkBase.ErrorInfo errorInfo) => {
// No S2S bid
if (adUnitId == PrebidBannerAdUnitId || adUnitId == MrecAdUnit) {
// show Mediation Banner
bannerAd.ShowAd();
} else if (adUnitId == PrebidInterstitialAdUnitId) {
// Record the mediation as winner
interstitialWinner = AdWinner.Mediation;
} else if (adUnitId == PrebidRewardedAdUnitId) {
// Record the mediation as winner
rewardedWinner = AdWinner.Mediation;
}
};

// Create LevelPlay banner
bannerAd = new LevelPlayBannerAd(bannerAdUnitId, LevelPlayAdSize.BANNER, LevelPlayBannerPosition.BottomCenter, null, false);

bannerAd.OnAdLoaded += (LevelPlayAdInfo adInfo) => {
PrebidSdk.LoadBannerAd(PrebidBannerAdUnitId);
};
bannerAd.OnAdLoadFailed += (LevelPlayAdError error) => {
PrebidSdk.LoadBannerAd(PrebidBannerAdUnitId);
};
bannerAd.OnAdDisplayed += BannerOnAdDisplayedEvent;
bannerAd.OnAdDisplayFailed += BannerOnAdDisplayFailedEvent;
bannerAd.OnAdClicked += BannerOnAdClickedEvent;
bannerAd.OnAdCollapsed += BannerOnAdCollapsedEvent;
bannerAd.OnAdLeftApplication += BannerOnAdLeftApplicationEvent;
bannerAd.OnAdExpanded += BannerOnAdExpandedEvent;

// Ad load
bannerAd.LoadAd();

// Create LevelPlay interstitial
interstitialAd = new LevelPlayInterstitialAd(interstitialAdUnitId);
interstitialAd.OnAdLoaded += (LevelPlayAdInfo adInfo) => {
// PrebidSdk.LoadInterstitial(); // before 1.9.0
// PrebidSdk.FetchInterstitialDemand(); // ⚠️ deprecated in v1.20.0
PrebidSdk.FetchInterstitialDemand(PrebidInterstitialAdUnitId); // since v1.20.0
};
interstitialAd.OnAdLoadFailed += (LevelPlayAdError error) => {
// PrebidSdk.LoadInterstitial(); // before 1.9.0
// PrebidSdk.FetchInterstitialDemand(); // ⚠️ deprecated in v1.20.0
PrebidSdk.FetchInterstitialDemand(PrebidInterstitialAdUnitId); // since v1.20.0
};
interstitialAd.LoadAd();

// Create LevelPlay rewarded
rewardedAd = new LevelPlayRewardedAd(rewardedAdUnitId);
rewardedAd.OnAdLoaded += (LevelPlayAdInfo adInfo) => {
// PrebidSdk.LoadRewardedAd(); // before v1.9.0
// PrebidSdk.FetchRewardedDemand(); // ⚠️ deprecated in v1.20.0
PrebidSdk.FetchRewardedDemand(PrebidRewardedAdUnitId); // since v1.20.0
};
rewardedAd.OnAdLoadFailed += (LevelPlayAdError error) => {
// PrebidSdk.LoadRewardedAd(); // before v1.9.0
// PrebidSdk.FetchRewardedDemand(); // ⚠️ deprecated in v1.20.0
PrebidSdk.FetchRewardedDemand(PrebidRewardedAdUnitId); // since v1.20.0
};
rewardedAd.LoadAd();
}

// Records which demand won the latest auction, so the ad can be shown later
enum AdWinner { None, S2S, Mediation }
AdWinner interstitialWinner = AdWinner.None;
AdWinner rewardedWinner = AdWinner.None;

void ShowInterstitial()
{
if (interstitialWinner == AdWinner.None) {
// No ad to show
return;
}
// since v1.20.0, pass the ad unit id you want to check / show
if (interstitialWinner == AdWinner.S2S && PrebidSdk.IsInterstitialReady(PrebidInterstitialAdUnitId)) {
PrebidSdk.ShowInterstitial(PrebidInterstitialAdUnitId);
} else if (interstitialAd.IsAdReady()) {
interstitialAd.ShowAd();
} else {
// Ad not ready to show
}
}

void ShowRewardedAd()
{
if (rewardedWinner == AdWinner.None) {
// No ad to show
return;
}
// since v1.20.0, pass the ad unit id you want to check / show
if (rewardedWinner == AdWinner.S2S && PrebidSdk.IsRewardedAdReady(PrebidRewardedAdUnitId)) {
PrebidSdk.ShowRewardedAd(PrebidRewardedAdUnitId);
} else if (rewardedAd.IsAdReady()) {
rewardedAd.ShowAd();
} else {
// Ad not ready to show
}
}