Flow Control
Complete or dismiss the flow. Resolves the startFlow() Promise.
complete()#
Complete the flow successfully. This closes the flow and resolves the startFlow() Promise with completed: true.
Mobana.complete(data?: Record<string, unknown>): void| Parameter | Type | Description |
|---|---|---|
data | Record<string, unknown> | Optional data to return to the app. Available as result.data in the startFlow() result. |
// Simple completion
document.getElementById('done-btn').addEventListener('click', () => {
Mobana.complete();
});
// Completion with data
document.getElementById('submit-btn').addEventListener('click', () => {
const selectedPlan = document.querySelector('input[name="plan"]:checked').value;
Mobana.complete({
selectedPlan,
onboardingCompleted: true,
timestamp: Date.now(),
});
});Returning Data to the App
// Data is returned to the app via startFlow() result
Mobana.complete({
selectedPlan: 'premium',
preferences: {
notifications: true,
darkMode: false,
},
});
// In the app:
// const result = await Mobana.startFlow('onboarding');
// if (result.completed) {
// console.log(result.data.selectedPlan); // 'premium'
// }Calling complete() automatically tracks a __completed__ system event for analytics. You don't need to track this manually.
dismiss()#
Dismiss the flow. This closes the flow and resolves the startFlow() Promise with dismissed: true.
Mobana.dismiss(): void// User wants to skip/close the flow
document.getElementById('skip-btn').addEventListener('click', () => {
Mobana.dismiss();
});
// Close button in corner
document.querySelector('.close-btn').addEventListener('click', () => {
Mobana.dismiss();
});Calling dismiss() automatically tracks a __dismissed__ system event for analytics.
requestCallback()#
Request the app to perform an async action (e.g., trigger a purchase, validate a promo code) and return a result. The flow stays open while the app processes the request.
Mobana.requestCallback(data?: Record<string, unknown>, options?: { timeout?: number }): Promise<Record<string, unknown>>| Parameter | Type | Description |
|---|---|---|
data | Record<string, unknown> | Arbitrary data to send to the app's onCallback handler. |
options.timeout | number | Timeout in seconds. Default: 300 (5 minutes). The Promise rejects if the app doesn't respond within this time. |
Flow Side
// Request the app to trigger a purchase
document.getElementById('buy-btn').addEventListener('click', async () => {
const planId = document.querySelector('input[name="plan"]:checked').value;
try {
// Show loading state while app processes
showLoading(true);
const result = await Mobana.requestCallback(
{ action: 'purchase', planId },
{ timeout: 120 } // 2 minute timeout for purchase flow
);
showLoading(false);
if (result.success) {
Mobana.haptic('success');
Mobana.complete({ purchased: true, planId });
} else {
showError('Purchase failed. Please try again.');
}
} catch (error) {
showLoading(false);
showError('Something went wrong. Please try again.');
}
});App Side
Provide an onCallback handler when calling startFlow():
// In the app — provide onCallback when starting the flow
const result = await Mobana.startFlow('paywall', {
params: { plans: availablePlans },
onCallback: async (data) => {
if (data.action === 'purchase') {
const purchase = await purchaseManager.buy(data.planId);
return { success: purchase.success, receipt: purchase.receipt };
}
return { error: 'Unknown action' };
},
});If the flow calls requestCallback() but no onCallback handler was provided to startFlow(), the Promise will reject with an error. Always wrap calls in try/catch.
The flow is responsible for showing its own loading UI while waiting for the callback result. The bridge does not display any loading indicators automatically.
To track custom events from your flow, see Flow Events and trackEvent().