Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Intent to implement Rendering Delegation on Prebid #507

Closed
github-antoine-barrault opened this issue Oct 31, 2022 · 6 comments
Closed

Intent to implement Rendering Delegation on Prebid #507

github-antoine-barrault opened this issue Oct 31, 2022 · 6 comments

Comments

@github-antoine-barrault

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.

@mmullin
Copy link

mmullin commented Nov 14, 2022

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

@YuriyVelichkoPI
Copy link
Contributor

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.
  • 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

@bretg
Copy link
Collaborator

bretg commented Dec 7, 2022

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 ?

@YuriyVelichkoPI
Copy link
Contributor

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

@bretg
Copy link
Collaborator

bretg commented Jul 6, 2023

Added a protocol proposal to prebid/prebid-server#2908

@jsligh
Copy link
Collaborator

jsligh commented Jun 3, 2024

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

@jsligh jsligh closed this as completed Jun 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

No branches or pull requests

5 participants