Store sheet (new) — install another app without leaving yours

After this page, a tap on Install for one of your other apps opens the store inside your app, and the installed app opens on the linked screen.

  • Task
  • ~ 20 minutes
  • Android
  • iPhone
On this page 10
  1. What it is, and where it works
  2. How it works
  3. 1. Check the installed app's details
  4. 2. Android
  5. 3. iPhone
  6. 4. React Native and Flutter
  7. 5. Test it
  8. Limits
  9. Common errors
  10. Next steps
Time
About 20 minutes
You need
Two apps in one Strait workspace (the one showing the store, and the one being installed), both set up with a Strait SDK, and a Strait link for the installed app
Works on
Android, iPhone

New. In the released SDKs (iOS 0.8.1, React Native and Flutter 0.8.2, and later). On iPhone it needs your app's App Store ID, and the deep link after install relies on install matching, which is opt-in. Taps from the store sheet are recorded but not billed while it's new.

What it is, and where it works

Some apps show the store as a sheet inside the app: the user taps Install, installs, and never leaves. The app showing the sheet does this with a store API. A link can't make another company's app do it, so a link tapped inside a social app's in-app browser can't open a store sheet there.

The store sheet works where your app is the host:

  • recommending a sibling app (a "lite", seller, partner or driver app) from your main app,
  • "invite a friend to app B" flows inside app A,
  • web content your app shows in its own WebView, when that page calls your app.

What Strait adds is the deep link. A bare store sheet drops context: the user installs app B, and app B doesn't know which screen they wanted. With openStoreSheet, app B opens on the linked screen after install.

How it works

  1. Your app calls openStoreSheet with one of your short links. Strait records the tap (sent_to = store_sheet in Analytics).
  2. Android: the SDK opens Google Play's inline install, a half-sheet over your app. Google calls inline install a test feature; when Play can't show the sheet, it shows the full listing. If inline install isn't available, the SDK opens the Play app, then the Play web page. Every one of these carries referrer=strait_link=<link>&strait_click=<tap>, the same Play Install Referrer the redirect uses, so app B's first open matches exactly.
  3. iPhone: the SDK saves this device's match details for the tap, then shows SKStoreProductViewController (the full product page as a sheet) or SKOverlay (a small card). The link's campaign goes to the App Store as the campaign token. App B's first open finds the link through iPhone install matching. If your workspace uses the clipboard boost, you can also have the SDK copy the one-time handoff link for an exact match.

1. Check the installed app's details

In Dashboard → Apps & stores, the workspace needs the installed app's Android package name and, for iPhone, its App Store ID. The SDK reads them from Strait. You can also pass them in the call.

You should see: both fields filled in for the app being installed.

2. Android

InstallButton.kt
// Off the main thread: it calls Strait first.
val result = strait.openStoreSheet(
    "https://hilltop.strait.link/promo",
    StoreLauncher { s ->
        val intent = Intent(s.action, Uri.parse(s.data)).apply {
            s.packageName?.let { setPackage(it) }
            for ((k, v) in s.extras) when (v) {
                is Boolean -> putExtra(k, v)
                is String -> putExtra(k, v)
            }
        }
        try { activity.startActivity(intent); true }
        catch (_: ActivityNotFoundException) { false }
    },
    StoreSheetOptions(callerId = activity.packageName),
)

callerId is your own package name; Play needs it for the inline sheet. Without it the SDK goes straight to the Play app.

You should see: result.method is inline_install (or market when inline install isn't available), and Play opens over your app.

3. iPhone

InstallButton.swift
strait.openStoreSheet(
    url: "https://hilltop.strait.link/promo",
    options: StoreSheetOptions(style: .productPage), // or .overlay
    presenter: SystemStoreSheetPresenter(from: viewController)
) { result in
    print(result.method) // "product_page", "overlay" or "none"
}

copyHandoffLink: true copies the clipboard boost's one-time link as well. It's off by default, because it replaces whatever the user had copied.

You should see: the App Store product page as a sheet over your app.

4. React Native and Flutter

Both SDKs have openStoreSheet with the same options. Opening the store inside the app needs a small native module, because JavaScript and Dart can't start an Android Intent or show StoreKit:

  • React Native: register a native module named StraitStoreSheet with openIntent(intent) (Android) and presentProduct(product, style) (iPhone). Without it, the SDK opens the Play app or the App Store app instead. The deep link is still kept, but the user leaves your app.
  • Flutter: pass a StoreSheetOpener. The SDK README has a MethodChannel version.

You should see: result.method is inline_install, product_page or overlay with the native module, and market or app_store without it.

5. Test it

Uninstall app B. In app A, tap your Install button, install app B from the sheet, then open it.

You should see: app B opens on the link's screen. In Dashboard → Analytics, the tap shows with sent_to = store_sheet, followed by the install.

Limits

  • It works only inside your own app. It can't open a store sheet inside another company's app.
  • Android inline install is a Google Play test feature. Play decides when the sheet shows.
  • iPhone: the deep link after install depends on install matching (opt-in) or the clipboard boost. Apple's App Store sheet doesn't pass any data to the installed app.
  • Offline, the SDK can still open the store when you pass the package name or App Store ID, but the deep link isn't kept.

Common errors

  • result.reason is no_package or no_app_store_id. The workspace has no package name or App Store ID for the installed app. Add it in Dashboard → Apps & stores, or pass androidPackage / appStoreId.
  • Android opens the full Play listing, not the half-sheet. Inline install is up to Google Play. Check that callerId is your own package name.
  • App B opens on its home screen. The tap was offline (result.reason is offline), or on iPhone install matching found no match. Try again online; on iPhone, see install matching.

Next steps