Bid floors in LevelPlay

Setup in LevelPlay

LevelPlay enables partners to dynamically set bid floor prices using the "Price limitations using waterfall configuration". For every ad opportunity, you first obtain a floor price from Nefta, then request an ad from LevelPlay with that bid floor in adConfiguration. If no ad is returned, you adhere to the provider specified delay and then repeat the process, by first obtaining a new floor price (which is adapted in real time and takes the previous no fill into consideration) and then requesting another ad as before.


Request user insights

Via the SDK, partners will request user specific ad format insight: Ìnsights.Banner, Insights.Interstitial, Insights.Rewarded:

Adapter.GetInsights(Insights.Interstitial, (Insights insights) => {
   _requestedFloorPrice = 0f;
   _usedInsight = insights._interstitial;
   if (_usedInsight != null) {
      _requestedFloorPrice = _usedInsight._floorPrice;
   }
}, 5);
NeftaPlugin._instance.GetInsights(Insights.Interstitial, callback: { insights in
   _requestedFloorPrice = 0
   _usedInsight = insights._interstitial
   if let interstitialInsight = _usedInsight {
      _requestedFloorPrice = interstitialInsight._floorPrice
   }
}
NeftaPlugin._instance.GetInsights(Insights.INTERSTITIAL, (Insights insights) -> {
   _requestedFloorPrice = 0;
   _usedInsight = insights._interstitial;
   if (_usedInsight != null) {
      _requestedFloorPrice = _usedInsight._floorPrice;
   }
}, 5);
🚧

Validate returned values

It is crucial a partner checks the values received are valid. Only if a valid response is received, a partner should proceed with using the values.

You are guaranteed to receive the callback in the same thread with all keys that you specified in the request.

Using the _floorPrice calculated above, request an ad with that bid floor.


Log ad request

When making and request, either from insight (ie., personalised price for that user), requested an ad in IronSource using the insights.[_banner|_interstitial|_rewarded]._floorPrice field or default (backfill) request log it with:

Adapter.OnExternalMediationRequest(_dynamicInterstitial, _dynamicInsight);
// or:
Adapter.OnExternalMediationRequest(_defaultInterstitial);
ISNeftaCustomAdapter.onExternalMediationRequest(withInterstitial: _dynamicInterstitial!, adUnitId: _dynamicAdUnitId, insight: _dynamicInsight)
// or:
ISNeftaCustomAdapter.onExternalMediationRequest(withInterstitial: _defaultInterstitial!, adUnitId: _defaultAdUnitId, insight: nil)
NeftaCustomAdapter.OnExternalMediationRequest(_dynamicInterstitial, _dynamicInsight);
// or:
NeftaCustomAdapter.OnExternalMediationRequest(_defaultInterstitial);

Log outcome of ad opportunity

The partner should log the outcome of the ad opportunity in order to continuously maximise ad revenue uplift with the following:

private void OnAdLoaded(LevelPlayAdInfo info)
{
  Adapter.OnExternalMediationRequestLoaded(info);
}

private void OnAdLoadFailed(LevelPlayAdError error)
{
  Adapter.OnExternalMediationRequestFailed(error);
}
func didLoadAd(with adInfo: LPMAdInfo) {
  ISNeftaCustomAdapter.onExternalMediationRequestLoad(adInfo)
}

func didFailToLoadAd(withAdUnitId adUnitId: String, error: any Error) {
  let lpError = error as NSError
  ISNeftaCustomAdapter.onExternalMediationRequestFail(lpError)
}
@Override
public void onAdLoaded(@NonNull LevelPlayAdInfo adInfo) {
  NeftaCustomAdapter.OnExternalMediationRequestLoaded(adInfo);
}

@Override
public void onAdLoadFailed(@NonNull LevelPlayAdError error) {
  NeftaCustomAdapter.OnExternalMediationRequestFailed(error);
}

Log Impression

In case you opted out of automatic impression collection when initializing Nefta SDK forward the impression manually:

// forward the impression manually only if you inited SDK like this:
Adapter.Init(_neftaAppId, false);
            
LevelPlay.OnImpressionDataReady += Adapter.OnLevelPlayImpression;
// forward the impression manually only if you inited SDK like this:
ISNeftaCustomAdapter.initWithAppId("5759667955302400", sendImpressions: false)

LevelPlay.add(ISNeftaImpressionCollector())
// forward the impression manually only if you inited SDK like this:
NeftaCustomAdapter.Init(MainActivity.this, "appId", false, null);

LevelPlay.addImpressionDataListener(new LevelPlayImpressionDataListener() {
  @Override
  public void onImpressionSuccess(LevelPlayImpressionData levelPlayImpressionData) {
    NeftaCustomAdapter.OnExternalMediationImpression(levelPlayImpressionData);
  }
});

Log ad interaction

To get the best insights also track player interaction with an ad. On IronSource on ad click callback log that with:

private void OnAdClicked(LevelPlayAdInfo info)
{
  Adapter.OnLevelPlayClick(info);
}
func didClickAd(with adInfo: LPMAdInfo) {
  ISNeftaCustomAdapter.onExternalMediationClick(adInfo)
}
@Override
public void onAdClicked(@NonNull LevelPlayAdInfo adInfo) {
  NeftaCustomAdapter.OnExternalMediationClick(adInfo);
}

Initial bid floor price has no fill

If the initially selected ad unit doesn't return an ad:

  • Re-request ad insight: the new floor price takes into account the previous no-fill event and is adjusted in real time. You can repeat this process for each ad opportunity. However, latency should be considered if requesting multiple times per ad opportunity. Nefta will help in balancing fill %, revenue uplift and latency.
  • Request an ad from LevelPlay without a floor price set.

Complete Example

Demonstration project: Integration example