Launch Params
Launch params let you start your app in a specific state. You supply a flat JSON object when the app is launched on a live device, and your app reads those values back through the platform’s own preferences API.
The point of the feature is what it doesn’t require: no VibeView SDK linked into your app, no imports, no rebuild. If your app can read UserDefaults on iOS or shared preferences on Android, it can read launch params today.
Typical uses: skip a login screen with a test account, flip a feature flag, point a build at a staging environment, or seed onboarding state so a demo always starts on the same screen.
Where you can pass params
Launch params are programmatic. There are three surfaces.
JavaScript SDK
Params apply when you launch or install an app — starting a device on its own does not launch anything, so there is nothing for params to apply to yet.
Put them on the client config to set a default for every launch this client makes, then launch the app:
import { VibeViewClient } from '@vibeview/sdk';
const client = new VibeViewClient('#simulator-container', {
deviceType: 'ios',
token: 'your-auth-token',
autoStart: true,
params: {
userEmail: 'demo@example.com',
skipOnboarding: true,
retryCount: 3,
},
});
// The config params are applied here.
const result = await client.launchApp('com.example.myapp');
console.log(result.paramTypes); // { userEmail: 'string', skipOnboarding: 'boolean', ... }
installApp() takes them the same way, as long as it is the call that launches
the app — pass launchAfterInstall: true. An install that does not launch has
nothing to apply params to, so it sends none.
To use different params for a single call, pass them explicitly — a per-call
params object replaces the config one rather than merging with it:
await client.launchApp('com.example.myapp', { params: { skipOnboarding: false } });
The SDK is not yet available as a public npm package — check with your VibeView contact on current availability before building against it. See the SDK reference for the rest of the configuration.
Embed URL
Add a params query parameter to the embed URL, holding a URL-encoded JSON object:
<iframe
src="https://vibeview.io/embed/ek_live_xxxxxxxxxxxxxxxxxxxxxxxx?params=%7B%22skipOnboarding%22%3Atrue%7D"
width="380"
height="820"
></iframe>
Build the value with encodeURIComponent(JSON.stringify(params)) rather than typing it out by hand — an unencoded {, &, or space will not survive the URL.
REST API
Pass a params object in the request body of the install and launch endpoints:
curl -X POST https://vibeview.io/api/v1/sessions/<session_id>/launch-app \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"package_name": "com.example.myapp",
"params": { "skipOnboarding": true, "retryCount": 3 }
}'
The same params field works when you install a build and launch it in one call. See the API reference for the full request shapes.
The response reports the type each key was interpreted as (see Value types below), which is the fastest way to check that a value was read as the type your app expects. It confirms how your JSON was interpreted — not that your app has read the value yet.
Where you cannot pass params
- Public share links do not carry params. A share URL is public — it gets pasted into chat, forwarded, and indexed — and launch params are exactly where people put things like a test-account password. Params are dropped on that surface by design. Use an embed key if you need a shareable page that launches your app with params: the embedding page is yours, so you control who sees the URL.
- There is no dashboard control for launch params. They are supplied programmatically through the three surfaces above.
Reading params in your app
Params land in the platform’s standard key/value store, under the key names you sent. No VibeView code is involved on the app side.
iOS
Read from the standard user defaults.
Swift
let email = UserDefaults.standard.string(forKey: "userEmail")
let skipOnboarding = UserDefaults.standard.bool(forKey: "skipOnboarding")
let retryCount = UserDefaults.standard.integer(forKey: "retryCount")
Objective-C
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *email = [defaults stringForKey:@"userEmail"];
BOOL skipOnboarding = [defaults boolForKey:@"skipOnboarding"];
NSInteger retryCount = [defaults integerForKey:@"retryCount"];
Android
Params arrive two ways at once, and both carry the same values with the same types. Read whichever suits your app:
- Shared preferences named
prefs.db— available from anywhere in the app, includingApplication.onCreate, and still there if the system restarts your app. - Intent extras on the activity that was launched — available in that activity’s
onCreate, for that launch only.
From shared preferences
Kotlin
val prefs = getSharedPreferences("prefs.db", Context.MODE_PRIVATE)
val email = prefs.getString("userEmail", null)
val skipOnboarding = prefs.getBoolean("skipOnboarding", false)
val retryCount = prefs.getInt("retryCount", 0)
Java
SharedPreferences prefs = getSharedPreferences("prefs.db", Context.MODE_PRIVATE);
String email = prefs.getString("userEmail", null);
boolean skipOnboarding = prefs.getBoolean("skipOnboarding", false);
int retryCount = prefs.getInt("retryCount", 0);
Other accessors work the same way: getLong, getFloat.
From the intent
Kotlin
val email = intent.getStringExtra("userEmail")
val skipOnboarding = intent.getBooleanExtra("skipOnboarding", false)
val retryCount = intent.getIntExtra("retryCount", 0)
Java
String email = getIntent().getStringExtra("userEmail");
boolean skipOnboarding = getIntent().getBooleanExtra("skipOnboarding", false);
int retryCount = getIntent().getIntExtra("retryCount", 0);
Extras reach only the activity that was launched, and only on that launch — if your app reads params outside its launch activity, or after the system has restarted it, use the shared preferences instead.
Roku
Roku does not have a key/value preference store to read from. Params are handed to your channel as arguments instead, so read them from the args associative array in Main:
sub Main(args as Object)
email = args.userEmail
skipOnboarding = args.skipOnboarding ' the string "true", not a boolean
end sub
Values are strings on Roku. There are no types on this platform: a true that stays a boolean on iOS and Android arrives as the string "true" here, and 3 arrives as "3". Convert in your channel code.
Value types
On iOS and Android, JSON scalars keep their native types:
| What you send | What your app reads |
|---|---|
| String | String |
| Boolean | Boolean |
| Integer within the 32-bit range | Integer |
| Integer beyond the 32-bit range | Long |
| Decimal number | Float |
| Array or object | JSON string — parse it yourself |
null | Key is omitted entirely |
Arrays and objects are not expanded into nested preferences. They arrive as their JSON text, so your app parses them with whatever JSON library it already uses.
Because types are inferred from the JSON you send, the shape of your JSON decides the stored type. {"retryCount": 3} stores a number; {"retryCount": "3"} stores a string. Query-string builders, form fields, and CI variables all like to turn numbers into strings, so check what you actually send.
Three caveats worth knowing up front
Reading with the wrong type crashes your app on Android. Android’s shared preferences are strictly typed: calling getBoolean on a value that was sent as a string does not fall back to the default — it throws, and the app dies on launch. Match the accessor to the type you sent. If a launch dies immediately and the screen goes back to the launcher, a type mismatch is the first thing to check; the launch response tells you the type each key was stored as.
Large integers need getLong. An integer beyond the 32-bit range (roughly ±2.1 billion) is stored as a long, so getInt is the wrong accessor for it — and per the caveat above, the wrong accessor throws. Timestamps in milliseconds are the usual way to hit this.
Decimals lose precision past about 7 significant digits. Non-integer numbers are stored as a float. If you need a value preserved exactly — a price, a long identifier, a coordinate at high precision — send it as a string and parse it in your app.
Android TV: intent extras only for release builds
On Android TV, a release build of your app receives launch params as intent
extras only — the prefs.db shared preferences are not available to it. Read
them from the intent in your launch activity, as shown above, and the values and
types are exactly the same.
A debug build on TV, and both debug and release builds on phones and tablets, receive params through both routes.
The one combination that cannot receive params at all is a release build on TV whose launcher activity cannot be determined — there is then neither a preferences file nor an intent to carry them.
When you supply params as part of installing the app — an embed session, or the install endpoints — that case fails with a clear error rather than starting your app without the params, so a missing param never looks like a working session.
The standalone launch endpoint is different: it dispatches the launch and returns as soon as the request is accepted, so its response tells you your params were valid, not that they were delivered. If you need launch to confirm delivery, install and launch in one call.
When params apply
Params are applied at app launch, and they apply to that launch only:
- Each launch gets exactly the params it was given. Values from a previous launch never carry over, on either platform.
- Launching the app again without params starts clean, as if freshly installed. If you want the same params on a relaunch, send them again.
- Params are in place before the app starts, so it is safe to read them in your app’s startup path.
Limits and rules
| Rule | Value |
|---|---|
| Key format | Must start with a letter or underscore, then letters, digits, underscores or dots |
| Key length | Up to 64 characters |
| Number of keys | Up to 50 |
| Total size | Up to 8 KB of JSON |
| Nesting | The object must be flat — nested values are stored as JSON text, not walked |
Keys that break the format are rejected, not silently cleaned up: you get an error naming the key, rather than a launch where a param quietly went missing. Keys with a null value are simply omitted, so your app sees its own default.
Two rarer rejections work the same way, and both exist because the value could not otherwise arrive intact:
- A whole number beyond about 9 quadrillion (2⁵³−1) is rejected — past that point the value can no longer be represented exactly. Send it as a string.
- A string containing a NUL character, or half of a surrogate pair, is rejected — neither can be carried to the device without being altered.
Both are errors naming the key rather than a launch where the value quietly changed.
Tips
- Namespace your keys (
vv.userEmail,demo.skipOnboarding) if your app already stores preferences of its own, so a param can never shadow a real setting. This matters for intent extras too: your params arrive as extras on the launched activity, so a param sharing a name with an extra your app sets itself (from a deep link or a notification, say) will be the one your activity reads. - Send strings when in doubt. A string is the one type that can never crash a read, and parsing
"3"in your app costs one line. - Don’t put real credentials in params. Use a disposable test account — embed URLs live in your page source, and anyone who can view source can read them.
- Keep a small set of well-known keys and document them alongside your app, so demo pages, CI jobs, and teammates all use the same names.