App Integration
Use this guide if you want to integrate Faslet in a native app while keeping the Faslet experience inside a webview. In this setup, your app decides when to show the CTA, and Faslet handles the sizing flow and returns updated user data.
How it worksβ
At a high level, the app integration loop is:
- Ask the Assistant State API what to show for a product.
- Show either no button, a default CTA, or a result CTA based on the returned state.
- Open a webview with Faslet and pass the returned
userIdvia the<faslet-app user-id="...">attribute. - Capture updated user data via
window._faslet.onDataChangedinside the webview. - Persist that data in your app/backend and send it again in the next
assistant/statecall.
State-driven UIβ
The Assistant State API returns one of these states:
| State | App behavior |
|---|---|
hidden | Do not show the Faslet CTA for this product. |
default | Show your default "Find your size" CTA. |
result | Show a CTA with the recommended size (from data.result). |
Always keep and reuse the returned data.userId. This links future requests to the same Faslet profile.
Implementation stepsβ
1) Request assistant stateβ
Call POST /assistant/state when a product screen is opened (or when product variants change).
Minimal request:
Use placeholders in this guide as template values that should be replaced with your own IDs and metadata.
{
"productId": "PRODUCT_ID",
"variants": [
{ "sizeLabel": "S", "available": true, "variantId": "VARIANT_ID_S" },
{ "sizeLabel": "M", "available": true, "variantId": "VARIANT_ID_M" }
]
}
2) Render your native CTA from stateβ
Use the returned state to decide if and how to render your button.
switch (assistantState.state) {
case 'hidden':
hideFasletButton();
break;
case 'default':
showFasletButton('Find your size');
break;
case 'result':
showFasletButton(`Recommended: ${assistantState.data.result}`);
break;
}
3) Open Faslet in a webviewβ
When the user taps your CTA, open a webview that includes your regular Faslet web integration and pass the userId from assistant/state:
<faslet-app
shop-id="SHOP_ID"
platform="unknown"
product-name="PRODUCT_TITLE"
product-identifier="PRODUCT_IDENTIFIER"
brand="PRODUCT_BRAND"
product-img="PRODUCT_IMAGE_URL"
user-id="USER_ID_FROM_ASSISTANT_STATE"
fullscreen="true"
></faslet-app>
<script src="https://widget.faslet.net/faslet-app.min.js" defer></script>
After the widget has loaded, open it programmatically:
window._faslet?.openWidget?.();
4) Capture user updates from the webviewβ
Use onDataChanged to receive updated profile context. Forward this payload to the native layer and persist it.
interface Window {
_faslet?: {
onDataChanged?: (userData: {
userId: string;
widgetVersion?: string;
seenExperiments?: string;
experimentVariants?: string;
profile?: FasletUserProfile;
}) => unknown;
};
}
window._faslet = {
...window._faslet,
onDataChanged: (userData) => {
postMessageToNativeApp({ type: 'faslet-user-data', payload: userData });
},
};
5) Reuse user data in future assistant-state callsβ
On next product views, send the stored user fields back to POST /assistant/state, for example:
{
"productId": "PRODUCT_ID",
"variants": [
{ "sizeLabel": "S", "available": true, "variantId": "VARIANT_ID_S" },
{ "sizeLabel": "M", "available": true, "variantId": "VARIANT_ID_M" }
],
"userId": "USER_ID",
"widgetVersion": "WIDGET_VERSION",
"seenExperiments": "SEEN_EXPERIMENTS",
"experimentVariants": "EXPERIMENT_VARIANTS",
"profile": {
"gender": "PROFILE_GENDER",
"height": "PROFILE_HEIGHT_CM",
"weight": "PROFILE_WEIGHT_KG",
"age": "PROFILE_AGE"
}
}
Common pitfallsβ
- Not passing
user-idinto<faslet-app>in the webview. - Not persisting the latest
onDataChangedpayload. - Replacing
userIdbetween sessions instead of reusing it. - Sending incomplete or stale variant availability in
assistant/staterequests.
Related docsβ
Helpβ
In case of any questions, please donβt hesitate to contact us on support@faslet.me