Your skill can allow its customers to enter structured data using a Webview
app.
Natural language conversations are, by their very nature, free-flowing. But
they may not always be the best way for your skill to collect information from its
users. For example, when entering credit card or passport details, users need to enter
specific information (and enter it precisely). To help with these kinds of tasks, your
skill can call a webview app.
These apps not only enable structured data entry through UI elements like
forms, date pickers, fields, and LOVs, but they can also validate the user input and
collect information in various ways, like uploading images, capturing user signatures,
or scanning barcodes. Webview apps also protect sensitive user data like credit card
numbers because this data doesnโt appear the chat history when itโs entered into the
app. Description of the illustration webview-webapp.png
How Do I Integrate a Webview into a Skill? ๐
You need the following to integrate a web app into your skill:
A Webview Service that connects the skill to the web app, which can be
hosted on an external web server, or within Digital Assistant.
A Webview Component in the dialog flow. This component acts a gateway to the web app by naming the Webview
Service, listing the dialog flow variables that get based to the web app, and storing any
values returned by the web app.
At runtime, the component renders a button
that launches the web app. The Webview component launches the app as a webview within
the skill, or in a separate browser tab when the skill runs on a web channel.
The web app itself, which is hosted within Digital Assistant, or on a remote web server.
The web apps hosted within Digital Assistant must be single-page apps (SPAs), client-side web apps with a single HTML page
(index.html) that launches the web app and gets updated in response
to the skill user's input. When the Webview component calls the SPA:
The index.html is loaded and launches the web app
as a webview or in a separate browser tab.
The web app makes a POST request to the callback URL that was
generated by the Webview component. This request signals that the app has
completed its processing. If the app returns data, it's included in this request
as a JSON object that gets stored in the variable property. You
can reference this data in your dialog flow using
${variable_property_name.value.Param}.
You can write the SPA using different frameworks, such as Oracle Visual
Builder, Angular, Oracle JavaScript Extension Toolkit (JET), or React.js.
Note
The backend for Oracle Visual
Builder manages REST connections, users (through Oracle Identity Cloud Service), and
runs business objects, so any Oracle Visual Builder app hosted within Digital Assistant will have the following limitations:
It can't use business objects.
It can't integrate with Oracle Identity Cloud Service.
It can't access a REST service using the Oracle Visual Builder
authentication proxy.
Therefore, supporting any of these capabilities means that you must host the
Oracle Visual Builder app on an external server.
To host the app within Digital Assistant you must bundle it into a TAR archive (a TGZ file). Because this is a SPA, the
index.html file must be at the root of this package.
Enable the SPA to Access the
Input Parameters and Callback URL ๐
When you host a SPA within in Digital Assistant, the Webview component injects the window.webViewParameters variable
(shown in the following snippet) into the <head> element of the
index.html file at runtime. The key-values pairs in the payload
inform the SPA of the input values passed from the
skill.
When you host the SPA within Digital Assistant, you don't need to define any placeholders for the variable values in the
index.html file. As long as the index.html file
has a <head> element, your web app will know what values to
expect, and the callback.
Add a Single Placeholder in the
<head> Element ๐
Within the <head> element, insert a
<script> block with the
webview.sourceVariableList placeholder. The web app replaces this
with a JSON-encoded string that has the input parameter data and the callback URL.
In the following example, the key is window.wvParams. You
can use any name for this key as long as you append it with window. You
must always define the value as "webview.sourceVariableList".
The let statement assigns
webview.sourceVariableList to wvParams.
The output values get parsed as a JSON object.
fullname extracts the name of the variable defined for the
sourceVariableList property in the webview component (where
name is the name of the variable defined).
Add Multiple Placehoders in the
<head> Element ๐
Add a <script> block that has placeholders for each value
defined for the SourceVariable component and the callback URL. The web
app returns the callback URL and the data for input parameters as a JSON-encoded string.
Because you've added placeholders, you don't have to declare a
window.webviewParameters['parameters'] variable.
As illustrated by the following snippet, the placeholders are defined by key-value pairs.
Each value must:
Match the input values defined for SourceVariable
property.
Be appended by webview. (webview.keyword, for
example).
In addition, The callback value must be webview.onDone. In the
following snippet, for example, webview.keyword,
webview.assignee, webview.inventor all match
sourceVariableList: "assignee, keyword, inventor". The callback URL
is defined with webview.onDone. You can name the callback key anything,
but you always need to define the value as webview.onDone.
You can optionally set global variables by appending the keys with window.
(window.Keyword in the following snippet, for example).
Wire the Callback URL to a Done
Button in the Web App ๐
The callback URL that's generated by the Webview component is essentially a
single-use callback because of its state token
(https://...?state=<callback-state-token>). While it has a
default lifetime of an hour, it gets cleared after Webview component handles the
callback request from the web app. Because users wonโt be able to query the web app
after this point, it should transition to an End page with a Close button thatโs wired
to the callback URL.
Externally Hosted
Webviews ๐
You would host an app on external server if it has security requirements,
leverages server-side infrastructure, or requires data integration or central
administration. Remotely hosted web apps can be SPAs, but don't have to be. You can
modify an existing web app to render as a webview or create a web app specifically for a
skill.
For externally hosted web apps, you need to host the web app itself and an
intermediary service. The web app expects a GET request from the skill, while the
intermediary service receives the skill's POST requests and formulates the redirect URL
to the web app. The two can reside on the same web server, or can be hosted on separate
web servers. Regardless of the implementation, the request flow is as follows:
At runtime, the Webview component sends the intermediary service a
POST request that includes the skillโs callback URL and the user's input
parameters as an array of key-value pairs. The component adds
webview.onDone variable as the callback URL key. The keys
are the names of parameters that are referenced by both the Webview's
Inputs for Service property and the
webview.onDone property.
The intermediary service returns a JSON object to the skill that
has a single property, webview.url. Its string defines the
redirect URL to the web app, which is used by the subsequent GET request from
the skill. This URL also contains the key-values passed from the POST request
(unless the payload of the POST request is saved in a storage accessible to the
web application). It might look something like:
The
web app uses the callback URL in a call to pass control back to the skill, and
optionally, to pass a response payload.
self.buttonClick = function (event) {
if (event.currentTarget.id === 'Submit') {
let data = {};
data.origin = self.origin();
data.destination = self.destination();
//return date in milliseconds
data.departureDate = (new Date(self.departureDate())).getTime();
data.returnDate = (new Date(self.returnDate())).getTime();
data.status = "success"
/*
function jqueryPost(url, data) {
return $.ajax({
contentType: "text/plain",
url: url,
data: data || {},
type: "POST",
dataType: "text/plain"
});
};
jqueryPost(webViewCallback, JSON.stringify(data));
*/
//JQuery post call
$.post(webViewCallback,JSON.stringify(data));
}
else {
//if user pressed "cancel" pass no data but a status informing the bot designer
let data = {};
data.status = "cancel"$.post(webViewCallback, JSON.stringify(data));
}
This
illustrates using the JQuery $.post method to return JSON
object to the skill with origin, destination,
departureDate, and returnDate key value
pairs:
This snippet has a
"status" property that's set to
"success" or "cancel" to indicate that
a user has completed work in the web app or canceled it. Users may close the
browser before the callback request has completed, so include a listener for
the closing that issues a callback if not yet happened. The call could use a
status of "cancel" to indicate that the form wasn't
completed successfully. If the user closes the window and you don't catch
this, then the skill waits until it time out.
The skill launches the web app by sending a GET request to the URL
defined by the webview.url property.
After the webview processes the input, it sends a completion
callback, which is a POST request, to the callback URL that the Webview
component generated and provided to the intermediary service. This request not
only signals that the app has finished (and that the skill should resume control
of the session), but can return a payload of data, which gets stored in the
Webviewโs Output for Service property.
Depending on your hosting strategy, there are a couple of things to keep in
mind:
If you host the web app and the intermediary service on
the same web server, then the skill's request parameters can be
saved into a session, thus eliminating the need for a long URL
string.
If you host the web app and the intermediary service on
different servers, then all of the web app request parameters in the
redirect URL that's sent to the skill must be encoded as query
parameters.
Create a Webview Service ๐
Configuring a Webview Service connects your skill to the service that hosts the
webview app.
You create Webview Services from the Webview page, which is accessed by
first clicking Components () in the left navbar, then clicking Webview. This page
lists the various Webview Services that you can reference in the Webview's Webview
Component Service property.
Note
You donโt need to reconfigure a Digital Assistant-hosted service when you version or clone your skill. If you host the web app
externally, however, you do need to reconfigure the service when you version or
clone your skill.
Create a Digital Assistant-Hosted Webview Service
๐
While you may need to provide authentication credentials as part of
configuring an externally-hosted Webview Service, you only need to package the web app
into a TAR archive (a TGZ file) and then upload it. The index.html file
must be at the root level of this file.
You can package the app using the GNU tar command:
tar -zcvf webapp.tgz *
In this example, the
-zcvf command creates a file called webapp.tgz. As
stated in Defining Placeholders in the index.html File, you can author the web app using your framework of choice as long as
the index.html file is at the root of the TGZ file. In fact, the
index.html can even be the only file at the root level.
To create the service:
Enter the name of the services in the Name file and a description
(which is optional). The name that you enter here must match the value for the
Webview Component Service property of the Webview
component.
Switch on the Service Hosted option.
Drop the TGZ into the Package File field or browse to, and select,
the TGZ file.
Click Create.
Package Oracle Visual Builder
Applications ๐
You build and optimize your Oracle Visual Builder apps for Digital Assistant using the vb-build Grunt task. You can run this task locally, or
as part of a build on Oracle Developer Cloud Service (DevCS).
Before you build the Oracle Visual Builder app:
Ensure that you've configured its service connection to accommodate the
limitations described in How Do I Integrate a Webview into a Skill? by choosing Direct (Bypass the proxy) and
Allow Anonymous Access in the Oracle Visual Builder.
If you're using Oracle Visual Builder to optimize the binary, then select
Push to Git. Otherwise, you can skip this step.
Refer to the Oracle Visual Builder Documentation to find out more about
securing the Oracle Visual Builder app and integrating it into a Git repository.
Package the Oracle Visual Builder
App Locally ๐
To optimize and package your Oracle Visual Builder app locally:
In the Oracle Visual Builder home page, select your app and then
click Export without Data.
Unzip the app.
Run npm install on the root folder (where both the
package.json and Gruntfile.js files are
located).
Running npm install retrieves the
grunt-vb-build npm package that's defind in the
package.json file.
The ID of the application. The application
ID may be the same as the application name, but the
application ID must be unique in your identity
domain.
ver
The version of your application.
git
Specifies the location of the sources (if
they are not located in your current folder).
After the build completes, navigate to the application directory (located with
in the WebApps directory). For example,
build/optimized/webApps/financialDispute.
Run the GNU tar command (tar -zcvf webapp.tgz *, for
example).
tar -zcvf webapp.tgz *
Package the App Using Oracle
Developer Cloud Service ๐
To build and optimize the app in Oracle Developer Cloud Service (DevCS):
Configure a build job in Oracle Cloud for the web app:
Associate the job with Git by adding Git as the source
control (your web app also needs to be integrated with a Git
repository).
Select a build template.
Add string parameters that get passed into the build. These
parameters include:
The application's service URL, ID, and version
(which you can obtain from your Oracle Visual Builder
instance)
Your user and password (a Password Parameter)
The optimization, such as Uglify2.
For the build steps, add a shell script that begins with
npm install and passes in the default parameters to
the Visual Builder Grunt
Tasks, such as vb-build.
For the After Build configuration, configure archiving, by
choosing Artifact Archiver (selected from Add
After Build Action menu) and then enter build*zip in
the Files to Archive field.
After the build completes, download the ZIP file and then extract
it. The index.html file is located within the
webapp folder (located in the webapps
directory).
Package the app into a TGZ file (tar -zcvf webapp.tgz
*, for example).
Create an Externally-Hosted
Webview Service ๐
For webview apps hosted on external web app servers, provide the following:
NameโThe name for remote service.
Note
The name that you enter here
must match the value for the Webview Component
Service property of the Webview component.
Switch off the Service Hosted toggle.
Web App URLโThe base endpoint provided by a
web server that accepts the source parameters as the payload in a HTTP POST
request. For example,
https://example.oracle.com:3001/webviewParams. Enter the
URL for the intermediary service when the web app and the intermediary service
are hosted separately.
Auth TokenโAn authorization token thatโs sent
with requests to the URL specified by the Web App Url
property. This property is the form of Basic <token> or
Bearer <token>. This is an optional property
Query ParametersโA stringified JSON object
whose key-value pairs are the query parameters that are appended to the POST
request. This is an optional property.
Reference the Returned Data in
the Dialog Flow ๐
Because the values returned in the payload do not update any of the variable
values, the property names in the response payload don't need to match the variable
names defined in the Inputs for Service property.
You can access the returned payload using
${variable_property_name.value.Param}.
After you create the Webview Service and configure the Webview component,
you can find out about the data returned by the web app using the Skill Tester (). After your conversation has traversed past the Webview state, use the
Conversation window to examine the values returned for the variables. Description of the illustration tester-variables.png
Tip:
Web app
developers should ensure that the returned payload includes descriptive property
names.