Documentation

Powered by Algolia

Sending commands and receiving data from an app

With Alan, you can send a command from a voice script, handle it on the app side and send some data to the voice script. In this tutorial, we will demonstrate how to exchange data between the voice script and a client-side app. We will create a simple quiz form that captures the user's answer and sends information about it to the voice script. Alan can then report back to the user if the answer is correct or not.

What you will learn

  • How to send commands from the voice script to an app
  • How to handle commands on the app side
  • How to send data to the voice script using Alan visualState and projectAPI

What you will need

To go through this tutorial, make sure the following prerequisites are met:

Step 1: Create a webpage

To start off, let's create a webpage and embed the Alan button. We will send and receive data to/from this page.

  1. In the Alan Studio, open your project.
  2. At the top of the code editor, click Integrations.
  3. In the Embed Code Example section, click Copy All. Save the copied code as an HTML page.
  4. In the HTML page, make sure alanBtnInstance is defined:
<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="UTF-8">
      <title>Alan Example</title>
      <link href="https://fonts.googleapis.com/css?family=Lato:100,100i,300,300i,400,400i,700,700i,900,900i"
         rel="stylesheet">
   </head>
   <body>
      <div class="alan-btn"></div>
      <script type="text/javascript"
         src="https://studio.alan.app/web/lib/alan_lib.js"></script>
      <script>
         // Define alanBtnInstance
         var alanBtnInstance = alanBtn({
           key: "ff4f9c03e405a5a07d43485dbc3cb44a2e956eca572e1d8b807a3e2338fdd0dc/stage",
           onCommand: function (commandData) {
             if (commandData.command === "go:back") {
               // Call client code that will react on the received command
             }
           },
           rootEl: document.getElementById("alan-btn"),
         });
      </script>
   </body>
</html>

Open the created webpage and make sure there is the Alan button in the bottom right corner.

Step 2: Add the quiz form

Let's add the quiz form to the webpage:

...
<body>
<h1>Quiz</h1>
<p>What's the name of the river that runs through Egypt?</p>
<form>
    <input type="radio" name="quiz" value="nile" id="nile"> Nile
    <input type="radio" name="quiz" value="amazon" id ="amazon"> Amazon   
</form>

<div class="alan-btn"></div>
...

Here is how the webpage should look like now:

Step 3: Send a command from the voice script to the page

Now we will add voice commands to the Alan script so the user can select the necessary option through voice. In the Alan Studio, add the following intents:

intent(`It is Nile`, p => {
        p.play({command: "answerQuiz", option: "nile"});
        p.play(`Thank you`);
});

intent(`It must be Amazon`, p => {
        p.play({command: "answerQuiz", option: "amazon"});
        p.play(`Thanks`);
});

These are now two utterances that the user can say. When the user input is matched, two things happen:

  • Alan sends the command provided in the intent to the webpage. To send the command, we need to specify a JSON object in the p.play function. In our case, the object contains the command name and the option we want to pass.
  • Alan plays back some response to the user.

Let's make sure the webpage can handle the received command properly. We will get back to the webpage and add a command handler to it.

  • First, we need to add a function that enables the necessary option in the webpage when the user says something. In the script section, add the following:

    ...
    function setOption(option) {
    	if (option == "nile") {
    		document.getElementById("nile").checked = true;
    	} else {
    		document.getElementById("amazon").checked = true;
    	};
    };
    ...
  • Second, we need to add a handler for the command sent from the voice script. Under alanBtnInstance, change the if block to the following:

    ...
    let alanBtnInstance = alanBtn({
    	key: "ff4f9c03e405a5a07d43485dbc3cb44a2e956eca572e1d8b807a3e2338fdd0dc/stage",
    	onCommand: function (commandData) {
    		if (commandData.command === "answerQuiz") {
    			setOption(commandData.option);
    			}
    		},
    	rootEl: document.getElementById("alan-btn"),
    }); 
    ...

