Home / API.AI / Initiate the conversation in DialogFlow (API.AI) – PHP code sample
API.AI

Initiate the conversation in DialogFlow (API.AI) – PHP code sample

I had written an article previously on the basic principle you would use to get API.AI to start a chat before the user types a message. I had only used the cURL command to explain it, and recently I got a request to explain it using some sample code.

In this article, I will show you how to do it in PHP.

Prerequisite

As it turns out, when you try to use sample code rather than cURL to explain the same concept, there is a little bit more setup work.

For one thing, since you are using the REST API, it follows that you need to have created your own custom webchat UI. You cannot mix the integrated web demo with a REST API call because the integrated web demo is an iFrame served from API.AI’s server.

I had written an article which explains some of the setup already. You should read that article as a prerequisite before reading this one, since the first article goes over the basic concepts.

Folder structure

In this example, I will add a file called starter.php to the code structure. The starter.php will trigger the default welcome intent, collect the response and save it to a DOM element.

Code

I have already explained the basics of the code in the previous article. So here I will show you the additional code involved.

index.php:

<html>
<head>
    <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
    <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <script src="js/chatbot.js"></script>
    <link rel="stylesheet" href="css/chatbot.css" type="text/css">
    <script>
        (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
                (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
            m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
        })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

        ga('create', 'UA-76380861-2', 'auto');
        ga('send', 'pageview');

    </script>
</head>
<body>

<div class="topstrip" id="topstrip">Powered by <a href="https://www.miningbusinessdata.com" style="color:#d3d3d3"> MiningBusinessData</a>&nbsp;&nbsp;&nbsp;</div>
<div class="topbar" id="chat-text">
</div>
<form>
    <span style="width:100%;">
        <input class="inputbox"
               placeholder="Write something and press Enter..." id="message" name="date" value="">
    </span>
    <input name="submit" type="hidden" value="Submit">
</form>
<?php
$sessionID = uniqid('',true);
include('starter.php');
?>
<span style="display: none;" id="sessionId">
        <?php
        echo $sessionID;
        ?>
    </span>
</body>
</html>

starter.php

<?php
/**
 * Created by PhpStorm.
 * User: aravind
 * Date: 8/25/17
 * Time: 7:50 PM
 */
try {
    // create curl resource
    $ch = curl_init();
    // set url
    curl_setopt($ch, CURLOPT_URL, "https://api.api.ai/v1/query?v=20150910&e=WELCOME&lang=en&sessionId=" . $sessionID);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Authorization: Bearer CLIENT_ACCESS_TOKEN'));
    //return the transfer as a string
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    // $output contains the output string
    $output = curl_exec($ch);
    // close curl resource to free up system resources
    curl_close($ch);
}catch (Exception $e) {
    $speech = $e->getMessage();
    $fulfillment = new stdClass();
    $fulfillment->speech = $speech;
    $result = new stdClass();
    $result->fulfillment = $fulfillment;
    $response = new stdClass();
    $response->result = $result;
    echo json_encode($response);
}
?>

<div id="dom-target" style="display: none;">
    <?php

        echo htmlspecialchars($output); /* You have to escape because the result will not be valid HTML otherwise. */
    ?>
</div>

process.php

<?php
try {
    if(isset($_POST['submit'])){
        $query = $_POST['message'];
        $sessionid = $_POST['sessionid'];
        $postData = array('query' => array($query), 'lang' => 'en', 'sessionId' => $sessionid);
        $jsonData = json_encode($postData);
        $v = date('Ymd');
        $ch = curl_init('https://api.api.ai/v1/query?v='.$v);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Authorization: Bearer CLIENT_ACCESS_TOKEN'));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $result = curl_exec($ch);
        echo $result;
        curl_close($ch);
    }
}
catch (Exception $e) {
    $speech = $e->getMessage();
    $fulfillment = new stdClass();
    $fulfillment->speech = $speech;
    $result = new stdClass();
    $result->fulfillment = $fulfillment;
    $response = new stdClass();
    $response->result = $result;
    echo json_encode($response);
}
?>

chatbot.js

/**
 * Created by aravind on 4/28/17.
 */


$(function () {
    window.initialMessageDisplayed = false;
    $(document).mouseenter(function(){
        if(!window.initialMessageDisplayed){
            var obj = JSON.parse($("#dom-target").text());
            var event = obj.result.action;
            var answerdiv = jQuery('<div/>', {
                html: obj.result.fulfillment.speech.linkify()+'&nbsp;',
                'class': "rounded-div-bot",
                tabindex:1
            });
            $("#chat-text").append(answerdiv);
            $("#message").focus();
            window.initialMessageDisplayed = true;
        }
    });


    var guid = ($("#sessionId").text()).trim();


    $('form').on('submit', function (e) {
        var query = $("#message").val();
        try{
            sendGAEvent('iFrame', guid, 'userSays: '+query);
        }
        catch(e){
            console.log(e);
        }

        showUserText();
        e.preventDefault();


        $.ajax({
            type: 'post',
            url: 'process.php',
            data: {submit:true, message:query, sessionid: guid},
            success: function (response) {
                var obj = JSON.parse(response);
                var event = obj.result.action;
                var answerdiv = jQuery('<div/>', {
                    html: obj.result.fulfillment.speech.linkify()+'&nbsp;',
                    'class': "rounded-div-bot",
                    tabindex:1
                });
                $("#chat-text").append(answerdiv);
                if(event){
                    var stylingDiv = jQuery('<div/>', {
                        html: $("#template").html(),
                        tabindex:1
                    });
                    if(event === 'show.customizer'){
                        $(answerdiv).append(stylingDiv);
                    }
                }
                $(answerdiv).focus();
                $("#message").focus();
                try{
                    sendGAEvent('iFrame',guid,'botSays: '+obj.result.fulfillment.speech)
                }
                catch(e){
                    console.log(e);
                }
            }
        });

    });

});

