Custom Integration
Dialogflow Messenger
Integrate Dialogflow with Zoho Live Chat
BotCopy Example Bots

Handling user interaction

You already noticed that we have code which takes the text of the button (suggestion chip) and posts it to the process.php as if user had typed it in.

Here is an example list view control:

Here is the corresponding JSON returned by the API call. Note that each list item has a info -> key field. Just like you have a text and a value in a typical listbox in web programming, you have the same notion of visible text vs underlying (invisible) value in the Google Assistant’s ListView rich response.

{
  "responseId": "ff484abc-fc58-43eb-bd01-0e7e60ef03d6",
  "queryResult": {
    "queryText": "Yes",
    "parameters": {},
    "allRequiredParamsPresent": true,
    "fulfillmentMessages": [
      {
        "platform": "ACTIONS_ON_GOOGLE",
        "simpleResponses": {
          "simpleResponses": [
            {
              "textToSpeech": "OK, what is your question about?"
            }
          ]
        }
      },
      {
        "platform": "ACTIONS_ON_GOOGLE",
        "listSelect": {
          "title": "Choose an option",
          "items": [
            {
              "info": {
                "key": "individual course"
              },
              "title": "Individual course",
              "description": "Example : Intro to Dialogflow",
              "image": {}
            },
            {
              "info": {
                "key": "course bundle"
              },
              "title": "Course Bundle",
              "description": "Example: Dialogflow Essentials",
              "image": {}
            },
            {
              "info": {
                "key": "general question"
              },
              "title": "General",
              "description": "If you have a question about my courses in general",
              "image": {}
            }
          ]
        }
      }
    ],
    "outputContexts": [
      {
        "name": "projects/testagent-ed43c/agent/sessions/ab06d0e0-6cd7-115c-6a59-21d2f0071f3e/contexts/awaiting_question_type",
        "lifespanCount": 1
      }
    ],
    "intent": {
      "name": "projects/testagent-ed43c/agent/intents/d505d0c8-e0b3-471e-9519-946c4887cacc",
      "displayName": "hasquestions.YES"
    },
    "intentDetectionConfidence": 1,
    "languageCode": "en"
  }
}

Let us take a look at code which renders the list box:

function renderList(data,parent){
    data = data['listSelect'];
    var i, len = data['items'].length;
    var listGroup = jQuery('<div/>',{
        'class':'list-group card gaListGroup'
    });
    if(data['title']){
        var titleOfCard = data['title'];
        var listGroupHeading = jQuery('<div/>',{
            'class':'gaListHeader card-header deep-orange lighten-1 white-text',
            'html':titleOfCard
        });
        listGroup.append(listGroupHeading);
    }
    for(i=0;i<len;i++){
        var item = data['items'][i];
        if(item){
            var optionTitle = item["title"];
            var optionDescription = item["description"];
            var optionKey = item['info']['key'];
            var imageUrl;
            if(item["image"]){
                imageUrl = item["image"]["imageUri"];
            }
            var anchor = jQuery('<a/>',{
                'data-key':optionKey,
                'class':'gaListItem list-group-item list-group-item-action flex-column ' +
                    'align-items-start'
            });
            anchor.click(function(){
                if(window.currentSuggestionChips){
                    var buttonRow = window.currentSuggestionChips;
                    buttonRow.remove();
                    window.currentSuggestionChips = null;
                    $("#message").removeAttr("disabled");
                }
                var textToSubmit = $(this).attr('data-key');
                $("#message").val(textToSubmit);
                $( "form" ).trigger( "submit" );
                $(listGroup).addClass('disabledbutton');
            });
            var headingDiv = jQuery('<div/>',{
            });
            var heading = jQuery('<div/>',{
                'class':'card-title',
                'text':optionTitle
            });
            heading.css("font-weight","bold");
            var row = jQuery('<div/>',{
                'class':'row'
            });
            var colSpanText = 'col';
            if(imageUrl) colSpanText = 'col-8';
            var colText = jQuery('<div/>',{
                'class':colSpanText
            });
            var colImage =jQuery('<div/>',{
                'class':'col-4'
            });
            var para = jQuery('<p/>',{
                'class':'mb-1',
                'html':optionDescription
            });

            if(imageUrl){
                var img = jQuery('<img/>',{
                    'class':'img-fluid',
                    'src':imageUrl,
                    'width':'50px'
                });
                colImage.append(img);
            }
            row.append(colText);
            if(imageUrl) row.append(colImage);
            headingDiv.append(heading);
            headingDiv.append(para);
            colText.append(headingDiv);
            anchor.append(row);
            listGroup.append(anchor);
        }
    }
    parent.append(listGroup);
    $("#message").attr("disabled","disabled");
}

Since there is a lot going on in this code, I am going to skip the explanation of what it does.

But notice that textToSubmit – which is submitted to process.php when user clicks an item in the list – is set to data[‘info’][‘key’].

That is, user selects an option, and some underlying value needs to actually be submitted to process.php. We accomplish this by using the value in data[‘info’][‘key’] and setting it as the text to be submitted.

In other words, we need to add code which handles the user interaction, and this has to be done based on the type of control the user is interacting with.

At this time, the code only handles two types of controls which user can click – Suggestion Chips (buttons) and List view control. You can take a look at their behavior and write your own modifications for handling more complex controls (e.g carousel).

Rinse and repeat

As you might have imagined, you just need to repeat the same request – response sequence to turn it into a proper conversation.

Check out my demo project here (you can 1-click install it to Heroku).

>