prebid-mobile-android icon indicating copy to clipboard operation
prebid-mobile-android copied to clipboard

Intent to implement Rendering Delegation on Prebid

Open github-antoine-barrault opened this issue 2 years ago • 5 comments

Description

We want to help you to implement Rendering Delegation, from which we will have a use case. Today we serve creatives that need special features only available on our SDK. As it is present in Prebid documentation: Rendering Delegation: The module will potentially delegate rendering of the winning bid to the Demand Partner SDK if it is required for special creatives. What was described in your docs as a potential feature. This PR represents a proposal of all the changes that need to be made in order to be able to offer rendering delegation for any partners.

Goals

The main goal of this PR is to get approval for the design we are going to implement in order to make rendering delegation a reality.

Shortly the points that are needed to be validated are:

  • Standardize a new parameter to send available third-party renderers inside the bid request
  • Pass this information (third-party renderers available) to the bid adapters inside the Prebid server
  • Make sure Prebid Server and Bid Adapters send back, in case of a custom rendering, a new attribute that indicates the custom render that needs to be used.
  • The way a custom renderer can be called and where this delegation should happens

Big picture design

Rendering delegation proposal

In-Scope

  • Method in the SDK to inform Prebid Server that custom renderer are available
  • Update of the Prebid Server to treat the parameter third_party_renderers
  • add a way on prebid server to pass extra infos to bid adapter
  • Create a way to pass hb_preferred_renderer parameter from bid adapter to PBS
  • Create a way to pass hb_preferred_renderer parameter from PBS inside the bid response
  • Parse hb_preferred_renderer parameter inside prebid mobile SDK
  • Adding a switch logic inside the rendering view to call external renderer if hb_preferred_renderer parameter is present
  • Let a third-party SDK renderer creatives

Prebid SDK Changes

We will present a solution to allows custom renderer to display Prebid ad for banner, interstitial and reward format. We will share snippets of code that are here for example and illustration, to explains better the concept, the real implementation can differ. For now we will present Android implementation only, but we can considere that the iOS part will be similare.

Passing the information that third party renderers are available

The Bid adapter need to have a way to know if custom renderers are available in order to be able to deliver specials creatives. A simple representation for it, is an array of strings something like: [“custom_renderer_1”, “custom_renderer_2”]. We can call it third_party_renderers inside the openRTB representation.

To pass the information to the bid adpaters we can simply use the context data and passing a new key/value tuple.

TargetingParams.addContextData("third_party_renderers", "[teads]")

A more robust alternative can be to implement a new global targeting parameter like User Keywords that will allow the publisher or third party SDKs to pass new strings (the supported custom renderers) to this object. TargetingParams.addCustomRenderer("custom_renderer_1")

Define a new interface AdRenderer

In order to delegate the ad rendering we decide to create an AdRenderer interface that is responsible for providing all the objects needed to display an ad received in a bid response. In the scope of our proposal, we can imagine an interface providing the methods to have a banner view and an interstitial controller.

public interface AdRenderer {

    View getBannerAdView(@NonNull Context context,
                         DisplayViewListener listener,
                         @NonNull AdUnitConfiguration adUnitConfiguration,
                         @NonNull BidResponse response);

    InterstitialControllerInterface getInterstitialController(Context context, 
                                                              InterstitialControllerListener listener);
}

Invoke an Ad Renderer

We propose two solutions, by reflexivity or by singleton. For the two cases, we assume that the bid response contains in bid.ext.prebid.targetting.hb_preferred_renderer an array with the package of the custom library renderer. For example for the Teads renderer, it could be ['tv.teads.prebid.renderer']. Following the two snippets that represents both implementations A and B.

A - By Reflexivity

