Customized microsite

Customized microsites serve as separate gateways for clients in the mluvii application, its functionality is essentially big widgets. The creation process requires setting up a configuration widget, creating an HTML document, adding CSS styles, adding Javascript, and saving the page to any hosting that supports HTTPS protocol.

For its simplicity, as in other instructions, we will use codepen.io. You can start here.

Set up a WebChat widget

You create a new/modify an existing configuration widget in the application administration in the Configuration widgets section. You set up the widget button for “any button” - this will not show the button, however all the functionality with the button connected will be available to you. The chat window setting is optional.

The creation process

In these instructions you can create a microsite for Callback/Invitation, or chat and AV calls that will be able to connect users to the mluvii application, able to view the status of the button and work with call parameters (both preset and customized variables). The final version will be the following (Live version here):

Create an HTML file

The HTML document is as follows. Used images are stored on github pages, where you will save the entire microsite.

Add CSS styles

Adding JavaScript

Javascript will bring your microsite to life. First enter the code of your configuration widget.

(function () {
  var scr = document.createElement('script'); scr.type = 'text/javascript'; scr.async = true; scr.charset = 'UTF-8';
  scr.src = '//app.mluvii.com/widget/OOWidget.js';
  scr.$owidgetOnLoad = function (owidget) {
    if (!owidget.isSupported) { return; }
    owidget.init('295b1064-cf5b-4a5d-9e05-e7a74f86ae5e', 'navodMicroSite');
    owidget.connectToServer();
  };
  var ffs = document.getElementsByTagName('script')[0]; ffs.parentNode.insertBefore(scr, ffs);
})();
scr.$owidgetOnLoad = function (owidget) {
  // Náš kód
};

Widget status indication

Begin first with the status of the widget, whether or not the operators are assigned to that widget online, busy or offline. And with this feature:

owidget.setStatusUpdateCallback()

As a callback parameter a feature is taken that will be called each time the operator status information arrives from the server. This callback takes thecodeparameter, i.e. number 0 if the operators are offline, 1 - if they are online and 2 - if busy.

The $ owidgetOnLoad function code will still look like this:

if (!owidget.isSupported) { return; }
owidget.init('295b1064-cf5b-4a5d-9e05-e7a74f86ae5e', 'navodMicroSite');

let widgetOnline = true;

owidget.setStatusUpdateCallback(function(code) {
    const statusIndicatorImage = document.getElementById('StatusIndicatorCore-imageSelf');
    const statusIndicatorText = document.getElementById('StatusIndicatorCore-textSelf');

    switch(code) {
        case 0:
            statusIndicatorImage.src = 'Images/ikonka_konverzace-01_offline.png';
            statusIndicatorText.innerText = 'Jsme offline';
            statusIndicatorText.style.color = '#bf464f';
            widgetOnline = false; 
            break;
         case 1:
            statusIndicatorImage.src = 'Images/ikonka_konverzace-01_online.png';
            statusIndicatorText.innerText = 'Jsme online';
            statusIndicatorText.style.color = '#8dc63f';
            widgetOnline = true;
            break;
         case 2:
            statusIndicatorImage.src = 'Images/ikonka_konverzace-01_busy.png';
            statusIndicatorText.innerText = 'Máme toho hodně';
            statusIndicatorText.style.color = '#ffbb06';                                           
            widgetOnline = true;                        
            break;
         }
    });

Application

The next step is to launch the button to enter the button mluvii application. Let us first look at the Callback/Invitation option.

On the page, you have an input to enter an invitation number or a phone number and a button to enter the application. With this button, you will hear a click, as soon as it happens, we will open a large space in the mluvii application, unless all the operators are offline:

const widgetButton = document.getElementById('WidgetInput-button');
const widgetInput = document.getElementById('WidgetInput-input');

