Optimize Custom Tabs

The web view APIs for ads makes app signals available to the tags in your CustomTabSession, helping to improve monetization for the web publishers that provided the content and to protect advertisers from spam.

How it works

Communication with the GMA Next-Gen SDK only happens in response to ad events triggered by any of the following:

The GMA Next-Gen SDK facilitates communication by opening a postMessage channel with the CustomTabsSession provided by the Android framework.

Prerequisites

Pass the application ID to the SDK

If you already have an AdMob application ID, initialize the GMA Next-Gen SDK with your existing application ID.

If you don't have an AdMob application ID, pass in InitializationConfig.WEBVIEW_APIS_FOR_ADS_APPLICATION_ID as the application ID when you initialize the GMA Next-Gen SDK:

Kotlin

MobileAds.initialize(
this@MainActivity,
// Use this application ID to initialize the GMA Next-Gen SDK if
// you don't have an AdMob application ID.
InitializationConfig.Builder(InitializationConfig.WEBVIEW_APIS_FOR_ADS_APPLICATION_ID)
.build(),
){
// Adapter initialization complete.
}

Java

MobileAds.initialize(
this,
// Use this application ID to initialize the GMA Next-Gen SDK if
// you don't have an AdMob application ID.
newInitializationConfig.Builder(InitializationConfig.WEBVIEW_APIS_FOR_ADS_APPLICATION_ID)
.build(),
initializationStatus->{
// Adapter initialization is complete.
});

Implementation

Within your Chrome Custom Tabs implementation, modify the code in the onCustomTabsServiceConnected() callback. Replace newSession() with MobileAds.registerCustomTabsSession(). This establishes a connection with the postMessage channel to enrich the ad tags with SDK signals. A Digital Asset Link is needed to connect the postMessage channel. Optionally, you can set the CustomTabsCallback parameter to listen for Chrome Custom Tab events.

You should still be able to send messages from the CustomTabsSession received from the GMA Next-Gen SDK but the port could change when the SDK requests a new channel that overrides the existing one.

The following code snippet shows how to register a CustomTabsSession using the GMA Next-Gen SDK:

Kotlin

importcom.google.android.libraries.ads.mobile.sdk.MobileAds
classMainActivity:ComponentActivity(){
privatevarcustomTabsClient:CustomTabsClient? =null
privatevarcustomTabsSession:CustomTabsSession? =null
overridefunonCreate(savedInstanceState:Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Get the default browser package name, this will be null if
// the default browser does not provide a CustomTabsService.
valpackageName=CustomTabsClient.getPackageName(applicationContext,null);
if(packageName==null){
// Do nothing as service connection is not supported.
return
}
CustomTabsClient.bindCustomTabsService(
applicationContext,
packageName,
object:CustomTabsServiceConnection(){
overridefunonCustomTabsServiceConnected(
name:ComponentName,client:CustomTabsClient,
){
customTabsClient=client
// Warm up the browser process.
customTabsClient?.warmup(0L)
// Create a new browser session using the GMA Next-Gen SDK.
customTabsSession=MobileAds.INSTANCE.registerCustomTabsSession(
client,
// Checks the "Digital Asset Link" to connect the postMessage channel.
ORIGIN,
// Optional parameter to receive the delegated callbacks.
customTabsCallback
)
// Create a new browser session if the GMA Next-Gen SDK is
// unable to create one.
if(customTabsSession==null){
customTabsSession=client.newSession(customTabsCallback)
}
// Pass the custom tabs session into the intent.
valcustomTabsIntent=CustomTabsIntent.Builder(customTabsSession).build()
customTabsIntent.launchUrl(this@MainActivity,
Uri.parse("YOUR_URL"))
}
overridefunonServiceDisconnected(componentName:ComponentName){
// Remove the custom tabs client and custom tabs session.
customTabsClient=null
customTabsSession=null
}
})
}
// Listen for events from the CustomTabsSession delegated by the GMA Next-Gen SDK.
privatevalcustomTabsCallback:CustomTabsCallback=object:CustomTabsCallback(){
@Synchronized
overridefunonNavigationEvent(navigationEvent:Int,extras:Bundle?){
// Called when a navigation event happens.
}
@Synchronized
overridefunonMessageChannelReady(extras:Bundle?){
// Called when the channel is ready for sending and receiving messages on both
// ends.
// This frequently happens, such as each time the SDK requests a
// new channel.
}
@Synchronized
overridefunonPostMessage(message:String,extras:Bundle?){
// Called when a tab controlled by this CustomTabsSession has sent a postMessage.
}
overridefunonRelationshipValidationResult(
relation:Int,requestedOrigin:Uri,result:Boolean,extras:Bundle?
){
// Called when a relationship validation result is available.
}
overridefunonActivityResized(height:Int,width:Int,extras:Bundle){
// Called when the tab is resized.
}
overridefunextraCallback(callbackName:String,args:Bundle?){
}
overridefunextraCallbackWithResult(callbackName:String,args:Bundle?):Bundle? {
returnnull
}
}
companionobject{
// Replace this URL with an associated website.
constvalORIGIN="https://www.google.com"
}
}

