# 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.

- 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

Source: https://straitlink.in/docs/store-sheet/

**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](https://straitlink.in/docs/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](https://straitlink.in/docs/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

```kotlin title="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

```swift title="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](https://straitlink.in/docs/iphone-install-matching/).

## Next steps

- [iPhone install matching](https://straitlink.in/docs/iphone-install-matching/): how the iPhone side finds the link after install.
- [Analytics: how we count](https://straitlink.in/docs/analytics/): where store sheet taps show up.
