Getting started with the TWA SDK
This guide walks you through the initial setup of Adtrace in a Trusted Web Activity (TWA) app. You'll configure the native Android shell, pass device IDs to the Web SDK through the launch URL, initialize the Web SDK, and verify that your integration is successful. By the end of this guide, your TWA app will be ready to track installs, sessions, and events from the web layer.
How TWA works with Adtrace
Trusted Web Activity (TWA) apps load a web UI inside a native Android shell. Unlike WebView with the WebBridge plugin, there is no stable channel between native Android code and the loaded web page after launch.
For Adtrace, that means:
- Native Android reads device IDs (for example
gps_adid) before the TWA opens. - Launch URL query parameters are the only reliable way to pass those IDs to the web app.
- Web SDK sends install, session, and event traffic from the web layer after
initSdkreceives the IDs.
See the TWA example project for a working reference implementation.
TWA launcher approaches (background)
Google provides three common ways to launch a TWA. Adtrace requires manual code so you can delay launch until device IDs are ready.
| Approach | Adtrace support | Notes |
|---|---|---|
Declarative manifest (LauncherActivity in XML only) | Not supported | Cannot delay launch or append query parameters |
Custom launcher activity (subclass LauncherActivity) | Recommended | This guide uses this approach |
Fully manual (TrustedWebActivityIntentBuilder) | Supported | Use when TWA opens from a native button or custom flow |
Core Google libraries:
androidx.browser:browser— low-level Custom Tabs and TWA componentscom.google.androidbrowserhelper:androidbrowserhelper— splash screen, fallbacks, and launcher helpers
If your app launches the PWA immediately from the manifest with no custom code, you cannot pass gps_adid to the Web SDK. Use a custom launcher activity instead.
1. Add dependencies
Add the TWA helper, Adtrace Android SDK (for getGoogleAdId), and Google Play Services Ads Identifier to your app build.gradle:
dependencies {
implementation 'com.google.androidbrowserhelper:androidbrowserhelper:2.6.2'
implementation 'io.adtrace:android-sdk:2.6.1'
implementation 'com.google.android.gms:play-services-ads-identifier:18.2.0'
}
Replace the versions with the latest compatible releases from Maven Central and the Android SDK releases page.
2. Set up Proguard
If you use Proguard or R8, add these rules so required classes are not removed:
-keep class io.adtrace.sdk.** { *; }
-keep interface io.adtrace.sdk.** { *; }
-keep enum io.adtrace.sdk.** { *; }
-keep class com.google.android.gms.common.ConnectionResult {
int SUCCESS;
}
-keep class com.google.android.gms.ads.identifier.AdvertisingIdClient {
com.google.android.gms.ads.identifier.AdvertisingIdClient$Info getAdvertisingIdInfo(android.content.Context);
}
-keep class com.google.android.gms.ads.identifier.AdvertisingIdClient$Info {
java.lang.String getId();
boolean isLimitAdTrackingEnabled();
}
3. Fetch device IDs and build the launch URL
In your main launcher activity, read gps_adid (and any other IDs you need) before opening the TWA. Append them as query parameters on the launch URL.
| Method | Purpose |
|---|---|
shouldLaunchImmediately() → false | Prevents auto-launch until native data is ready |
AdTrace.getGoogleAdId(...) | Reads gps_adid from Google Play Services |
launchTwa() | Opens the TWA after IDs are available |
getLaunchingUrl() | Returns the PWA URL with query parameters appended |
- Java
- Kotlin
package com.example.twa;
import android.net.Uri;
import android.os.Bundle;
import io.adtrace.sdk.AdTrace;
public class LauncherActivity extends com.google.androidbrowserhelper.trusted.LauncherActivity {
private String mGoogleAdId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AdTrace.getGoogleAdId(this, googleAdId -> {
mGoogleAdId = googleAdId != null ? googleAdId : "";
launchTwa(); // Call only when all required parameters are ready
});
}
@Override
protected boolean shouldLaunchImmediately() {
return false;
}
@Override
protected Uri getLaunchingUrl() {
Uri base = Uri.parse("YOUR_WEB_PAGE_BASE_URL");
return base.buildUpon()
.appendQueryParameter("gps_adid", mGoogleAdId != null ? mGoogleAdId : "")
.build();
}
}
package com.example.twa
import android.net.Uri
import android.os.Bundle
import io.adtrace.sdk.AdTrace
class LauncherActivity : com.google.androidbrowserhelper.trusted.LauncherActivity() {
private var googleAdId: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
AdTrace.getGoogleAdId(this) { adId ->
googleAdId = adId ?: ""
launchTwa() // Call only when all required parameters are ready
}
}
override fun shouldLaunchImmediately(): Boolean = false
override fun getLaunchingUrl(): Uri {
val base = Uri.parse("YOUR_WEB_PAGE_BASE_URL")
return base.buildUpon()
.appendQueryParameter("gps_adid", googleAdId ?: "")
.build()
}
}
Use the same query parameter key on native and web (for example gps_adid). You can append additional IDs or a push token the same way. If you also fetch a push token, call launchTwa() only after both values are ready.
If your web app redirects unauthenticated users to /login, launch URL parameters can be lost. See FAQ.
4. Create the Application class
Create a global Application class if you do not have one. No Adtrace native init is required for the basic TWA flow; native code only reads device IDs.
- Java
- Kotlin
package com.example.twa;
import android.app.Application;
public class GlobalApplication extends Application {
}
package com.example.twa
import android.app.Application
class GlobalApplication : Application()
Register the class in AndroidManifest.xml:
<application
android:name=".GlobalApplication">
<!-- ... -->
</application>
5. Add permissions and configure AndroidManifest.xml
Required permissions
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Google Advertising ID (AD_ID)
If your app targets Android 12 (API level 31) or higher, add:
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />
Complete manifest example
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.twa">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />
<application
android:name=".GlobalApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
android:usesCleartextTraffic="true">
<activity
android:name=".LauncherActivity"
android:exported="true"
android:launchMode="singleTask"
android:theme="@android:style/Theme.Translucent.NoTitleBar">
<meta-data
android:name="android.support.customtabs.trusted.DEFAULT_URL"
android:value="YOUR_WEB_PAGE_BASE_URL" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" android:host="YOUR_DEEP_LINK_BASE_URL" />
</intent-filter>
</activity>
<meta-data
android:name="asset_statements"
android:resource="@string/asset_statements" />
<meta-data
android:name="web_manifest_url"
android:value="YOUR_TWA_BASE_HOST_URL/manifest.json" />
<meta-data
android:name="twa_generator"
android:value="pwabuilder" />
</application>
</manifest>
Replace placeholder URLs with your PWA host, deep link host, and web manifest path.
6. Add the web app manifest
Create manifest.json in your web app (or assets folder, depending on your TWA setup):
{
"name": "TWA App",
"short_name": "TWA App",
"start_url": "/",
"scope": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#ffffff",
"icons": [
{
"src": "/icons/icon-192.svg",
"sizes": "192x192",
"type": "image/svg+xml"
},
{
"src": "/icons/icon-512.svg",
"sizes": "512x512",
"type": "image/svg+xml"
}
]
}
7. Initialize the Web SDK
Install and load the Adtrace Web SDK in your PWA. See the Web SDK integration guide for script setup, NPM install, and full initSdk options.
For TWA, parse launch URL query parameters before calling initSdk:
function getQueryParam(name) {
const params = new URLSearchParams(window.location.search);
return params.get(name);
}
const gpsAdid = getQueryParam('gps_adid'); // Must match the native query key
Adtrace.initSdk({
appToken: 'YOUR_APP_TOKEN',
environment: 'sandbox', // Use 'production' before release
gps_adid: gpsAdid,
});
Replace YOUR_APP_TOKEN with your app token from the Adtrace panel.
Use environment: 'sandbox' while testing and 'production' before you publish.
TWA device ID parameters
Pass any IDs you appended on the native launch URL into initSdk:
| Parameter | Description |
|---|---|
gps_adid | Google Advertising ID (Android) |
idfa | IDFA (iOS, if applicable) |
oaid | Huawei Advertising ID |
android_uuid | Android ID |
fb_id | Facebook advertising ID |
fire_adid | Amazon Advertising ID |
persistent_ios_uuid | Persistent iOS ID |
ios_uuid | iOS ID |
idfv | IDFV |
primary_dedupe_token | Primary dedupe token |
push_token | Push token sent with each request |
After Web SDK init, continue with Web layer for events, callbacks, partner parameters, and attribution.
8. Test the integration
A successful install (first open after install) must be recorded before sessions and events appear correctly in Adtrace. Use the steps below to verify your integration.
Install is recorded only when the app runs on a physical mobile phone or an emulator with Google Play support. On other device types, Adtrace treats the device as non-mobile and does not record an install.
Prepare a clean test device
To trigger a real install for testing:
- Use a phone that has never installed your app, or uninstall the app from the device.
- Reset the Google Advertising ID (
gps_adid): open Settings → Google → Ads → Google Advertising ID (or Reset advertising ID), then reset it. - Install and open the app again.
If you use an emulator, use an AVD image that includes Google Play. Emulators without Google Play cannot provide a valid Google Advertising ID.
You can find your Google Advertising ID (gps_adid) on the device under Settings → Google → Ads.
Test in the Adtrace panel
If you use the Adtrace panel:
- Copy your device Google Advertising ID (
gps_adid) from Settings → Google → Ads. - Open the Adtrace panel, select your app, then go to Settings → Testing Console.
- Enter the device ID, choose the ID type (
gps_adid), and check whether an install is recorded for that device.
If no install appears, review the earlier setup steps and the example apps, then try again on a clean device.
If gps_adid is missing or install still fails, see FAQ.
Checklist
Before you move on, confirm you have completed:
- Added TWA helper, Adtrace Android SDK, and Play Services Ads Identifier dependencies
- Added Proguard/R8 keep rules (if you use Proguard or R8)
- Set
shouldLaunchImmediately()tofalseand delayedlaunchTwa()until IDs are ready - Appended device IDs to the launch URL with matching keys on native and web
- Declared
INTERNET,ACCESS_NETWORK_STATE, andAD_IDpermissions - Configured
LauncherActivityandGlobalApplicationinAndroidManifest.xml - Initialized the Web SDK with parsed query parameters on first page load
- Verified a successful install in the Testing Console on a mobile device