Java

importcom.google.android.libraries.ads.mobile.sdk.MobileAds;
class MainActivityextendsComponentActivity{
// Replace this URL with an associated website.
privatestaticfinalStringORIGIN="https://www.google.com";
privateCustomTabsClientcustomTabsClient;
privateCustomTabsSessioncustomTabsSession;
@Override
protectedvoidonCreate(@NullableBundlesavedInstanceState){
super.onCreate(savedInstanceState);
// Get the default browser package name, this will be null if
// the default browser does not provide a CustomTabsService.
StringpackageName=CustomTabsClient.getPackageName(getApplicationContext(),null);
if(packageName==null){
// Do nothing as service connection is not supported.
return;
}
CustomTabsClient.bindCustomTabsService(
getApplicationContext(),
packageName,
newCustomTabsServiceConnection(){
@Override
publicvoidonCustomTabsServiceConnected(@NonNullComponentNamename,
@NonNullCustomTabsClientclient){
customTabsClient=client;
// Warm up the browser process.
customTabsClient.warmup(0);
// Create a new browser session using the GMA Next-Gen SDK.
customTabsSession=MobileAds.INSTANCE.registerCustomTabsSession(
client,
// Checks the "Digital Asset Link" to connect the postMessage channel.
ORIGIN,
// Optional parameter to receive the delegated callbacks.
customTabsCallback);
// Create a new browser session if the GMA Next-Gen SDK is
// unable to create one.
if(customTabsSession==null){
customTabsSession=client.newSession(customTabsCallback);
}
// Pass the custom tabs session into the intent.
CustomTabsIntentintent=newCustomTabsIntent.Builder(customTabsSession).build();
intent.launchUrl(MainActivity.this,Uri.parse("YOUR_URL"));
}
@Override
publicvoidonServiceDisconnected(ComponentNamecomponentName){
// Remove the custom tabs client and custom tabs session.
customTabsClient=null;
customTabsSession=null;
}
}
);
}
// Listen for events from the CustomTabsSession delegated by the GMA Next-Gen SDK.
privatefinalCustomTabsCallbackcustomTabsCallback=newCustomTabsCallback(){
@Override
publicvoidonNavigationEvent(intnavigationEvent,@NullableBundleextras){
// Called when a navigation event happens.
super.onNavigationEvent(navigationEvent,extras);
}
@Override
publicvoidonMessageChannelReady(@NullableBundleextras){
// Called when the channel is ready for sending and receiving messages on both
// ends.
// This frequently happens, such as each time the SDK requests a
// new channel.
super.onMessageChannelReady(extras);
}
@Override
publicvoidonPostMessage(@NonNullStringmessage,@NullableBundleextras){
// Called when a tab controlled by this CustomTabsSession has sent a postMessage.
super.onPostMessage(message,extras);
}
@Override
publicvoidonRelationshipValidationResult(intrelation,@NonNullUrirequestedOrigin,
booleanresult,@NullableBundleextras){
// Called when a relationship validation result is available.
super.onRelationshipValidationResult(relation,requestedOrigin,result,extras);
}
@Override
publicvoidonActivityResized(intheight,intwidth,@NonNullBundleextras){
// Called when the tab is resized.
super.onActivityResized(height,width,extras);
}
@Override
publicvoidextraCallback(@NonNullStringcallbackName,@NullableBundleargs){
super.extraCallback(callbackName,args);
}
@Nullable
@Override
publicBundleextraCallbackWithResult(@NonNullStringcallbackName,@NullableBundleargs){
returnsuper.extraCallbackWithResult(callbackName,args);
}
};
}

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025年12月11日 UTC.