Ads SDKs in the SDK Runtime are not able to access a publisher's view hierarchy.
Instead, SDKs in the Runtime have their own views. The SDK cannot use the same
View APIs as they use outside the SDK runtime to determine whether the ad is
visible to the user, because the ad view is not attached to the application's
window. This includes Android View APIs like getLocationOnScreen
,
getLocationInWindow
, or getVisibility
, which don't return the expected
values.
Supporting ads viewability measurement is a core SDK Runtime requirement. This design proposal aims to achieve support for Open Measurement and similar measurement services. The solutions discussed here might also be applicable to the Attribution Reporting APIs.
Capabilities
This design aims to support ads SDKs or measurement partners to compute the following viewability data (names are provisional and subject to change):
viewport [Rect]
: Represents the device screen or the app window geometry, depending on the capabilities of the platform.uiContainerGeometry [Rect]
: The geometry of theSandboxedSdkView
being rendered.alpha [float]
: The opacity of theSandboxedSdkView
being rendered.onScreenGeometry [Rect]
: The subset ofuiContainerGeometry
which is not clipped by parent views, up to and including theviewport
).occludedGeometry [Rect]
: The parts of theonScreenGeometry
which are obstructed by any views in the application's hierarchy. Includes aRect
for each occlusion, corresponding to zero, one, or more app views that intersect with theSandboxedSdkView onScreenGeometry
Requirements
- Values for
uiContainerGeometry
,onScreenGeometry
, andoccludedGeometry
are expressed in the coordinate space of theviewport
. - Visibility change reporting occurs with minimal latency.
- Visibility is measurable for the full lifecycle of the ad view, from its first appearance to its last.
Design proposal
This proposal builds on how UI presentation works using the client and provider UI libraries. We will extend the UI libraries to allow the SDK to register one or more observers of the UI session. The observer will receive viewability information whenever relevant events that modify the data types in the capabilities section are detected. Measurement SDKs in the SDK runtime (OMID and MRAID implementations) can attach this observer to the UI session, so that this information can be sent to them directly. Measurement partners can combine information obtained from UI libraries with data about content already available (such as when using measurement scripts injected in the ad creative) to generate JavaScript viewability events.
The client library listens to changes in the ad UI through event listeners such
as ViewTreeObserver
. Whenever it determines that the ad UI has changed in a
way that might affect viewability measurement, the client library checks when
the last notification was sent to the observer. If the last update is greater
than the allowed latency (configurable by the SDK, up to a minimum of 200ms on
mobile), a fresh AdContainerInfo
object is created and a notification is
dispatched to the observer. This event-based model is better for system health
than the polling done by most OMID implementations on Android today.
API
The following will be added to the privacysandbox.ui.core library:
SessionObserver
: Typically implemented by the measurement SDK, attached to the session returned by the SDK through the privacysandbox.ui. This interface will also enable the measurement SDK to opt-in to certain categories of viewability signals. This in turn, enables the UI client library to only collect signals the observer is interested in, which is better for system health overall.registerObserver()
: Added to theSession
class, this method allows anyone with access to the Session to register an observer. If the observer is registered after the UI session has been opened, they will be sent the cachedAdContainerInfo
right away. If registered before the session is opened, they will be sentAdContainerInfo
when the session is opened.AdContainerInfo
: A class with getters that enables the observer to obtain read-only ad container information for the data types listed in the capabilites section above. The return values from these getters will correspond, wherever possible, to the parcelable return values from existing getters onView
and its subclasses. If the ad container has been created using Jetpack Compose, this exposes the container's semantic properties. This class can be used to compute MRAID and OMID events related to viewability.SessionObserverotifyAdContainerChanged()
: Used to notify the observer whenever viewability changes. It passes anAdContainerInfo
object. This is called whenever events are detected that affect data types listed in the Capabilities section. Note: This method might be called in addition to methods on Session. For example,Session.notifyResized()
is called to request the SDK to resize the ad, andSessionObserver.notifyAdContainerChanged()
is also called when this happens.SessionObserverotifySessionClosed()
: Notifies the observer that the session has been closed.
Future enhancements
Any code running in the application process, including the code from the privacysandbox.ui.client library, can be modified if the application is compromised. Therefore, any signal collection logic that runs in the application process is prone to tampering by application code. This applies also to SDK code deployed prior to the availability of Privacy Sandbox that runs in the application process. Consequently, signal collection by the UI library does not make the security situation worse.
Additionally, code in the SDK runtime can use a platform API called
setTrustedPresentationCallback
that can give it stronger guarantees from
the framework about the ad UI presentation. setTrustedPresentationCallback
works at the Surface level, and can help make assertions about the Surface
containing the ad UI by specifying minimum thresholds for presentation, such as
the percentage of pixels visible, time on screen, or scale. This data can be
checked against viewability data provided by the UI client library, explained
above. Since the framework-provided data is more reliable, any events from the
UI library whose data are not in agreement with data from the framework can be
discarded. For example, if the listener provided to
setTrustedPresentationCallback
is invoked with a notification that no pixels
of the ad UI are being shown on the screen, and the client UI library shows a
non-zero number of pixels on screen, data from the latter can be discarded.
Open questions
- What viewability signals are you interested in that aren't mentioned in this explainer?
- The current proposal is to update viewability no less frequently than every 200 milliseconds, provided there is a relevant change in the UI. Is this frequency acceptable to you? If not, what frequency would you prefer?
- Do you prefer to analyze information from
setTrustedPresentationCallback
yourself, or for the provider UI library to drop data from the client UI library, when it doesn't matchsetTrustedPresentationCallback
data? - How do you consume viewability signals? Help us understand your use cases by filing feedback that answers these questions.