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
getVisibility, which don't return the expected
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. Your feedback on this proposal is encouraged.
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 the
alpha [float]: The opacity of the
onScreenGeometry [Rect]: The subset of
uiContainerGeometrywhich is not clipped by parent views, up to and including the
occludedGeometry [Rect]: The parts of the
onScreenGeometrywhich are obstructed by any views in the application's hierarchy. Includes a
Rectfor each occlusion, corresponding to zero, one, or more app views that intersect with the
- Values for
occludedGeometryare expressed in the coordinate space of the
- 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.
The client library listens to changes in the ad UI through event listeners such
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.
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 the
Sessionclass, 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 cached
AdContainerInforight away. If registered before the session is opened, they will be sent
AdContainerInfowhen 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 on
Viewand 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 an
AdContainerInfoobject. 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, and
SessionObserver.notifyAdContainerChanged()is also called when this happens.
SessionObserverotifySessionClosed(): Notifies the observer that the session has been closed.
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.
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.
We invite feedback on the following points:
- 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
setTrustedPresentationCallbackyourself, or for the provider UI library to drop data from the client UI library, when it doesn't match
- How do you consume viewability signals? Help us understand your use cases by filing feedback that answers these questions.