Widget Integration
With the widget style of integration, you retrieve and inject a Tilia-supplied script into your page, which provides an API to interact with our widget. You then “execute” the desired flow, passing an element id to indicate where the Tilia UI will appear in your page and callback functions to handle specific messages returned from the widget.
The diagram below illustrates the flow of information within a widget integration.
To integrate the Tilia widget
Widget integration involves the following steps:
Step 2: Add the widget script to your page
Step 3: Retrieve redirect url and execute the flow
Step 4: Handle the flow result
The rest of this document walks you through the basics of integrating a flow using the widget method.
Step 1: User authorization
All flows start with an OAuth2 authorization of the end user by passing an account_id
. The response will include a redirect URL with a generated nonce that authorizes the user to interact with the Tilia UIs.
Your server should contain an api endpoint that passes the 'redirect' payload to your frontend.
Creating the nonce requires an Access Token with the scope write_user_tokens
.
curl --location --request POST https://auth.tilia-inc.com/authorize/user \
--header 'Authorization: Bearer <Access_Token>' \
--header 'Content-Type: application/json' \
Request body
{
"account_id": "<tilia_account_id>"
}
Sample response
{
"status": "Success",
"message": [],
"codes": [],
"payload": {
"redirect": "https://web.tilia-inc.com/ui/appauth/ed8ff1e9-9256-4205-918a-b9ca23ec00ec"
}
}
The response includes a redirect URL that is used in the next step.
attention
The nonce is valid for 24 hours. We recommend generating a nonce immediately before sending the user to a Tilia UI. Each nonce may only be used once.
Step 2: Add the widget script to your page
/**
* Load widget script in your page.
* This should happen early within the page load so it is ready when needed.
*/
const widget = document.createElement("script");
widget.src = `https://web.tilia-inc.com/ui/v1/widget`;
widget.onload = () => {
// Use this to ensure the widget is
// loaded before using it.
};
document.body.appendChild(widget);
Step 3: Retrieve redirect url and execute the flow
Next, you will retrieve the redirect url (from Step 1) and pass that with the desired flow name to the Tilia widget.
/**
* 1: Setup your callback functions
* 2: Call your endpoint to retrieve redirect payload
* 3: Execute widget with your desired Flow
*/
function handleWidgetReady(e) {
console.log('handleWidgetReady:', e);
// handle the ‘ready’ message
}
function handleWidgetError(e) {
console.error('handleWidgetError', e);
// handle error
}
function handleWidgetComplete(e) {
console.log('handleWidgetComplete:', e);
// handle the ‘complete’ message
}
function triggerTiliaWidgetFlow() {
const yourEndpointThatReturnsRedirectPayload = "/PATH/TO/YOUR/API/ENDPOINT/THAT/RETURNS/REDIRECT/PAYLOAD";
fetch(yourEndpointThatReturnsRedirectPayload)
.then(response => {
/**
* For this example we will assume your endpoint is
* passing back the full payload from step one:
* {
* "status": "Success",
* "message": [],
* "codes": [],
* "payload": {
* "redirect": "https://web.tilia-inc.com/ui/appauth/ed8ff1e9-9256-4205-918a-b9ca23ec00ec"
* }
* }
*/
window.Tilia.execute({
//required parameters
rootId: < your.element.id > ,
flow: < flow.name > , // for example: "tos", "kyc", "purchase", "payout"
redirect: response.payload.redirect, // this could be different based on what your server is sending as a response. Expects a URL string.
onComplete: handleWidgetComplete,
onError: handleWidgetError,
// optional parameters
debug: true,
onReady: handleWidgetReady,
flowConfig: {} // see specific flow documentation for supported config values
});
})
.catch(e => {
console.error('error retrieving redirect payload', e);
// handle error
});
}
triggerTiliaWidgetFlow(); // call when ready.
Your onComplete
handler function will be called when the user completes the flow. The function will pass results specific to the flow.
Full HTML Example...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style type="text/css">
html, body { width: 100%; height: 100%; }
body {
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
}
#my-widget-wrapper {
width: 480px;
height: 700px;
padding: 4px;
border: 1px solid black;
border-radius: 8px;
}
</style>
<script type="text/javascript">
var widgetLoaded = false;
var callTriggerFlowAfterWidgetLoaded = false;
function loadWidget() {
/**
* Load widget script in your page.
* This should happen early within the page load so it is ready when needed.
*/
var widget = document.createElement("script");
widget.src = "https://web.tilia-inc.com/ui/v1/widget"; // if using the staging environment, you will want to change this to match staging URL
widget.onload = () => {
// Use this to ensure the widget is
// loaded before using it.
widgetLoaded = true;
console.log('widget loaded');
if (callTriggerFlowAfterWidgetLoaded) {
triggerTiliaWidgetFlow();
}
};
document.body.appendChild(widget);
}
/**
* Your callback handlers
*/
function handleWidgetReady(e) {
console.log('handleWidgetReady:', e);
// handle the ‘ready’ message
}
function handleWidgetError(e) {
console.error('handleWidgetError', e);
// handle error
}
function handleWidgetComplete(e) {
console.log('handleWidgetComplete:', e);
// handle the ‘complete’ message
}
/* ----------------- */
function triggerTiliaWidgetFlow() {
if (!widgetLoaded) {
// in this basic example, we are likely calling this function before the widget is ready.
// to get around this, we are setting a variable to re-call this function when the widget has loaded.
callTriggerFlowAfterWidgetLoaded = true;
return;
}
const yourEndpointThatReturnsRedirectPayload = "/PATH/TO/YOUR/API/ENDPOINT/THAT/RETURNS/REDIRECT/PAYLOAD";
fetch(yourEndpointThatReturnsRedirectPayload)
.then(response => {
/**
* For this example we will assume your endpoint is
* passing back the full payload from step one:
* {
* "status": "Success",
* "message": [],
* "codes": [],
* "payload": {
* "redirect": "https://web.tilia-inc.com/ui/appauth/ed8ff1e9-9256-4205-918a-b9ca23ec00ec"
* }
* }
*/
window.Tilia.execute({
//required parameters
rootId: "my-widget-wrapper",
flow: "purchase", // for example: "tos", "kyc", "purchase", "payout"
redirect: response.payload.redirect, // this could be different based on what your server is sending as a response. Expects a URL string.
onComplete: handleWidgetComplete,
onError: handleWidgetError,
// optional parameters
debug: true,
onReady: handleWidgetReady,
flowConfig: {} // see specific flow documentation for supported config values
});
})
.catch(e => {
console.error('error retrieving redirect payload', e);
// handle error
});
}
window.addEventListener('load', function() {
loadWidget();
triggerTiliaWidgetFlow();
}, false);
</script>
</head>
<body>
<div id="my-widget-wrapper"></div>
</body>
</html>
Step 4: Handle the flow result
Upon completing the flow, the onComplete
function returns a result. Refer to the flow-specific documentation for details.