All articles

Technical

How to Detect if Your PWA is Running Inside a TWA

September 1, 2026 · 7 min read

When you distribute your Progressive Web App on the Google Play Store using a Trusted Web Activity, your web application runs inside a specialised, full-screen Android browser container. To the end user, this container behaves exactly like a native Android application. However, because the underlying engine is still your web application, your frontend needs to understand its operational context. An application already installed from the Google Play Store should never prompt the user to install the web app, yet this is one of the most common user experience flaws in newly converted apps.

Showing an Add to Home Screen prompt or a web-installation banner inside an app downloaded from Google Play looks unprofessional. It can confuse users and lead to immediate rejection during Google Play policy reviews. To build a polished, production-ready hybrid application, you must programmatically detect when your PWA is running inside the Android wrapper and adjust your user interface accordingly.

The Best Method: Appending a Query Parameter to the Start URL

The most robust, reliable, and industry-standard method to detect a Trusted Web Activity environment is to modify the launch URL of your application within your Android wrapper. When you convert your PWA, you configure an Android launch activity. This launcher initiates the TWA and directs it to a specific URL on your domain.

By appending a custom query parameter to this start URL, you can instantly flag the traffic source. For example, instead of launching your root domain, you can configure your TWA launcher to load a URL with a specific query parameter. Common parameters include setting the source to playstore or setting the mode to twa.

Once this parameter is present in the URL, your frontend JavaScript can detect it on load and write a persistent value to session storage. This ensures that even when the user navigates away from the landing page to other sections of your PWA, your application still remembers that it is operating within the Android app wrapper.

Consider the following JavaScript implementation to execute on your application entry point:

const urlParams = new URLSearchParams(window.location.search);

if (urlParams.get('utm_source') === 'playstore' || urlParams.get('mode') === 'twa') {

sessionStorage.setItem('app_context', 'twa');

}

By checking session storage instead of checking the active URL on every page load, you prevent the app-context flag from being lost as the user navigates deep into your internal application routes where the initial query parameter is no longer present.

Preventing the Browser Install Prompt

Once you have established the detection mechanism, your first priority is to disable web installation promotions. Modern mobile browsers fire a specific event when they detect a installable PWA. By intercepting this event, you can prevent the browser from showing the default install banner and hide your custom layout elements that encourage installation.

You can use your saved session storage flag to selectively block this behaviour. When your application loads, check if the context is set to your TWA value. If it matches, prevent the default prompt immediately.

Here is how to structure this logic inside your main JavaScript file:

window.addEventListener('beforeinstallprompt', (event) => {

const isTwa = sessionStorage.getItem('app_context') === 'twa';

if (isTwa) {

event.preventDefault();

return false;

}

});

This implementation ensures that users who have already downloaded your software via the Google Play Store are never prompted to install the web version, preserving native expectations.

Using CSS Display Mode Media Queries

Another layer of detection relies on modern CSS. The Web App Manifest defines display modes such as standalone, fullscreen, or minimal-ui. When your PWA is launched inside a TWA, it inherits the display mode defined in your manifest, which is typically standalone or fullscreen.

You can use CSS media queries to apply specific styling rules only when the application is running in an installed window context. This is highly useful for hiding website-specific navigation headers, footers, or browser-specific call-to-action buttons.

For example, you can write CSS rules that target the standalone display mode directly:

@media (display-mode: standalone) {

.web-only-navigation {

display: none;

}

.app-header {

padding-top: 20px;

}

}

However, you must note a major limitation of this approach: the standalone media query matches both a TWA running from Google Play and a standard PWA installed directly from a mobile browser like Chrome or Safari. It does not distinguish between a web-installed PWA and an app-store-installed TWA. For precise, platform-specific UI changes, the query parameter method remains necessary.

Comparing Detection Methods

To help you choose the best implementation strategy for your specific use case, the table below outlines the core differences, advantages, and limitations of each detection vector.

Detection MethodReliabilityDistinguishes TWA from Web PWAPrimary Use Case
Query ParameterHighYesHiding install banners, tracking Play Store analytics
CSS Display ModeMediumNoGeneral styling adjustments for frameless windows
Referrer HeaderLowNoServer-side initial rendering tweaks

Applying Custom Styling and Class Indicators

To keep your codebase clean and maintainable, a recommended architectural pattern is to apply a global CSS class to your document body element immediately after detecting the TWA environment. This allows your design team to write clean, scoped CSS styles for your Android app wrapper without polluting your core web styles.

You can implement this dynamically with a simple helper function:

function applyTwaStyles() {

const isTwa = sessionStorage.getItem('app_context') === 'twa';

if (isTwa) {

document.body.classList.add('platform-twa');

}

}

Once this class is appended to your body element, you can write clean, scoped CSS rules that selectively alter elements across your entire UI. For instance, you might want to hide a promotion banner, reduce high margins designed for desktop displays, or display Android-specific touch-target styles.

.platform-twa .download-promo-banner {

display: none;

}

.platform-twa .back-button-custom {

display: block;

}

Implementing these checks ensures that your Progressive Web App transitions smoothly from a standard website to a native-feeling Android application, creating a polished experience that passes Google Play review processes with ease.

Ready to ship your Android app?

Paste your PWA URL, get a signed APK and a Google Play ready AAB in minutes.

Build my app