widgetButton.addEventListener('click', function() {
   if(!widgetOnline) return; // tuto proměnnou deklarujeme a nastavujeme výše.
   owidget.openApp('callshow', widgetInput.value);
}

You now add regular expression validation input so that only six and nine-digit numbers can be sent to the server, and the user will see a message about this status:

const hints = document.getElementById('Hints');
const regNumberLength6 = new RegExp('^\\d{6}$');
const regNumberLength9 = new RegExp('^\\d{9}$');

widgetButton.addEventListener('click', function() {
   if(!widgetOnline) return; // tuto proměnnou deklarujete a nastavujete výše.
   
   // V případě, že input neprošel jedním z našich testů, zobrazíte nápovědu
   if(!regNumberLength6.test(widgetInput.value) || !regNumberLength9.test(widgetInput.value)) {
     hints.classList.remove('isHidden');
   }

   // Pokud je číslo šestimístné, zahájíte Pozvánku v novém okně
   if(regNumberLength6.test(widgetInput.value)) {
     owidget.openApp('callshow', widgetInput.value)
   }

   // Pokud je číslo devítimístné, zahájíte callback v novém okně
   if(regNumberLength9.test(widgetInput.value)) {
     owidget.openApp('callback', widgetInput.value);
   }
}

For callback you must still readjust and use the features:

owidget.numberNormalization(string)
// or
owidget.setCustomNumberNormalization(vaseNormalizacniFunkce);

The first feature is a preset standardization feature that adds an international prefix to the phone number and possibly remove spaces,

The second feature allows you to add your own standardization function, such as your own international number,

Opening the callback will look like this:

if(regNumberLength9.test(widgetInput.value)) {
    owidget.numberNormalization(widgetInput.value)
    const normalizedNumber = owidget.numberNormalization(widgetInput.value);
    owidget.openApp('callback', normalizedNumber);
}

To make sure that the prompter disappears as soon as a user enters a six or nine-digit number into the input, create an “event listener” for this case:

widgetInput.addEventListener('input', function() {
  if(regNumberLength6.test(widgetInput.value) || regNumberLength9.test(widgetInput.value)) {
     hints.classList.add('isHidden');
  }
});

This secures the basic functionality of your microsite.

Chat, video chat

If you would like to provide customers with Callback/Invitations to provide chat or AV call services, just replace your Callback/Invitations feature for chat initialization or AV calls in your case. You can also delete the input for the invite number/phone number as these features do not need a parameter - you will also eliminate your testing of the embedded number.

Chat initialization:

owidget.openChat();

Initiate an AV call:

owidget.openApp("av");

The “event listener” on the call button would look like this in the case of an AV call:

widgetButton.addEventListener('click', function() {
   if(!widgetOnline) return;
   owidget.openApp("av");
}

Customized parameters

Along with a phone number or invitation number, you can send customized parameters by your operators. We created an input for this purpose on the microsite, which, if filled in, sends a variable (parameter) to the server. Enter the code before the tests with regular expressions:

const nameInput = document.getElementById('inputName');
if(nameInput.value !== '') {
    owidget.addCustomData('navod_clientName', nameInput.value);
}

You can also count on any other interactions, such as the log in/out of the user on the microsite. For the listener for the “Start Call” button, we would create additional listeners for the Login and Logout buttons, where the assumption is that the website has its own logic of user authentication. Use mluvii features at the moment of successful authentication/logout:

const login = document.getElementById('login');
const logout = document.getElementById('logout');

login.addEventListener('click', function() {
    // Logika autentizace zde, výsledek autentizace je přiřazené id uživatele, v callbacku autentizace bychom přidali naší funkci:
    const foundUserId = 'as3d21sad351as-as1d';
    owidget.addCustomData('navod_clientId', foundUserId);
});
logout.addEventListener('click', function() {
    // Logika odhlášení zde, v callbacku odhlášení pak použijeme funkce:
    owidget.removeCustomData('navod_clientId'); 
    // owidget.clearCustomData();
});

The owidget.removeCustomData feature takes the name of the variable you want to delete as the parameter. The owidget.clearCustomData () feature deletes all variables.

The Javascript of your microsite eventually looks like this:

Microsite publishing

If you are using codepen.io when creating your own CTA, it is now necessary to export the CTA. Click the “Save” button, then export it in “.zip” format

You can save CTA’s created as a subpage of your website or use any web hosting such as Github pages.

If you used the text editor, the resulting page will look like this:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">    
    <link href="https://fonts.googleapis.com/css?family=Raleway" rel="stylesheet">    
    <title>Document</title>
    <style>
        body {
            background-image: linear-gradient(to right, #6ca6bd, #8dc63f);
            font-size: Raleway;
        }
        html, body {
            margin: 0;
            padding: 0;
        }
        input, button, p, label {
            font-family: Raleway;            
        }
        .Logo {
            position: absolute;
            width: 25%;
            margin: 20px;
            min-width: 200px;
        }
        .Page {
            display: flex;
            width: 100%;
            height: 100vh;
            align-items: center;
            justify-content: center;
        }
        .Frame {
            background-color: white;
            width: 450px;
            height: 350px;
            border-radius: 10px;
            display: flex;
            flex-direction: column;
            overflow: hidden;
        }
        .StatusIndicator {
            flex: 3;
            display: flex;
            flex-direction: row;
            justify-content: center;
        }
        .StatusIndicatorCore {
            width: 300px;
            display: flex;
        }
        .StatusIndicatorCore-image {
            flex: 3;
            display: flex;
            align-items: center;
        }
        .StatusIndicatorCore-image>img {
            max-height: 100%;
            max-width: 100%;
        }
        .StatusIndicatorCore-text {
            flex: 7;
            display: flex;
            align-items: center;
        }
        #StatusIndicatorCore-textSelf {
            font-size: 35px;
            font-family: Raleway;
            font-weight: bold;
            color: #8dc63f;
            text-align: center;
            margin: 0;
        }
        .WidgetInput {
            width: 100%;
            flex: 7;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            position: relative;
        }
        #WidgetInput-input {
            width: 60%;
            height: 40px;
            border-radius: 8px;
            border: 1px solid #6ca6bd;
            font-size: 20px;
            text-align: center;
            color: #8dc63f;
            margin-bottom: 10px;
            box-sizing: border-box;
        }
        #WidgetInput-input:focus, #WidgetInput-button:focus, .LoginButtons:focus {
            outline: 0;
            border: 2px solid #6ca6bd;            
        }
        #WidgetInput-button {
            width: 60%;
            border-radius: 8px;
            border: 1px solid #6ca6bd;
            background-color: #8dc63f;    
            transition: all 0.3s;
            color: #fff;
            height: 40px;
            font-size: 20px;
            margin-bottom: 20px;
        }
        #WidgetInput-button:hover, .LoginButtons:hover {
            background-color: #6ca6bd;
        }
        #Hints {
            position: absolute;
            bottom: 0;
            background-color: #bf464f;
            color: white;
            width: 100%;
            padding: 10px 8px;
            text-align: center;
            box-sizing: border-box;
            margin: 0;
            transition: all ease-out 0.3s;
        }
        #Hints.isHidden {
            transform: translateY(100%);
        }
        .CustomVariables {
            position: absolute;
            bottom: 0;
            margin: 0 auto;
            height: 50px;
            width: 800px;
            border-radius: 10px 10px 0 0;
            background-color: #fff;
            display: flex;
            flex-direction: row;
            align-content: center;
        }
        .CustomVariables-input {
            flex: 1;
            text-align: center;
        }
        .CustomVariables-input:first-of-type {
            flex: 2;
        }
        .CustomInput {
            width: 250px;
            height: 30px;
            border-radius: 8px;
            border: 1px solid #6ca6bd;
            font-size: 18px;
            text-align: center;
            color: #8dc63f;
            box-sizing: border-box;
            margin: 10px 0;
            margin-left: 5px;
            outline: 0;
        }
        .CustomInput:focus {
            border: 2px solid #6ca6bd;
        }
        label {
            font-size: 20px;
            color: #5b5b5b;
        }
        .LoginButtons {
            width: 150px;
            border-radius: 8px;
            border: 1px solid #6ca6bd;
            background-color: #8dc63f;    
            transition: all 0.3s;
            color: #fff;
            height: 30px;
            font-size: 20px;
            margin: 10px 0;
        }
    </style>