@Nullable 
public static AdRenderer retrieveCustomRenderer(List<String> rendererPackageNames) {
    for (String packageRenderer : rendererPackageNames) {
        try {
            Class<?> c = Class.forName(packageRenderer);
            Constructor<?> constructor = c.getConstructor();
            Object testObject = constructor.newInstance();
            return (AdRenderer) testObject;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    return null;
}

B - By Singleton

This is done in two steps:

  • For the first one, the app developer have to provide the custom renderer through a singleton store.
CustomRendererStore.getInstance().customRenderers.put("tv.teads.prebid.renderer", TeadsRenderer())
  • In the second step, the prebid mobile sdk invoke the custom renderer by calling the singleton
@Nullable
public static AdRenderer retrieveCustomRendererBySingleton(List<String> rendererPackageNames) {
    for (String packageRenderer : rendererPackageNames) {
        AdRenderer renderer = CustomRendererStore.getInstance().customRenderers.get(packageRenderer);
        if (renderer != null) {
            return renderer;
        }
    }
    return null;
}

Use of the ad renderer

For banner ad

The choice of the ad renderer can be done inside the DisplayView. To avoid a heavy breaking change, one solution to achieve it, is to move the logic inside DisplayView to a new layer, for example a DefaultRenderer which will implement a RendererInterface. The DisplayView will only have the responsibility to select the right renderer and provide the event for the DisplayViewListener.

public class DisplayView extends FrameLayout {
    private View rendererAdView;

    public DisplayView(
            @NonNull Context context,
            DisplayViewListener listener,
            @NonNull AdUnitConfiguration adUnitConfiguration,
            @NonNull BidResponse response
    ) {
        super(context);

        WinNotifier winNotifier = new WinNotifier();
        winNotifier.notifyWin(response, () -> {
            adUnitConfiguration.modifyUsingBidResponse(response);
            rendererAdView = chooseThePreferredRenderer(response).getBannerAdView(context, listener, adUnitConfiguration, response);
            addView(rendererAdView);
        });
    }

    private RendererInterface chooseThePreferredRenderer(
            @NonNull BidResponse response) {

        List<String> rendererPackages = response.getPreferredRenders();
        RendererInterface renderer = null;
        if (rendererPackages != null && rendererPackages.size() > 0) {
            renderer = CustomRendererUtils.retrieveCustomRendererByReflexivity(rendererPackages);
        }
        if (renderer == null) {
            renderer = new DefaultRenderer();
        }
        return renderer;
    }
}

For interstitial and reward ad

The best option is to choose the renderer in the BaseInterstitialAdUnit class. Once the bid request is received, we could initialize the interstitialControler by getting it from the chosen renderer.

protected void loadPrebidAd() {
        List<String> renderedPackages = bidResponse.getPreferredRenders();
        if (renderedPackages != null && renderedPackages.size() > 0) {
            AdRenderer customRenderer = CustomRendererUtils.retrieveCustomRendererByReflexivity(renderedPackages);
            if (customRenderer != null) {
                interstitialController = customRenderer.getInterstitialController(getContext(), controllerListener);
            }
        }

        interstitialController.loadAd(adUnitConfig, bidResponse);
    }

Prebid Server OpenRTB Changes

Their will be two news parameters to add inside openRTB requests.

On bid request

A new parameter will be added by the Prebid Mobile SDK that represents the fact that there is or not custom renderers available. The parameter will be called third_party_renderers and will be an array of strings.

On bid response

A new parameter will be added by the Prebid server/bid adpater that will indicate that the creative should be rendered by a specific renderer. The parameter will be called hb_preferred_renderer and will be a string.

Prebid Server Changes

The Prebid server will need to handle the new parameters defined on the OpenRTB changes defined above. Also every bidders that wants to use a custom renderer for special creative.

github-antoine-barrault avatar Oct 31 '22 17:10 github-antoine-barrault

Adding this here for tomorrow's discussion PBS-with-SDK-Bidding

mmullin avatar Nov 14 '22 20:11 mmullin

Here is a short follow-up for the kick-off call.

  • The Teads team is starting to implement rendering delegation in the prebid repositories according to the spec above.
  • The spec is not final and should be updated respectively to the challenges and solutions that emerged in the development process.
    • @github-antoine-barrault, please update your first image with the description of rtb changes due to the Mikes spec.
  • The Teads team will prepare a PBS ticket in order to support third_party_renderers and prefered_renderer extensions.
  • The supported formats are Display, Video for ad units Banner, and Interstitial. Native format - TBD.

Open Questions:

  • @mmullin, please clarify the purpose and use cases of the token that the rendering plugin should send to PBS. Also, please, clarify whether it is expected to be a constant value for lifetime / app sessions or dynamic for each bid request.
  • plugin registration approach. During the development, we will use the singleton approach proposed in the issue, and we will try to discover whether we need a reflexive one (@elneruda, please describe the case that you mention on the call).
  • does it make sense to introduce the plugins repository for Prebid Mobile in order to keep all available plugins in the same place and have the ability to automatically discover them in runtime, so publishers don't need to register plugins manually? This is a question for the community.

cc: @mittal-ank

YuriyVelichkoPI avatar Nov 17 '22 08:11 YuriyVelichkoPI

Would it be reasonable to tie certain bidder codes to the preferred renderer rather than creating another targeting parameter? Or perhaps just an ORTB extension in the response, e.g. seatbid.bid.ext.prebid.renderer ?

bretg avatar Dec 07 '22 21:12 bretg

Short note from Bret seatbid.bid.ext.prebid.meta.rendering_api

YuriyVelichkoPI avatar Jul 06 '23 15:07 YuriyVelichkoPI

Added a protocol proposal to https://github.com/prebid/prebid-server/issues/2908

bretg avatar Jul 06 '23 19:07 bretg

Closed as this has been done on Android and is in development on iOS.

jsligh avatar Jun 03 '24 14:06 jsligh