function sendGAEvent(category, action, label){
    //var d = new Date();
    //var t = d.getTime();
    //ga('send','event',category,action,label,t);
}

function showUserText(){
    var div = jQuery('<div/>', {
        text: $("#message").val(),
        'class': "rounded-div",
        tabindex:1
    });
    $("#chat-text" ).append(div);
    $("#message").val('');
}

if(!String.linkify) {
    String.prototype.linkify = function() {

        // http://, https://, ftp://
        var urlPattern = /\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim;

        // www. sans http:// or https://
        var pseudoUrlPattern = /(^|[^\/])(www\.[\S]+(\b|$))/gim;

        // Email addresses
        var emailAddressPattern = /[\w.][email protected][a-zA-Z_-]+?(?:\.[a-zA-Z]{2,6})+/gim;

        return this
            .replace(urlPattern,
                '<a class="answerLink" style="color:#0000EE" target="_blank" href="$&">$&</a>')
            .replace(pseudoUrlPattern,
                '$1<a class="answerLink" style="color:#0000EE" target="_blank" href="http://$2">$2</a>')
            .replace(emailAddressPattern,
                '<a class="answerLink" style="color:#0000EE" href="mailto:$&">$&</a>');
    };
}

chatbot.css

.topstrip{
    width:99%;
    overflow-y: scroll;
    position:fixed;
    top:0px;
    height:50px;
    background-color: black;
    color:white;
    text-align: right;
    font-size: 16px;
    font-family: Georgia;
}
.topbar{
    display:block;
    width:100%;
    overflow-y: scroll;
    position:fixed;
    top:50px;
    bottom:65px;
}
.rounded-div-bot{
    display:inline-block;
    clear:left;
    max-width:80%;
    border-radius: 5px;
    border:solid 1px black;
    background-color: lightgreen;
    float:right;
    margin: 10px;
    padding:5px;
    min-height: 1em;
}
.rounded-div{
    display:inline-block;
    clear:right;
    max-width:80%;
    border-radius: 5px;
    margin: 10px;
    padding:5px;
    border:solid 1px black;
    background-color: lightgray;
    float:left;
}
.inputbox{
    outline:none;
    width:98%;
    height:40px;
    position:fixed;
    bottom:25px;
}

Demo

I started with the WebhookAssistant bot and implemented a custom web UI layer on top of it. (It is not clearly visible in the animated GIF below, but the message “Hello. What can I do for you?” only shows up when you hover over the chat window).

Installation

The instructions for installation are similar to the previous article and you can check it out over there.

I have also added the full code sample and the corresponding Dialogflow agent ZIP file in my MBD Resources course. (Chapter 13)

As in the previous article, you should consider this code as a demo and a learning resource, and you understand that I am not responsible if there are any issues on your website by using the above code.

Related Posts

  • Please share the node js code for the above article. I am calling my api on bot button click,but in dailogflow fulfilment want to get session id in node js.please help me for this.How can i get session id value in welcome methode in fulfilment

  • hi Aravind, your post are awesome and really very helpful to understand the concepts. I am new to bot world and trying to achieve this feature in my sample bot using DialogFlow. I am using Node.JS here. Any pointers how can I achieve this using node.js?

  • Hi, When i executed the above code i got an error saying that “Uncaught TypeError: Cannot read property ‘action’ of undefined
    at HTMLDocument. (chatbot.js:11)”

    Can you help on this?
    Thank you

    • My suggestion is to set up PHP debugging on your dev machine, and get the code running locally and step through the code.

  • Hi,

    I am working chatbot with DialogFlow and FB integration with core PHP. Here i stuck with some concept that was, can we trigger the particular dialogflow intent by php code which means i am checkin some condition, the condition is true i want to trigger the intent from php script. is there is any way to do it?

    Thanking you,

    • The answer, generally speaking, is to use Events in your intent and trigger the Event by making an API call. I am not sure if that is what you are asking about here.

      • Thanks for your valuable comment,

        Here what am i doing is, i have used web hook and FB integration and also stored the user details in DB by FB sender ID . Once user start conversation with my chat bot then i will check the user was available or not in my DB.

        If available, i will trigger one of my intent in dialog flow with next conversation response, also if not available then trigger the another intent with different response.

        i hope now you have some clearance,

        is it possible?

        Thanks

        • Frankly, that’s a little complex to answer without actually looking at your app. If you are interested in 1-on-1 Skype coaching, you can get in touch via the contact form. miningbusinessdata.com/work-with-me/

  • I wanna thank for this article. and the using php .First one worked well.
    for bot initiating chat , I tried this one. I m getting error.
    “status”: {
    “code”: 206,
    “errorType”: “partial_content”,
    “errorDetails”: “Webhook call failed. Error: Webhook response was empty.”,
    “webhookTimedOut”: false
    },

    Help me this.
    Thank You,

    • The error message says that you didn’t format the response object correctly. You need to set up ngrok and step through the code to debug it.