</head>
<body>
    <img src="Images/logo-transparent-no-safezone.png" alt="" class="Logo">
    <div class="Page">
        <div class="Frame">
            <div class="StatusIndicator">
                <div class="StatusIndicatorCore">
                    <div class="StatusIndicatorCore-image">
                        <img id="StatusIndicatorCore-imageSelf" src="Images/ikonka_konverzace-01_online.png" alt="">                        
                    </div>
                    <div class="StatusIndicatorCore-text">
                        <p id="StatusIndicatorCore-textSelf">
                            Jsme online
                        </p>
                    </div>
                </div>
            </div>
            <div class="WidgetInput">
                <p id="Hints" class="isHidden">Zadejte prosím devítimístné telefonní číslo nebo šestímístné číslo pozvánky.</p>
                <input type="text" id="WidgetInput-input" placeholder="Telefon / č. pozvánky">
                <button id="WidgetInput-button">Začít hovor</button>
            </div>
        </div>
        <div class="CustomVariables">
            <div class="CustomVariables-input">
                <label for="inputName">Jméno:</label>
                <input type="text" class="CustomInput" id="inputName">
            </div>
            <div class="CustomVariables-input">
                <button class="LoginButtons" id="login">Login</button>
            </div>
            <div class="CustomVariables-input">
                <button class="LoginButtons" id="logout">Logout</button>
            </div>
        </div>
    </div>


    <script type="text/javascript">
        (function () {
        var scr = document.createElement('script'); scr.type = 'text/javascript'; scr.async = true; scr.charset = 'UTF-8';
        scr.src = '//app.mluvii.com/widget/OOWidget.js';
        scr.$owidgetOnLoad = function (owidget) {
            if (!owidget.isSupported) { return; }
            owidget.init('295b1064-cf5b-4a5d-9e05-e7a74f86ae5e', 'navodMicroSite');

            let widgetOnline = true;

            owidget.setStatusUpdateCallback(function(code) {
                const statusIndicatorImage = document.getElementById('StatusIndicatorCore-imageSelf');
                const statusIndicatorText = document.getElementById('StatusIndicatorCore-textSelf');

                switch(code) {
                    case 0:
                        statusIndicatorImage.src = 'Images/ikonka_konverzace-01_offline.png';
                        statusIndicatorText.innerText = 'Jsme offline';
                        statusIndicatorText.style.color = '#bf464f';
                        widgetOnline = false; 
                        break;
                    case 1:
                        statusIndicatorImage.src = 'Images/ikonka_konverzace-01_online.png';
                        statusIndicatorText.innerText = 'Jsme online';
                        statusIndicatorText.style.color = '#8dc63f';
                        widgetOnline = true;
                        break;
                    case 2:
                        statusIndicatorImage.src = 'Images/ikonka_konverzace-01_busy.png';
                        statusIndicatorText.innerText = 'Máme toho hodně';
                        statusIndicatorText.style.color = '#ffbb06';                                           
                        widgetOnline = true;                        
                        break;
                }
            });


            const widgetButton = document.getElementById('WidgetInput-button');
            const widgetInput = document.getElementById('WidgetInput-input');
            const hints = document.getElementById('Hints');

            const nameInput = document.getElementById('inputName');

            const login = document.getElementById('login');
            const logout = document.getElementById('logout');

            const regNumberLength6 = new RegExp('^\\d{6}$');
            const regNumberLength9 = new RegExp('^\\d{9}$');

            widgetButton.addEventListener('click', function(e) {
                if(!widgetOnline) return;

                if(nameInput.value !== '') {
                    owidget.addCustomData('navod_clientName', nameInput.value);
                }

                
                if(!regNumberLength6.test(widgetInput.value) || !regNumberLength9.test(widgetInput.value)) {
                    hints.classList.remove('isHidden');
                }
                if(regNumberLength6.test(widgetInput.value)) {
                    owidget.openApp('callshow', widgetInput.value)
                }
                if(regNumberLength9.test(widgetInput.value)) {
                    owidget.numberNormalization(widgetInput.value)
                    const normalizedNumber = owidget.numberNormalization(widgetInput.value);
                    owidget.openApp('callback', normalizedNumber);
                }
            });

            widgetInput.addEventListener('input', function() {
                if(regNumberLength6.test(widgetInput.value) || regNumberLength9.test(widgetInput.value)) {
                    hints.classList.add('isHidden');
                }
            });

            login.addEventListener('click', function() {
                const foundUserId = 'as3d21sad351as-as1d';
                owidget.addCustomData('navod_clientId', foundUserId);
            });
            logout.addEventListener('click', function() {
                owidget.removeCustomData('navod_clientId');
                // owidget.clearCustomData();
            });

            owidget.connectToServer();
        };
        var ffs = document.getElementsByTagName('script')[0]; ffs.parentNode.insertBefore(scr, ffs);
        })();
    </script>
</body>
</html>

Last updated