Now, when the webpage receives the answerQuiz command, the setOption function is invoked, and the corresponding option is passed to it as an argument.

You can test how it works: open the webpage, click the Alan button and say: It must be Amazon. The Amazon option must be selected, and Alan must play back the response.

Step 4: Send data with visualState

We want to send information about the chosen option back to the script and let Alan report if this answer is correct or not. It is possible to send data to the voice script in the following ways:

  • With visualState: You can use visualState to pass the current state of the app to the voice script. visualState can be helpful if you need to know the app state to adjust the logic in the dialog flow, for example, filter out some voice commands, give responses applicable to this state and so on.
  • With projectAPI: projectAPI has a more general usage. It can help if you need to pass any data to the voice script or perform some actions (call functions, set variable values) without a voice command.

At this step, we will send data from the webpage to the voice script with visualState. visualState allows you to send a custom JSON object, and you can then access the passed data on the voice script side.

Let's modify the setOption function. We will add the userChoice variable to get the answer type first.

...
<script>
let userChoice = "";

function setOption(option) {
    if (option == "nile") {
        document.getElementById("nile").checked = true;
        userChoice = "correct";
    } else {
        document.getElementById("amazon").checked = true;
        userChoice = "incorrect";
    };
};
... 

To send data back to the script, we need to call the setVisualState() method and pass to it the object to be sent:

...
<script>
let userChoice = "";

function setOption(option) {
    if (option == "nile") {
        document.getElementById("nile").checked = true;
        userChoice = "correct";
    } else {
        document.getElementById("amazon").checked = true;
        userChoice = "incorrect";
    };
    //set visualState
    alanBtnInstance.setVisualState({
        answer: userChoice
    });
};
...

Now, when you choose an option, the answer type is sent to the script. Let's get back to the Alan Studio and add a new command that will report about the answer.

To access data in visualState, we need to use the p.visual.answer runtime variable. Add the command below to the script. Depending on the answer type obtained from the webpage, Alan will reply differently.

...
follow(`Am I right?`, p => {
    let answer = p.visual.answer;
    switch (answer) {
        case "correct":
            p.play(`You are right`);          
            break;
        case "incorrect":
            p.play(`You are wrong`);           
            break;
        default:
            p.play("(Sorry,|) I have no data");
    }      
}); 
...

Here we use follow instead of intent. Follows are context-dependent commands. You will be able to run this command only after the first intent is matched.

You can test how it works: in the webpage, click the Alan button and say: It is Nile. Then ask: Am I right? Alan will get back with: You are right.

Step 5: Send data with projectAPI

Alan offers another method to send data from an app to the voice script - with projectAPI. If you use projectAPI, you can access data on the script side using the p.userData variable.

Let's do the same thing we did in step 4, but now using projectAPI. In the voice script, remove the follow with visualState and add the following:

...
projectAPI.sendAnswer = function(p, param, callback) {
    p.userData.answer = param.answer;
    callback();
};

follow(`Am I right?`, p => {
    let answer = p.userData.answer;
    switch (answer) {
        case "correct":
            p.play("You are right");
            break;
        case "incorrect":
            p.play("You are wrong");
            break;
        default:
            p.play("(Sorry,|) I have no data");
    }    
});
...

Here we define a projectAPI method that we will use to send data to the voice script, and add the p.userData.answer that will contain the passed data.

In the webpage, we need to modify the setOption() function to add callProjectApi() and pass the defined method together with the answer object to it:

...
function setOption(option) {
    if (option == "nile") {
        document.getElementById("nile").checked = true;
        userChoice = "correct";
    } else {
        document.getElementById("amazon").checked = true;
        userChoice = "incorrect";
    };
    //call projectAPI
    alanBtnInstance.callProjectApi("sendAnswer", {
        answer: userChoice
    }, (err) => {
        if (err) alert(err)
    });
};
...

You can test how it works: in the webpage, click the Alan button and say: It must be Amazon. Then ask: Am I right? Alan will get back with: You are wrong.