21 Channels

What Are Channels?

Channels carry the chat back and forth from users on various messaging platforms to the digital assistant and its various skill bots. They also support user agent escalation, event-initiated conversations, and testing.

Channel Types

You can create and manage the following channel types from the Channels page, which you access by clicking Channels in the left menu. There’s a tab for each type.

Channel Type Uses
Users
Agent Integrations
  • Configure the Oracle Service Cloud account information that connects the user to a live agent.

  • Enable or disable the agent integration. Configure the Agent Integration Channel describes configuring the Oracle Cloud Service account in conjunction with configuring the dialog flow with the agent integration components.

Applications
  • Configure the application channel through which an external application sends notifications to a skill so that it can trigger a conversation. AIC Configuration describes the process of configuring the skill to respond to notifications.

  • Enable or disable the application from sending this notification (and therefore prevent the skill-initiated conversation).

System
  • Enable or disable the chat on the Skill Tester for all skill developers.

  • Reset the chat sessions for all skill developers.

User Channel Routing

You can route each user-facing channel to a single version of a digital assistant (This is an image of the digital assistant routing icon.) or to a single version of a skill (This is an image of the skill routing icon.). Only one version of a skill or digital assistant can run on a channel at any given time. When you create new version of the skill, you can stop the routing to the old version and then assign the routing to the updated version.
Description of routing_menu.png follows
Description of the illustration routing_menu.png

You can support running two versions of a skill or digital assistant concurrently by creating separate channels for each one. For example, beta testers could access the skill through one channel while customers continue to chat through a separate channel uninterrupted.

In addition, your pool of user-facing channels can be routed and re-routed from one skill or digital assistant to another, eliminating the need for users to switch accounts when you create new versions.

Note:

Whenever you discontinue and then reassign the routing, you risk continuity gaps. Current conversations may be lost during the switch-over and when users do receive replies, they’ll originate from a different skill. If you’re routing to a newer version of a skill, this transition may be seamless, but it may be jarring if you route to a skill that performs an entirely different set of tasks.

Note:

You can’t change the routing for a skill (or rather, a bot) that was built using pre-18.4.3 versions of the product. Because the channel configuration is intrinsic to bots (there’s a one-to-one relationship between a bot and its channels), routing is disabled: read-only information about the bot-to-channel routing displays in place of the Route To option.

How Digital Assistant Channel Routing Works

When you register a skill to a digital assistant, both the messages that it sends and receives are relayed through the digital assistant’s channels. The digital assistant’s routing takes over, even if the skill already has other channels routed to it.

For example, say there two skills, each with their own web channel that have been registered to a digital assistant, which in turn routes to its own web channel and to a Facebook channel. When users send a message to the digital assistant through the digital assistant’s web channel, it determines the intent and sends the message to the appropriate skill. When the skill replies, its message is sent back to the user over the digital assistant’s web channel, not through the skill’s web channel. Likewise, when the digital assistant intercepts a message from a Facebook subscriber, the skill’s response to the user is sent back over the digital assistant’s Facebook channel instead of the skill’s own web channel.

Enable or Disable Channels

From time to time, you may need to disable a channel to perform maintenance or updates to the configuration and then re-enable the channel..

To do so, you can use the these switches:

  • Channel Enabled
  • Interaction Enabled (for agent integrations)
  • Application Enabled (for applications)

Disabling the System channel, which supports the Skill tester, alerts developers that channel is unavailable.

To access these options:

  • Click icon to open the side menu to open the side menu, select Development > Channels, and select the channel.

Reset Sessions

You can break off the current conversations in a channel by clicking its Reset Sessions button.

You can use this option, for example, to cut off the message flow during a denial of service attack to keep your server from getting overwhelmed.

To access the Reset Sessions button:

  • Click icon to open the side menu to open the side menu, select Development > Channels, and select the channel.

User Channel Configuration

Facebook Messenger

You’ll need the following to configure the channel for Facebook Messenger:
  • A Facebook Developer account

  • A Facebook page

  • A Facebook app

  • A page access token

  • An app secret ID

  • The webhook URL

  • A verify token

To run your bot on Facebook Messenger, you first need to set up a Facebook page and a Facebook app. You can find out more about this from the Facebook Messaging Platform documentation.

In a nutshell, here's how it works. The Facebook page hosts your bot. Users chat with your bot through this page when they use the chat window in a desktop browser. When they use a mobile device, users interact with your bot directly through Facebook Messenger itself. In this scenario, the Facebook app allows your bot to get the messages that are handled by Facebook Messenger.

To create a Facebook Messenger channel, you need artifacts that are generated by both ODA and by Facebook Messenger.

From ODA, you’ll need:

  • the webhook URL that connects your bot to Facebook Messenger
  • the verify token that enables Facebook Messenger to identify the bot

From Facebook Messenger, you’ll need:

  • the page access token
  • the app secret ID

Because you need transfer these artifacts between ODA and Facebook Messenger, you’ll need to switch between these two platforms as you configure the channel.

Step 1: Set Up Facebook Messenger

Start off by generating the App Secret and the Page Access token in Facebook Messenger.

  1. Log into your Facebook developer’s account.

  2. Create a Facebook page that hosts your bot. The description, images, and cover page you add to the page will identify your bot to its users.

  3. Next, create the Facebook app that you’ll link to this page. Because this is a Messenger app, choose Apps for Messenger and then click Create App ID.
    Description of setup_fbapp.png follows
    Description of the illustration setup_fbapp.png

    If you didn't choose the Apps for Messenger option in this dialog (for example, if you’re creating a test app), then click Add Product in the left navbar, choose Messenger from the Product Setup page, and then click Get Started.
    Description of add_product.png follows
    Description of the illustration add_product.png

  4. On the Dashboard page of the Facebook app, copy the app secret and paste somewhere convenient on your system.
    Description of facebook_dashboard.png follows
    Description of the illustration facebook_dashboard.png

    You’ll need the app secret to complete your Facebook channel configuration.

  5. In the Dashboard for your app, generate the Page Access Token by selecting your Facebook page.
    Description of page_access_token.png follows
    Description of the illustration page_access_token.png

  6. Copy the access token and paste it somewhere convenient.

    You’ll use this token, which gives your Facebook App access to Facebook’s Messaging API, to complete your channel definition in ODA.

Important:

Changes to the Facebook User Profile API require that you now must request permissions for certain user profile fields for any Facebook app that you created before or after July 26, 2018. Without the following permissions, the user’s name will be populated as a random numeric string.
  • pages_messaging

  • pages_user_locale

  • pages_user_timezone

If you created the app before July 26, you have until January 29, 2019 to apply the permissions. If you created your app after July 26, 2018, then you need to add these permissions as soon as possible. You can set them in the App Review for Messenger section of the Messenger page.
Step 2: Add the Facebook Keys
Complete the Create Channel dialog by providing the Page Access Token and App Secret keys from Facebook.
  1. In ODA, click Channels in the left menu and then choose Users.
  2. Next, click Add Channel to open the Create Channel dialog.

  3. Give your channel a name.

  4. Choose Facebook Messenger as the channel type.
    Description of create_channel_dialog_started.png follows
    Description of the illustration create_channel_dialog_started.png

  5. In the Page Access Token field, paste the page access token that you generated previously in the Set Up Facebook Messenger procedure.

  6. In the App Secret field, paste the app secret that you copied previously in the Set Up Facebook Messenger procedure.

  7. Click Create.

  8. In the Channels page, copy both the Verify Token and WebHook URL and paste them somewhere convenient on your system. You’ll need these to configure the Facebook webhook.
    Description of fb_channel_complete.png follows
    Description of the illustration fb_channel_complete.png

Step 3: Configure the Facebook Messenger Webhook
In Facebook Messenger, define the Callback URL using the Webhook URL generated by ODA in the previous step.
  1. In Facebook Messenger, be sure that you’ve selected the project that you initially created for the webhook.



  2. Click Messenger and then choose Settings .
    Description of fb_navbar.png follows
    Description of the illustration fb_navbar.png

  3. Click Setup Webhooks to open the New Page Subscription dialog.

  4. Copy the Webhook URL that you got from the ODA Channels page and paste it in the CallBack URL field in the New Page Subscription dialog.

  5. Copy the Verify Token generated by ODA and paste it into the Verify Token field.

  6. Under Subscription Fields, select the messages and messaging_postbacks callback events.

    The messages event is triggered whenever someone sends a message to your Facebook page.

  7. Click Verify and Save.
  8. Subscribe to the page:
    1. In the Webhooks section of the Messenger settings, select the Facebook page for your digital assistant (or standalone skill).

    2. Click Subscribe.

    .

    Tip:

    You might need to bounce your webhook by first clicking Unsubscribe then Subscribe.
Step 4: Enable the Facebook Channel

With the configuration complete, you’re ready to activate the Facebook channel.

  • In ODA, select the channel and switch on the Channel Enabled control.

You can now test out your bot.

Step 5: Test Your Bot on Facebook Messenger

With the Facebook Channel and messaging configuration complete, you can test your simultaneously using your Facebook page, Facebook Messenger (https://www.messenger.com/) and the Facebook Messenger app on your phone (This is an image of the Facebook app icon.). Once you locate your bot in the search, you’re ready to start chatting with it. You can see the changes that you make to the dialog flow in real time.
Description of test_bot.png follows
Description of the illustration test_bot.png

Webhooks

If your channel or messaging service is not supported out of the box you can use an HTTP webhook channel to manually integrate ODA with it.

To create a webhook channel, you need the following:
  • A publicly accessible HTTP messaging server that relays messages between the user device and your bot using a webhook.

    You implement this webhook with:

    • A POST call that enables the server to receive messages from your bot.

    • A POST call that enables the server to send messages to your bot.

  • The URI of the webhook call that receives your bot’s messages (so the bot knows where to send the messages).

  • The Webhook URL that’s generated for your bot after you complete the Create Channel dialog (so that the message server can access your bot).

To assemble these pieces into a webhook:
  1. Set up the server.

  2. To receive messages from your bot, publish the POST call on the server.

  3. In the Create Channel dialog, enter a name and then:
    • Choose Webhook as the channel type.

    • Set Platform Version to 1.1 (Conversation Model).

    • Register the server as the recipient of your bot’s messages by entering the URI to this POST call in the Outgoing Webhook URI field.

    • If needed, enter the session expiry and switch on Channel Enabled.


    Description of create_webhook_channel.png follows
    Description of the illustration create_webhook_channel.png
  4. Click Create.

    ODA generates the webhook URL for your bot and its Secret Key for encrypting messages. Keep the webhook URL handy, because it’s the pointer that your messaging server needs to send messages back to your bot.
    Description of webhook_channel_config.png follows
    Description of the illustration webhook_channel_config.png

  5. On your server, publish the second POST API, one that sends messages to your bot using the webhook URL.

  6. Switch the Channel Enabled option on.

Video: An Introduction to Channels

To find out more about webhooks, check out this video.

Inbound Messages
The call for sending messages to your bot must have:
  1. An X-Hub-Signature header containing the SHA256 value of the payload. The call includes functions that create this hash using Secret Key as the key.
    const body = Buffer.from(JSON.stringify(messageToBot), 'utf8');
        const headers = {};
        headers['Content-Type'] = 'application/json; charset=utf-8';
        headers['X-Hub-Signature'] = buildSignatureHeader(body, channelSecretKey);
    
    ...
    
    function buildSignatureHeader(buf, channelSecretKey) {
        return 'sha256=' + buildSignature(buf, channelSecretKey);
    }
    
    function buildSignature(buf, channelSecretKey) {
        const hmac = crypto.createHmac('sha256', Buffer.from(channelSecretKey, 'utf8'));
        hmac.update(buf);
        return hmac.digest('hex');
    }
  2. A JSON object with userId, userProfile, and messagePayload properties:
    {
     "userId: "33c0bcBc8e-378c-4496-bc2a-b2b9647de2317"
     "userProfile": {
        "firstName": "Bob",
        "lastName": "Franklin",
        "age": 45
       },
     "messagePayload: {....}
    }
    Property Description Type Required?
    userId A unique identifier for the user. This ID is specific to the caller. String Yes
    userProfile Properties that represent the user, like firstName and LastName. JSON object No
    messagePayload The messagePayload can be text, postback, attachment, and location:
    • text
      {
          "type": "text",
          "text": hello, world!"
        }
      
    • postback
      {
          "type": "postback",
          "postback": {
            "state": "orderPizza",
            "action": "deliverPizza",
            "variables": {
              "pizzaSize": "Large",
              "pizzaCrust": "Thin",
              "pizzaType": "Hawaiian"
            }
          }
        }
      
    • attachment
      {
          "type": "attachment",
          "attachment": {
            "type": "image",
            "url": "https://image.freepik.com/free-icon/attachment-tool-ios-7-interface-symbol_318-35539.jpg"
          }
      }
    • location
      {
          "type": "location",
          "location": {
            "longitude": -122.265987
            "latitude": 37.529818
          }
        }
    JSON object Yes
Outbound Messages

You need to publish the calls in the JSON format that ODA expects, along with the authorization header.

The call for your bot’s outbound messages includes:
  1. An X-Hub-Signature header containing the SHA256 value of the payload, calculated using the Secret Key as the key.

    Note:

    ODA uses the X-Hub-Signature header to allow the recipient to authenticate your bot as the sender and validate the integrity of the payload.
  2. A JSON payload containing the userID, a unique identifier that’s specified by the inbound message, the type, which can be text,attachment, and card. As shown in the following examples, both the text and card response types can have associated actions. Any of the response types can also include global actions.
    Response Type Example Payload
    text
    {
     "userId":"22343248763458761287
     "messagePayload": {
        "type": "text",
        "text": "Hello, how are you?"
         }
    }
    The following snippet show a text response with actions:
    {
     "userId":"22343248763458761287
     "messagePayload": {
        "type": "text",
        "text": "What do you want to do?",
        "actions": [
          {
            "type": "postback",
            "label": "Order Pizza",
            "postback": {
              "state": "askAction",
              "action": "orderPizza"
            }
          },
          {
            "type": "postback",
            "label": "Cancel A Previous Order",
            "postback": {
              "state": "askAction",
              "action": "cancelOrder"
          }
        ]
      }
    }
    card
    
    ...
    {
     "type": "card",
      "layout": "horiztonal",
      "cards": [
        {
          "title": "Hawaiian Pizza",
          "description": "Ham and pineapple on thin crust",
          "actions": [
            {
              "type": "postback",
              "label": "Order Small",
              "postback": {
                "state": "GetOrder",
                "variables": {
                  "pizzaType": "hawaiian",
                  "pizzaCrust": "thin",
                  "pizzaSize": "small"
                }
              }
            },
            {
              "type": "postback",
              "label": "Order Large",
              "postback": {
                "state": "GetOrder",
                "variables": {
                  "pizzaType": "hawaiian",
                  "pizzaCrust": "thin",
                  "pizzaSize": "large"
                }
              }
            }
          ]
        },
        {
          "title": "Cheese Pizza",
          "description": "Cheese pizza (i.e. pizza with NO toppings) on thick crust",
          "actions": [
            {
              "type": "postback",
              "label": "Order Small",
              "postback": {
                "state": "GetOrder",
                "variables": {
                  "pizzaType": "cheese",
                  "pizzaCrust": "thick",
                  "pizzaSize": "small"
                }
              }
            },
            {
              "type": "postback",
              "label": "Order Large",
              "postback": {
                "state": "GetOrder",
                "variables": {
                  "pizzaType": "cheese",
                  "pizzaCrust": "thick",
                  "pizzaSize": "large"
                }
              }
            }
          ]
        }
      ],
      "globalActions": [
        {
          "type": "call",
          "label": "Call for Help",
          "phoneNumber": "123456789"
        }
      ]
    }
    attachment The attachment response type can an image, audio file, or a video:
    
    ...
    {
      "type": "attachment",
      "attachment": {
        "type": "video",
        "url": "https://www.youtube.com/watch?v=CMNry4PE93Y"
      }
    }

Client Messaging Apps and Web Pages

Using the client SDKs, you can integrate your bot with iOS apps, Android apps, and web pages. Your bot doesn’t communicate with these clients directly; instead a chat server, one with message handlers implemented for each channel type, acts as an intermediary. It communicates with your bot via HTTPS requests. For clients, it uses WebSockets. The SDK’s client libraries, when deployed on the native apps (or in the case of a web page, the web server that hosts that page) establish the WebSocket connection to the appropriate message handler.

For any of these integrations, you need to generate the App ID by creating a Web, iOS, or Android channel. After you create the App ID, you copy and paste it into the client app code or, if you’re integrating your bot into a web page, the <script> tag.

Android
Add the Client SDK to Your App

The ODA Client SDK for Android library is distributed in both AAR and JAR formats. If you are using Android Studio, follow the instructions for installation of the AAR package.

Note:

Compile your app using API Level 26 (Android Oreo) or higher. Level 19 (Android 4.4, Kitkat) is the lowest version that can support the ODA Client SDK for Android. If your app needs to support even earlier versions, keep in mind that we haven’t tested these and therefore can’t guarantee their compatibility.
Add the SDK and AAR Files
  1. Download the Bots Client SDK for Android module from the Oracle Technology Network’s ODA and OMC download page.

  2. Import the core and UI files (bots-client-sdk-android-core-vv<version_number>.aar and bots-client-sdk-android-ui-v<version_number>.aar into your Android Studio project by going to File > New > New Module > Import .JAR/.AAR Package.

  3. Add the following lines to the project’s build.gradle file:
        compile project(':bots-client-sdk-android-core-1.2.1')
        compile project(':bots-client-sdk-android-ui-1.2.1') 
    
        compile 'com.google.firebase:firebase-messaging:11.0.4'
        compile 'com.google.firebase:firebase-core:11.0.4'
        compile 'com.google.code.gson:gson:2.4'
        compile 'com.squareup.okhttp3:okhttp:3.4.1'
        compile 'com.android.support:support-annotations:26.0.2'
        compile 'com.android.support:appcompat-v7:26.0.2'
        compile 'com.android.support:recyclerview-v7:26.0.2'
        compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
        compile 'com.davemorrissey.labs:subsampling-scale-image-view:3.5.0'
        compile 'com.google.android.gms:play-services-location:11.0.4' 
Initialize the Bots Android SDK in Your App

Before your code can invoke the SDK’s functionality, you’ll have to initialize the library using your app’s ID.

To get this unique ID, first click Add Channel to open the Add Channel dialog. Complete the dialog by adding a channel name and then choosing Android as the channel type. After you click OK, Bots generates the App ID.

After you obtain this ID, use the following to initialize the SDK.
Bots.init(this, new Settings("YOUR_APP_ID"), newBotsCallback() {
     @Override
     public void run(Response response) {
          // Your code after init is complete
    }
});

Note:

Make sure to replace YOUR_APP_ID with your app ID.
To ensure that the SDK is always initialized properly, copy the following snippet and save it to your application package.
package your.package;

import android.app.Application;
import oracle.cloud.mobile.core.Bots;

public class YourApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        Bots.init(this, new Settings("YOUR_APP_ID"), new BotsCallback() {
            @Override
            public void run(Response response) {
                // Your code after init is complete
            }
        });
    }

Note:

You need to declare this in the Application class because it’s the class that’s required by Bots.init(this, new Settings("YOUR_APP_ID"). If you declare this class elsewhere (say, AppCompatActivity), then add the following snippet, which uses getApplication() as the first argument:
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        Bots.init(getApplication(), new Settings("YOUR_APP_ID"), new BotsCallback() {
            @Override
            public void run(Response response) {
                // Your code after init is complete
            }
        });
    } 
You also need to declare your newly created class in the <application> tag in your AndroidManifest file.
<application
    android:name="your.package.YourApplication">
    ...
</application>

Note:

Remember to replace your.package, YourApplication, YOUR_APP_ID with the appropriate names and the App Id for the Android channel.
Display the Bots Android SDK User Interface

Once you’ve initialized Bots Android SDK, you’re ready to try it out.

Find a suitable place in your app’s interface to invoke the SDK and use the code below to display the Android Messenger user interface. You invoke up the Bots Android SDK whenever your user needs access to help or needs to contact you.
ConversationActivity.show(getApplicationContext());
Call Other Functions
You can call various functions when the SDK has been initialized successfully. As shown in the following snippet, you can update user properties before your app calls the ConversationActivity class:
if (Bots.getInitializationStatus() == InitializationStatus.Success) {
   Log.d(TAG,"Already Initialized with App ID "+ mAppID);
   User.getCurrentUser().setFirstName("John");
   User.getCurrentUser().setLastName("Smith");
   User.getCurrentUser().setEmail("john.smith@example.com");
   User.getCurrentUser().setSignedUpAt(new Date());


  final Map<String, Object> customProperties = new HashMap<>();
  customProperties.put("premiumUser", true);
  customProperties.put("numberOfPurchases", 20);
  customProperties.put("itemsInCart", 3);
  customProperties.put("couponCode", "PREM_USR");
  User.getCurrentUser().addProperties(customProperties);

  ConversationActivity.show(getApplicationContext(), Intent.FLAG_ACTIVITY_NEW_TASK);
}
Replace the FileProvider Entry

If you do not have a FileProvider entry in your AndroidManifest.xml file, you can ignore this section. These steps will fix the Manifest merger failed : Attribute provider#android.support.v4.content.FileProvider@authorities compile error

To replace the FileProvider entry with your own::
  1. Add tools:replace="android:authorities" to the <provider> entry.

  2. Add the following path to your android.support.FILE_PROVIDER_PATHS resource file:
    <external-path name="dcim" path="DCIM"/>
  3. When initializing the SDK, call settings.setFileProviderAuthorities(authoritiesString); on the settings object.
    Settings settings = new Settings(appId);
    settings.setFileProviderAuthorities(authoritiesString);
    Bots.init(this, settings, myInitCallback);
Localization

Every string you see in ODA can be customized and localized. ODA provides a few languages out of the box, but adding new languages is easy to do. When localizing strings,ODA looks for values in the strings.xml in your app first then in the ODA UI bundle, enabling you to customize any strings and add support for other languages.

Add More Languages

To enable other languages beside the provided ones, first copy the English strings.xml file from the ODA UI bundle to the corresponding values folder for that language. Then, translate the values to match that language.

Strings Customization

ODA lets you customize any strings it displays by overwriting its keys. To do this, simply add res/values-<your-language-code>/strings.xml file in your Android project and specify new values for the keys used in ODA. You can find all of the available keys by browsing to the artifacts:bots-client-sdk-android-ui-x.x.x/res/values/values.xml file in the External Libraries in Android Studio.

Dates shown in the conversation view are already localized to the user’s device.

For example, if you wanted to override strings for English, you would create a file called res/values-en/strings.xml and include the following in that file:
<resources>
<string name="Bots_activityConversation">Messages</string>
<string name="Bots_startOfConversation">This is the start of your conversation with the team.</string>
<string name="Bots_welcome">Feel free to leave us a message about anything that\'s on your mind.</string>
<string name="Bots_messageHint">Type a message…</string>
</resources>

Note:

if you want to specify new strings for the default fallback language, you must override them in the res/values/string.xml file.
Style the Conversation Interface

Using a colors.xml file in your res/values folder, you can change the colors used by Bots:

<resources>
<color name="Bots_accent">#9200aa</color>
<color name="Bots_accentDark">#76008a</color>
<color name="Bots_accentLight">#be7cca</color>

<color name="Bots_backgroundInput">#ffffff</color>

<color name="Bots_btnSendHollow">#c0c0c0</color>
<color name="Bots_btnSendHollowBorder">#303030</color>

<color name="Bots_header">#989898</color>

<color name="Bots_messageDate">@color/Bots_header</color>
<color name="Bots_messageShadow">#7f999999</color>

<color name="Bots_remoteMessageAuthor">@color/Bots_header</color>
<color name="Bots_remoteMessageBackground">#ffffff</color>
<color name="Bots_remoteMessageBorder">#d9d9d9</color>
<color name="Bots_remoteMessageText">#000000</color>

<color name="Bots_userMessageBackground">@color/Bots_accent</color>
<color name="Bots_userMessageBorder">@color/Bots_accentDark</color>
<color name="Bots_userMessageFailedBackground">@color/Bots_accentLight</color>
<color name="Bots_userMessageText">#ffffff</color>
</resources>
If you need to update the image of the Send button, simply add an image with the following name to your drawables:
bots_btn_send_normal.png
You can find the original resources by browsing external libraries through Android Studio.
Permissions
The ODA Client SDK for Android library includes the following permissions by default:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  • WRITE_EXTERNAL_STORAGE is used to take photos and to store downloaded pictures locally to avoid needless re-downloading.

  • ACCESS_FINE_LOCATION is used in order to access the customer’s location when requested using location request buttons.

If you do not intend to request the user’s location at any point, it is safe to remove the ACCESS_FINE_LOCATION using the following override:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" tools:node="remove" />
All other permissions are necessary for ODA to function as intended.
iOS
Add the Client SDK to Your App
  1. Download the ODA Client SDK for iOS module from the Oracle Technology Network’s ODA and OMC download page.

  2. Unzip the file. This creates a directory called Bots.framework (the framework).

  3. Add the framework to your Xcode project by selecting File > Add Files to My_Project and then selecting Bots.framework in the file picker.

  4. In your project settings, add Bots.framework to the list of Embedded Binaries in the General tab for your application target.

    You can now import the framework (#import <Bots/Bots.h>) and start using it in your code.

Import the Bots Header File

Import the Bots file into the your app delegate’s .m file and any other places you plan to use it.

  • Objective-C:
    #import <Bots/Bots.h>
  • Swift:
    import Bots
Add Required Keys in Your App’s info.plist

The Client SDK for iOS may need to ask users permission to use certain features. Depending on the feature, you must provide a description in your app’s Info.plist to explain why access is required. These descriptions will be displayed the moment it prompts the user for permission.

Images

The Client SDK for iOS allows users to send images. To support this feature, you need to provide a description for the following keys:
  • NSCameraUsageDescription—Describes the reason your app accesses the camera (for example: camera permission is required to send images to ${PRODUCT_NAME}). For more information, see the iOS documentation about NSCameraUsageDescription.

  • NSPhotoLibraryUsageDescription—Describes the reason your app accesses the photo library (for example: photo library permission is required to send images to ${PRODUCT_NAME}). For more information, see the iOS documentation about NSPhotoLibraryUsageDescription.

Note:

Beginning with iOS 10, these values are required. If they are not present in your app's Info.plist, the option to send an image will not be displayed.

Location

The Client SDK for iOS also allows users to send their current location. To support this feature, you must provide a description for any of the following keys depending on your app’s use of location services. The SDK will ask the user for the location depending on the key you provide:
  • NSLocationWhenInUseUsageDescription—Describes the reason for your app to access the user’s location information while your app is in use (for example: location services is required to send your current location to ${PRODUCT_NAME}). This permission is recommended if your app does not use location services. The SDK will default to it if both keys are included. See the iOS documentation about NSLocationWhenInUseUsageDescription.

  • NSLocationAlwaysUsageDescription—Describes the reason for your app to access the user’s location information at all times (for example: location services is required to send your current location to ${PRODUCT_NAME}). See the iOS documentation about NSLocationAlwaysUsageDescription.

Note:

If you don't provide one of these keys, any attempt from the user to send their current location will fail.
Initialize the Client SDK in Your App
Before your code can invoke the SDK, you’ll have to initialize the library using the App Id that’s generated for your bot when you add an iOS channel. To get this ID, click Add Channel to open the Create Channel dialog. Add a name for the iOS channel and then choose iOS as the channel type. After you click Create, ODA generates the App Id. Next, use this ID to replace YOUR APP ID in the applicationDidFinishLaunchingWithOptions: method:
  • Objective-C

    [Bots initWithSettings:[OMCSettings settingsWithAppId:@"YOUR_APP_ID"] completionHandler:^(NSError * _Nullable error, NSDictionary * _Nullable userInfo) {
        // Your code after init is complete
    }];
  • Swift:
    Bots.initWith(OMCSettings(appId: "YOUR_APP_ID")) { (error: Error?, userInfo: [AnyHashable : Any]?) in// Your code after init is complete}
You can show the ODA UI anywhere in your app after it finishes loading by adding the following line::
  • Objective-C:
    [Bots show];
  • Swift:
    Bots.show();
Call Other Functions
You can call other functions after the SDK has been initialized successfully. For example, you can update the user's first name, last name, and email address:
// Update first name and last name
   [Bots setUserFirstName:@"John"
           lastName:@"Smith"];

// Update email address
   [OMCUser currentUser].email = @"john.smith@example.com";
Update the SDK
Run the following to update Carthage dependencies:
$ carthage update
Localization of iOS Apps

Every string you see in your bot can be customized and localized. ODA provides a few languages out of the box, but adding new languages is easy to do. When localizing strings,ODA looks for BotsLocalizable.strings in your app bundle first then in theODA bundle, enabling you to customize any strings and add support for other languages.

Enable Localization

For ODA to display a language other than English, your app needs to first enable support for that language. You can enable a second language in your Xcode project settings:
Description of xcode_project_language_settings.png follows
Description of the illustration xcode_project_language_settings.png

Once you have this, ODA will display itself in the device language for the supported language.

These languages are included with the ODA Client SDK for iOS: Arabic, English, Finnish, French, German, Italian, Japanese, Korean, Mandarin Chinese (traditional and simplified), Persian, Portuguese (Brazil and Portugal), Russian, Slovenian, Spanish, and Swedish.

Note:

Localization is subject to caching. If you can't see your changes, cleaning your project, resetting the simulator, deleting your app from your test devices are good measures.
Strings Customization
ODA lets you customize any strings it displays via Apple’s localization mechanism. To override one or more strings, add an empty string file named BotsLocalizable.strings in your Xcode project and specify new values for the keys you would like to override. For example, to change the “Messages” header, and the “Done” button create a file with these contents:
"Messages" = "My Messages"

"Done" = "I'm Done"
To enable string customization across languages, make sure you localize your BotsLocalizable.strings file in Xcode.
Description of ios_localize.png follows
Description of the illustration ios_localize.png

The BotsLocalizable.strings File

Here is the full set of keys:
/* Nav bar button, action sheet cancel button */
"Cancel" = "...";

/* Conversation title */
"Messages" = "...";

/* Conversation header. Uses CFBundleDisplayName */
"This is the start of your conversation with the %@ team. We'll stay in touch to help you get the most out of your app.\nFeel free to leave us a message about anything that’s on your mind. We’ll get back to your questions, suggestions or anything else as soon as we can." = "...";

/* Conversation header when there are previous messages */
"Show more..." = "...";

/* Conversation header when fetching previous messages */
"Retrieving history..." = "...";

/* Error message shown in conversation view */
"No Internet connection" = "...";

/* Error message shown in conversation view */
"Could not connect to server" = "...";

/* Error message shown in conversation view */
"An error occurred while processing your action. Please try again." = "...";

/* Error message shown in conversation view */
"Reconnecting..." = "...";

/* Fallback used by the in app notification when no message author name is found */
"%@ Team" = "...";

/* Conversation send button */
"Send" = "...";

/* Conversation text input place holder */
"Type a message..." = "...";

/* Conversation nav bar left button */
"Done" = "...";

/* Failure text for chat messages that fail to upload */
"Message not delivered. Tap to retry." = "...";

/* Status text for chat messages */
"Sending..." = "...";

/* Status text for sent chat messages */
"Delivered" = "...";

/* Status text for chat messages seen by the appMaker */
"Seen" = "...";

/* Timestamp text for recent messages */
"Just now" = "...";

/* Timestamp text for messages in the last hour */
"%.0fm ago" = "...";

/* Timestamp text for messages in the last day */
"%.0fh ago" = "...";

/* Timestamp text for messages in the last week */
"%.0fd ago" = "...";

/* Action sheet button label */
"Take Photo" = "...";

/* Action sheet button label */
"Use Last Photo Taken" = "...";

/* Action sheet button label */
"Choose from Library" = "...";

/* Photo confirmation alert title */
"Confirm Photo" = "...";

/* Action sheet button label */
"Resend" = "...";

/* Action sheet button label */
"View Image" = "...";

/* Error displayed in message bubble if image failed to download */
"Tap to reload image" = "...";

/* Error displayed as message if location sending fails */
"Could not send location" = "...";

/* Error title when user selects "use latest photo", but no photos exist */
"No Photos Found" = "...";

/* Error description when user selects "use latest photo", but no photos exist */
"Your photo library seems to be empty." = "...";

/* Error title when user attempts to upload a photo but Photos access is denied */
"Can't Access Photos" = "...";

/* Error description when user attempts to upload a photo but Photos access is denied */
"Make sure to allow photos access for this app in your privacy settings." = "...";

/* Error title when user attempts to take a photo but camera access is denied */
"Can't Access Camera" = "...";

/* Error description when user attempts to take a photo but camera access is denied */
"Make sure to allow camera access for this app in your privacy settings." = "...";

/* Generic error title when user attempts to upload an image and it fails for an unknown reason */
"Can't Retrieve Photo" = "...";

/* Generic error description when user attempts to upload an image and it fails for an unknown reason */
"Please try again or select a new photo." = "...";

/* Error title when user attempts to send the current location but location access is denied */
"Can't Access Location" = "...";

/* Error description when user attempts to send the current location but location access is denied */
"Make sure to allow location access for this app in your privacy settings." = "...";

/* UIAlertView button title to link to Settings app */
"Settings" = "...";

/* UIAlertView button title to dismiss */
"Dismiss" = "...";

/* Title for payment button */
"Pay Now" = "...";

/* Title for message action when payment completed */
"Payment Completed" = "...";

/*
 Instructions for entering credit card info. Parameters are as follows:
 1. Amount (e.g. 50.45)
 2. Currency (e.g. USD)
 3. App name (Uses CFBundleDisplayName)
*/
"Enter your credit card to send $%@ %@ securely to %@" = "...";

/* Error text when payment fails */
"An error occurred while processing the card. Please try again or use a different card." = "...";

/* Button label for saved credit card view */
"Change Credit Card" = "...";

/*
 Information label for saved credit card view. Parameters are as follows:
 1. Amount (e.g. 50.45)
 2. Currency (e.g. USD)
 3. App name (Uses CFBundleDisplayName)
 */
"You're about to send $%@ %@ securely to %@" = "...";

/* Title for user notification action */
"Reply" = "...";

/* Date format used for message grouping headers on the conversation screen */
"MMMM d, h:mm a" = "MMMM d, h:mm a";

/* Date format used for message timestamps on the conversation screen */
"hh:mm a" = "hh:mm a";

/* Error message when the content of a webview fails to load */
"Failed to open the page" = "...";
Style the Conversation Interface
The style of the conversation user interface can be controlled through two techniques:
  • Using the UIAppearance proxy of UINavigationBar to style the navigation bar’s color and appearance.

  • The OMCSettings class provides access to the status bar and the color of the message bubbles.

Suppose you wanted the conversation UI to have a black navigation bar and red message bubbles. First, you’d use UINavigationBar's appearance proxy to set up the navigation bar. Then, you’d use OMCSettings to finish styling the UI:
  • Objective C
    OMCSettings* settings = [OMCSettings settingsWithAppId:@"YOUR_APP_ID"];
    settings.conversationAccentColor = [UIColor redColor];
    settings.conversationStatusBarStyle = UIStatusBarStyleLightContent;
    
    [[UINavigationBar appearance] setBarTintColor:[UIColor blackColor]];
    [[UINavigationBar appearance] setTintColor:[UIColor redColor]];
    [[UINavigationBar appearance] setTitleTextAttributes:@{ NSForegroundColorAttributeName : [UIColor redColor] }];
  • Swift
    var settings = OMCSettings(appId: "YOUR_APP_ID");
    settings.conversationAccentColor = UIColor.red();
    settings.conversationStatusBarStyle = UIStatusBarStyle.LightContent
    UINavigationBar.appearance().barTintColor = UIColor.black();
    UINavigationBar.appearance().tintColor = UIColor.red();
    UINavigationBar.appearance().titleTextAttributes = [ NSForegroundColorAttributeName : UIColor.red()];
JavaScript

The ODA Client SDK for JavaScript enables you to embed a bot into any web page. It includes a client library that enables the client to communicate with the chat server that stands in between ODA and the client and manages the channel-specific communications and payloads between the two. The SDK also provides a customizable messaging widget that you can add to any web page where you want to surface your bot.

Typically, you deploy the SDK’s library files to a web server, which also hosts the web page. The basic steps for adding your bot to a web page are:

Tip:

This video describes the chat server-client relationship in further detail and steps you through configuring the files, setting up a server, and embedding the widget.
Configure the Library

The ODA SDK library is composed of multiple assets that get fetched at runtime for better performance. For that reason, the public path (the URL where the static files are hosted) is hardcoded in multiple places.

To configure the library for your environment, run:
./configure 
The script generates a folder with the configured project in it.
Setup Examples

Local Testing Setup

If the static files are hosted at http://localhost:8000/static/ and you run the following script from the /home/your-name/ folder:
./configure http://localhost:8000/static/
then the files will be available at /home/your-name/http:__localhost:8000_static_/.

Production Setup

If the static files are hosted at https://cdn.acme.org/ and you run the following script from the /home/your-name/ folder:
./configure https://cdn.acme.org/
then the files will be available at /home/your-name/https:__cdn.acme.org_/.
Deploy the SDK Files
After you’ve configured the library, you need to deploy the SDK to a web server.
  1. Download the Client SDK for JavaScript module from the Oracle Technology Network’s ODA and OMC download page.

  2. Put all of the files from the generated folder at the root of the storage within https://placeholder.public.path/. For example if your files are hosted at http://localhost:8000/static/, copy all the files to the static folder on your local server.

  3. If your storage is behind a CDN (Content Delivery Network), issue a cache invalidation for https://placeholder.public.path/loader.json.

  4. Make sure your server allows CORS requests.

  5. Test your deployment by initializing the SDK as described in Add the Client SDK to Your Site.

Add the Client SDK to Your Site

You can include the Client SDK for JavaScript by editing the <script> tag. You need an App Id to do this, so if don’t have one already for the Web channel, start off by clicking Add Channel. In the Create Channel dialog, add a name for the channel and then choose Web as the channel type. When you click Create, IODA generates the App Id. You then substitute this value for <app-id> in the code.

Update the Script Tag
  1. Include the Client SDK for JavaScript in your web page by adding the following code towards the end of the head section on your page and replacing <sdk-folder-url> with the URL where the SDK is hosted.
    <script> 
      !function(e,t,n,r){ 
        function s(){
         try{
           var e;
            if((e="string"==typeof this.response?JSON.parse(this.response):this.response).url){
            var n=t.getElementsByTagName("script")[0],r=t.createElement("script");
            r.async=!0,r.src=e.url,n.parentNode.insertBefore(r,n)
          }
         }
         catch(e){}}var o,p,a,i=[],c=[];e[n]={init:function(){o=arguments;
          var e={then:function(t){
            return c.push({type:"t",next:t}),e
            } ,catch:function(t){return c.push({type:"c",next:t}),e}};
            return e},on:function(){
             i.push(arguments)},render:function(){p=arguments},destroy:function(){a=arguments}
            } ,e.__onWebMessengerHostReady__=function(t){
             if(delete e.__onWebMessengerHostReady__,e[n]=t,o)for(var r=t.init.apply(t,o),s=0;s<c.length;s++){
              var u=c[s];
               r="t"===u.type?r.then(u.next):r.catch(u.next)
               } p&&t.render.apply(t,p),a&&t.destroy.apply(t,a);
             for(s=0;s<i.length;s++)t.on.apply(t,i[s])};
             var u=new XMLHttpRequest;u.addEventListener("load",s),u.open("GET",r+"/loader.json",!0),u.responseType="json",u.send() 
            }
         (window,document,"Bots", "<sdk-folder-url>"); 
    </script>
  2. Initialize the Client SDK for JavaScript with your new App ID by adding the following snippet near the end of the body section of your page and replacing <app-id> with your App Id for the Web channel found in your app settings page.
    <script>
        Bots.init({appId:'<app-id>'});
    </script>
Embedded Mode
To embed the widget in your existing markup, you need to pass embedded: true when calling Bots.init. By doing so, you are disabling the auto-rendering mechanism and you will need to call Bots.render manually. This method accepts a DOM element which will be used as the container where the widget will be rendered.
Bots.init({
    appId: '<app-id>',
    embedded: true
});


Bots.render(document.getElementById('chat-container'));

Note:

The embedded widget will take full width and height of the container. You must give it a height, otherwise, the widget will collapse.
Strings Customization

ODA lets you customize any strings it displays by overwriting its keys. To do this, add the customText key in your Bots.init() call and specify new values for the keys shown in the following sample. If any text is within {}, or if there is an HTML tag such as <a>, it needs to remain in the customized text.

For example:
Bots.init({
    appId: <'app-id'>,
    customText: {
        actionPostbackError: 'An error occurred while processing your action. Please try again.',
        clickToRetry: 'Message not delivered. Click to retry.',
        conversationTimestampHeaderFormat: 'MMMM D YYYY, h:mm A',
        fetchHistory: 'Load more',
        fetchingHistory: 'Retrieving history...',
        headerText: 'How can we help?',
        inputPlaceholder: 'Type a message...',
        invalidFileError: 'Only images are supported. Choose a file with a supported extension (jpg, jpeg, png, gif, or bmp).',
        introductionText: 'We\'re here to talk, so ask us anything!',
        locationNotSupported: 'Your browser does not support location services or it’s been disabled. Please type your location instead.',
        locationSecurityRestriction: 'This website cannot access your location. Please type your location instead.',
        locationSendingFailed: 'Could not send location',
        locationServicesDenied: 'This website cannot access your location. Allow access in your settings or type your location instead.',
        messageError: 'An error occurred while sending your message. Please try again.',
        messageIndicatorTitlePlural: '({count}) New messages',
        messageIndicatorTitleSingular: '({count}) New message',
        messageRelativeTimeDay: '{value}d ago',
        messageRelativeTimeHour: '{value}h ago',
        messageRelativeTimeJustNow: 'just now',
        messageRelativeTimeMinute: '{value}m ago',
        messageTimestampFormat: 'hh:mm A',
        messageSending: 'Sending...',
        messageDelivered: 'Delivered',
        sendButtonText: 'Send',
        settingsHeaderText: 'Settings',
        tapToRetry: 'Message not delivered. Tap to retry.',
        unsupportedMessageType: 'Unsupported message type.',
        unsupportedActionType: 'Unsupported action type.'
    }
});
Date Localization
When you translate the user interface by customizing strings, you might also want to show the date and time in the target language as well. To do this, pass locale at initialization time. You might also want to override the timestamp format to match your language.
Bots.init({
    appId: <'app-id'>,
    locale: 'fr-CA',
    customText: {
        // ...
        conversationTimestampHeaderFormat: 'Do MMMM YYYY, hh:mm',
        // ...
    }
});
The locale options is using the language-COUNTRY format. You can find language codes here and country codes here. The country part is optional, and if a country is either not recognized or not supported, it falls back to using the generic language. If the language isn't supported, it will fallback to en-US.

Note:

The locale option only affects date and time localization, not the strings.
Sound Notification

By default, a sound notification will be played when a new message comes in and the window is not in focus.

To disable this feature, you need add the soundNotificationEnabled option to the Bots.init call, like this:
Bots.init({
    appId: <'app-id>',
    soundNotificationEnabled: false // Add this line to your 'Bots.init' call
});
Custom User Interfaces

While the SDK’s widget provides a rich, prebuilt UI, you can create your own using the SDK’s APIs for sending messages and the callback event interface for receiving messages.

To get started, use the following custom UI starter code for a UI that outputs simple text messages. By updating its <body> and <script> elements, you can create a chat widget that can do the following: You can reference this code snippet, which incorporates these functions. At runtime, it looks something like this.

Custom UI Starter Code

You need to update SDK_FOLDER_URL with the URL where the SDK is hosted.

<!DOCTYPE html>
 <html lang="en">
 <head>
   <meta charset="UTF-8">
   <title>Document</title>
 </head>
 <body>
   <script>
     !function(e,t,n,r){
         function s(){try{var e;if((e="string"==typeof this.response?JSON.parse(this.response):this.response).url){var n=t.getElementsByTagName("script")[0],r=t.createElement("script");r.async=!0,r.src=e.url,n.parentNode.insertBefore(r,n)}}catch(e){}}var o,p,a,i=[],c=[];e[n]={init:function(){o=arguments;var e={then:function(t){return c.push({type:"t",next:t}),e},catch:function(t){return c.push({type:"c",next:t}),e}};return e},on:function(){i.push(arguments)},render:function(){p=arguments},destroy:function(){a=arguments}},e.__onWebMessengerHostReady__=function(t){if(delete e.__onWebMessengerHostReady__,e[n]=t,o)for(var r=t.init.apply(t,o),s=0;s<c.length;s++){var u=c[s];r="t"===u.type?r.then(u.next):r.catch(u.next)}p&&t.render.apply(t,p),a&&t.destroy.apply(t,a);for(s=0;s<i.length;s++)t.on.apply(t,i[s])};var u=new XMLHttpRequest;u.addEventListener("load",s),u.open("GET",r+"/loader.json",!0),u.responseType="json",u.send()
     }
(window,document,"Bots", "<SDK_FOLDER_URL>");
 </script>
 </body>
 </html>
Initialize the Client SDK for JavaScript in Embedded Mode
To initialize the SDK but prevent the default UI from displaying:
  1. Create a container that prevents the widget from displaying. In the <body> element, define the <div> tag that hides the default widget.
    <div id="no-display" style="display:none;"></div>
  2. In the <script> element, initialize the Client SDK for JavaScript in embedded mode and render the “no-display” element:
    Bots.init({ appId: appId, embedded: true });
    Bots.render(document.getElementById('no-display'));
Fetch the Initial Data
To determine the initial state of the UI, use the SDK’s Bots.getConversation method. This method provides access to things like the unread message count and the conversation history.
  1. Display the conversation by adding the following tag in the <body>:
    <ul id="conversation"></ul>
  2. Within the <script> tag, define a function that when called, displays a message in the custom UI.
    function displayMessage(message) {
      var conversationElement = document.getElementById('conversation');
      var messageElement = document.createElement('li');
      messageElement.innerText = message.name + ' says "' + message.text + '"';
      conversationElement.appendChild(messageElement);
    }
    
  3. To display the initial conversation state after the initialization of the SDK, replace the Bots.init call with the following:
    Bots.init({ appId: appId, embedded: true }).then(function() {
      // displays initial messages
      var conversation = Bots.getConversation();
      conversation.messages.forEach(displayMessage);
    });
Send Messages
To enable the widget to send messages:
  1. Create a text input element in the <body> that allows the widget to accept plain text messages:
    <input type="text" id="text-input" placeholder="text"
  2. In the <script> tag, add the following element that calls Bots.sendMessage function right after the Bots.init call. When the text input element is active, this function, which enables users to send plain text or structured messages, gets called whenever a user taps Enter:
    var inputElement = document.getElementById('text-input');
     
    inputElement.onkeyup = function(e) {
      if (e.key === 'Enter') {
        Bots.sendMessage(inputElement.value)
          .then(function() {
            inputElement.value = '';
          });
      }
    }
Receive Messages
To update the UI with the new message content, use the SDK’s Bots.on event interface to bind the message:received event (inbound messages) and the message:sent event (outbound messages) to the displayMessage function. To call this function whenever these message events occur, add the following somewhere after the Bots.init call.
Bots.on('message:sent', displayMessage);
Bots.on('message:received', displayMessage);
Add Postback Actions
You can add actions to the bot’s reply message by updating the displayMessage function.
function displayMessage(message) {
    var conversationElement = document.getElementById('conversation');
    var messageElement = document.createElement('li');
    messageElement.innerText = message.name + ' says "' + message.text + '"';
 
    if(message.actions && message.actions.length > 0){
        var wrapperElement = document.createElement('div');
        for(var i = 0; i < message.actions.length; i++){
            var action = message.actions[i];
            var btnElement = createButtonElement(action);
            wrapperElement.appendChild(btnElement);
        }
        messageElement.appendChild(wrapperElement);
    }
    conversationElement.appendChild(messageElement);
}
 
function createButtonElement(action) {
    var btnElement = document.createElement('button');
    var btnTitle = document.createTextNode(action.text);
    btnElement.appendChild(btnTitle);
    btnElement.onclick = function(e){Bots.triggerPostback(action._id);};
    return btnElement;
}
Calling Other Functions
You can call other functions after the SDK has been initialized successfully. For example, you can update a user profile by calling updateUser.
<script>
    Bots.init({ appId: '5b1014820c9940062e39108' })
        .then(function (res){
            Bots.updateUser(
                {
                    "givenName”:"John", 
                    "surname”:"Smith", 
                    "email": “john@example.com", 
                    "properties": { 
                        “botsCustomVariable1”:"beer", 
                        “botsCustomVariable2”:”code”,
                        “botsCustomVariable3”:”repeat"
                    }
                }
            );
        })
        .catch(function (err) {
            console.error(err);
        });
  </script>

Sample Code for the Custom UI
<!DOCTYPE html>
 <html lang="en">
 <head>
   <meta charset="UTF-8">
   <title>Document</title>
 </head>
 <body>
   <div id="no-display" style="display:none;"></div>
   <p>User ID: <span id="user-id"></span></p>
   <ul id="conversation"></ul>
   <input type="text" id="text-input" placeholder="text">

  <script>
        var appId = '<APP_ID>';
     !function(e,t,n,r){
          function s(){try{var e;if((e="string"==typeof this.response?JSON.parse(this.response):this.response).url){var n=t.getElementsByTagName("script")[0],r=t.createElement("script");r.async=!0,r.src=e.url,n.parentNode.insertBefore(r,n)}}catch(e){}}var o,p,a,i=[],c=[];e[n]={init:function(){o=arguments;var e={then:function(t){return c.push({type:"t",next:t}),e},catch:function(t){return c.push({type:"c",next:t}),e}};return e},on:function(){i.push(arguments)},render:function(){p=arguments},destroy:function(){a=arguments}},e.__onWebMessengerHostReady__=function(t){if(delete e.__onWebMessengerHostReady__,e[n]=t,o)for(var r=t.init.apply(t,o),s=0;s<c.length;s++){var u=c[s];r="t"===u.type?r.then(u.next):r.catch(u.next)}p&&t.render.apply(t,p),a&&t.destroy.apply(t,a);for(s=0;s<i.length;s++)t.on.apply(t,i[s])};var u=new XMLHttpRequest;u.addEventListener("load",s),u.open("GET",r+"/loader.json",!0),u.responseType="json",u.send()
     }
(window,document,"Bots", "<SDK_FOLDER_URL>");

  inputElement.onkeyup = function(e) {
  if (e.key === 'Enter') {
  Bots.sendMessage(inputElement.value)
  .then(function() {
  inputElement.value = '';
  });
  }
  }
  // display new messages
  Bots.on('message:sent', displayMessage);
  Bots.on('message:received', displayMessage);

  // initialize Bots and render the UI in a hidden element
  Bots.init({ appId: appId, embedded: true })
  .then(function () {

  // displays initial messages
  var conversation = Bots.getConversation();
  conversation.messages.forEach(displayMessage);

  Bots.render(document.getElementById('no-display'));

  function displayMessage(message) {
  var conversationElement = document.getElementById('conversation');
  var messageElement = document.createElement('li');
  messageElement.innerText = message.name + ' says "' + message.text + '"';
  conversationElement.appendChild(messageElement);
  }
    </script>
 </body>
 </html>
Message Types
Text Message

A text type message is sent with text and/or actions.

{
    /**
     * The text content of the message. Optional only if actions are provided.
     */
    text?: string,
    /**
     * Message type
     */
    type: 'text',
    /**
     * Message role can be 'appUser' or 'appMaker'
     * Added by SDK when send through the sendMessage method
     */
    role?: 'appMaker',
    /**
     * Array of action buttons.
     */
    actions?: MessageAction[],
    /**
     * Url to the avatar for this message sender
     */
    avatarUrl?: string
}
Carousel Message

Carousel messages are a horizontally scrollable set of items, each of which can contain combinations of text, images, and action buttons.

{
    /**
     * Message type
     */
    type: 'carousel',
    /**
     * Message role can be 'appUser' or 'appMaker'
     * Added by SDK when send through the sendMessage method
     */
    role?: 'appMaker',
    /**
     * Url to the avatar for this message sender
     */
    avatarUrl?: string,
    /**
    * Array of message items. The array is limited to 10 items.
    */
    items: Item[],
    /**
    * Settings to adjust the carousel layout.
    */
    displaySettings?: {
        imageAspectRatio: 'horizontal' | 'square'
    }
}
Image Message
An image type message is a message that is sent with an image, and, optionally, text and/or actions.
{
    /**
     * Message type
     */
    type: 'image',
    /**
     * Message role can be 'appUser' or 'appMaker'
     * Added by SDK when send through the sendMessage method
     */
    role?: 'appMaker',
    /**
     * Url to the avatar for this message sender
     */
    avatarUrl?: string,
    /**
    * The text content of the message. Optional only if actions are provided.
    */
    text?: string,
    /**
    * The media type is defined here, for example image/jpeg. If mediaType is not specified, the media type will be resolved with the mediaUrl.
    */
    mediaType?: string;
    /**
    * The image URL used for the image message.
    */
    mediaUrl: string;
    /**
    * Array of action buttons.
    */
    actions?: MessageAction[]
}
File Message
A file type message is a message that is sent with a file attachment.
{
    /**
     * Message type
     */
    type: 'file',
    /**
     * Message role can be 'appUser' or 'appMaker'
     * Added by SDK when send through the sendMessage method
     */
    role?: 'appMaker',
    /**
     * Url to the avatar for this message sender
     */
    avatarUrl?: string,
    /**
    * The text content of the message. Optional only if actions are provided.
    */
    text?: string,
    /**
    * The media type is defined here, for example application/pdf. If mediaType is not specified, the media type will be resolved with the mediaUrl.
    */
    mediaType?: string;
    /**
    * The URL of the file attachment.
    */
    mediaUrl: string;
}
Location Message
A location type message includes the location coordinates (latitude and longitude). Typically, these messages are sent in response to a location request.
{
    /**
     * Message type
     */
    type: 'location',
    /**
     * Message role can be 'appUser' or 'appMaker'
     * Added by SDK when send through the sendMessage method
     */
    role?: 'appMaker',
    /**
     * Url to the avatar for this message sender
     */
    avatarUrl?: string,
    /**
    * The coordinates of the location.
    */
    coordinates?: {
        /**
        * A floating point value representing the latitude of the location
        */
        lat: number,
        /**
        * A floating point value representing the longitude of the location
        */
        long: number
    }
}
Message Actions
Postback Action
A postback action posts the action payload when tapped.
{
    _id: string,
    /**
     * The button text.
     */
    text: string,
    /**
     * Type of the action
     */
    type: 'postback',
    /**
     * Value indicating whether the action is the default action for a message item.
     */
    default: boolean,
    /**
     * Flat object containing any custom properties associated with the action.
     */
    metadata?: any,
    /**
    * A string payload to help you identify the action context. You can also use metadata for more complex needs.
    */
    payload: string
} 
Link Action
A link action opens the provided URI when tapped.
{
    /**
     * The button text.
     */
    text: string,
    /**
     * Type of the action
     */
    type: 'link',
    /**
     * Value indicating whether the action is the default action for a message item.
     */
    default: boolean,
    /**
     * Flat object containing any custom properties associated with the action.
     */
    metadata?: any,
    /**
    * The action URI. This is the link that will be used in the clients when clicking the button.
    */
    uri: string
    /**
    * Extra options to pass directly to the channel API.
    */
    extraChannelOptions?: any
} 
Location Request Action
A location request action prompts users to share their location.
{
    /**
     * The button text.
     */
    text: string,
    /**
     * Type of the action
     */
    type: 'locationRequest',
    /**
     * Value indicating whether the action is the default action for a message item.
     */
    default: boolean,
    /**
     * Flat object containing any custom properties associated with the action.
     */
    metadata?: any,
} 
Reply Action
A reply action echoes the user’s choice as a message.

Tip:

You can also specify an iconURL which renders as an icon for each option.
{
    /**
     * The button text.
     */
    text: string,
    /**
     * Type of the action
     */
    type: 'reply',
    /**
     * Value indicating whether the action is the default action for a message item.
     */
    default: boolean,
    /**
     * Flat object containing any custom properties associated with the action.
     */
    metadata?: any,
    /**
    * A string payload to help you identify the action context. Used when posting the reply. You can also use metadata for more complex needs.
    */
    payload: string,
    /**
    * An icon to render next to the reply option
    */
    iconUrl?: string
} 
Webview Action
When a user taps or clicks a webview action, the URL is loaded in the webview.
{
    /**
     * The button text.
     */
    text: string,
    /**
     * Type of the action
     */
    type: 'webview',
    /**
     * Value indicating whether the action is the default action for a message item.
     */
    default: boolean,
    /**
     * Flat object containing any custom properties associated with the action.
     */
    metadata?: any,
    /**
    * The webview URI. This is the URI that will open in the webview when clicking the button.
    */
    uri: string,
    /**
    * The webview fallback URI. This is the link that will be opened when not support webviews.
    */
    fallback: string,
    /**
    * Controls the webview height.
    */
    size?: 'compact' | 'tall' | 'full',
    /**
    * Extra options to pass directly to the channel API.
    */
    extraChannelOptions?: any
} 
Share Action
A share button.
{
    /**
     * The button text.
     */
    text: string,
    /**
     * Type of the action
     */
    type: 'share',
    /**
     * Value indicating whether the action is the default action for a message item.
     */
    default: boolean,
    /**
     * Flat object containing any custom properties associated with the action.
     */
    metadata?: any
} 
Message Item
{
    /**
     * The image URL to be shown in the carousel/list item.
     */
    mediaUrl?: string,
    /**
     * The text description, or subtitle.
     */
    description?: string,
    /**
     * The title of the carousel item.
     */
    title: string,
    /**
     * If a mediaUrl was specified, the media type is defined here, for example image/jpeg. If mediaType is not specified, the media type will be resolved with the mediaUrl.
     */
    mediaType: string,
    /**
     * Array of action buttons. At least 1 is required, a maximum of 3 are allowed. link and postback and share actions are supported.
     */
    actions: IBotsSDKMessageAction[],
    /**
     * The size of the image to be shown in the carousel/list item
     */
    size: 'compact' | 'large'
}
Display Style Options
You can style the UI by adding these options after Bots.init.
Option Description Default Value Required
displayStyle

How the messenger widget appears on your website. This is defined as either a button or tab. You can style the button’s size and icon:

  • buttonIconUrl

  • buttonWidth

  • buttonHeight

For example:
Bots.init({ appId: appId, embedded: true });
    // ...

displayStyle: "button",
buttonIconUrl: https://myimage.png,
buttonWidth: '90',
buttonHeight: '90'
...
}).then(function() {
    // Your code after init is complete
});
button No
buttonIconUrl

The URL that points to the button icon. The icon image must be:

  • At least 200 x 200 pixels

  • JPG, PNG, or GIF format

  No
buttonWidth The button width, in pixels. 8px No
buttonHeight The button height, in pixels. 58px No
businessName The business name. For example: businessName: “Oracle”   No
businessIconUrl

The URL that points to the business’ icon image. This image must be:

  • At least 200 x 200 pixels

  • JPG, PNG, or GIF format

For example:
Bots.init({ appId: appId, embedded: true });
    //...
    businessName: "Acme Corporation",
    businessIconUrl: "https://example.com/image/thumb/thatimage.jpg/1200x630bb.jpg"
    //...
}).then(function() {
    // Your code after init is complete
});
  No
backgroundImageUrl

The URL that points to the image that appears in the background of the conversation. This image is tiled to fit the chat window.

For example:
Bots.init({ appId: appId, embedded: true });
    // ...
    backgroundImageUrl: "https://a-nice-texture.png"
    // ...
}).then(function() {
    // Your code after init is complete
});

  No
integrationOrder

An array of integration IDs. When set, only integrations from this list will be displayed. If the array is empty, then , no integrations will be displayed.

Note: Listing an integration in the array doesn't guarantee that it will be displayed in the widget.

  No
customColors

The colors used in the Web Messenger UI.

The three-to-six character hexadecimal colors used for the brandColor, conversationColor, and actionColor options. No
brandColor The color used in the messenger header and for the button or tab in idle state 65758e No
conversationColor This color used for customer messages, quick replies and actions in the footer. 0099ff No
actionColor

The color used to change the appears of selected actions inside your messages, like tapped buttons or links.

This color is also used for the Send button when it is in active state.

0099ff No

Text-Only Channels

Like the Facebook channel, you configure text-only channels using artifacts generated by both the messaging platform and ODA. For text-only channels like Twilio/SMS and WeChat, however, you also need to update the dialog flow definition to allow your bot’s responses to render appropriately when buttons aren’t supported. There are two aspects of this:
  • Showing or hiding content for text-only channels. For the System.CommonResponse component, this means that you need to update the metatdata property to include (or where applicable, exclude) Twilio or WeChat for any response item, card, or global action:
    channelTest:
      component: "System.CommonResponse"
      properties:
        processUserMessage: false
        metadata:
          responseItems:
          - type: "text"
            text: "This text text displays on Twilio"
            visible:
              channels:
                include: "twilio"             
          - type: "text"
            text: "This text is not shown in Twilio or Facebook!"
            visible:
              channels:
                exclude: "facebook, twilio"
            actions:
            - label: "This action is only shown on web channel."
              type: "postback"
              payload:
                action: "someAction"
              visible:
                channels:
                  include: "web"
  • Configuring auto-numbering.

How Do I Configure a Twilio/SMS Channel?
You’ll need the following to run your bot on Twilio/SMS:
  • Twilio Credentials (you provide these to the ODA channel configuration):
    • A Twilio phone number.

    • Account SID

    • Auth Token

  • From ODA (and provided to Twilio):

    • The webhook URL (generated when you create the Twilio channel).

Step 1: Get an SMS-Enabled Twilo Number
To generate the Twilio Number, Account SID, Auth Token needed for the Twilio channel configuration, you first need to create a Twilio account (if you don’t have one already).After you’ve verified your identity:
  1. Click All Products and Services (This is an image of the All Products and Services icon.) in the left navbar.

  2. Pin both Programmable SMS (This is an image of the Programmable SMS icon.) and Phone Numbers (This is an image of the Phone Numbers icon.) to your dashboard.
    Description of twilio_products.png follows
    Description of the illustration twilio_products.png

  3. Click Phone Numbers (now pinned to the left navbar) and then click Get Started.

  4. Choose Get a Number or Buy a Number. In either case, be sure to select the SMS capability. . Keep this number close at hand, because you’ll use this number to configure the Twilio channel back in ODA.

  5. Click Console Dashboard (This is an image of the dashboard icon.) in the left navbar and note the Account SID and Auth Token (accessed by clicking View). Along with the Twilio number, you need these credentials to configure the Twilio Channel.

Step 2: Link Your Bot to the Twilio Number
With the Twilio credentials close at hand:
  1. Back in ODA, click Channels in the left menu and then choose Users.

  2. Click Add Channel.

  3. In the Create Channel dialog:
    • Enter a name and then choose Twilio SMS from the Channel Type menu.

    • Enter the Account SID, Auth Token and Twilio Number.

    Switch on Channel Enabled.
  4. Click Create. Note the Webhook URL. You’ll need this for one last stop to the Twilio Console.

  5. In the Twilio Console, click Phone Numbers (This is an image of the Phone Numbers icon.) then click Active Numbers.

  6. Click the Twilio number in the Active Numbers page.

  7. In the Messaging Section of the Configure page, paste the Webhook URL into the A Message Comes In field.

  8. Click Save.

Testing Tips

You can test the Twilio Channel using your own phone by sending messages to the ODA Twilio account number.

How Do I Conifgure a WeChat Channel?
To configure a WeChat channel, you need:
  • An App ID from WeChat—You provide this to ODA. To get an App ID, you need:
    • A WeChat Official Account or an International Official Account (WeChat OA) for bots used in China.

    • The account type must be a Service Account.

  • Credentials required by both WeChat and ODA:

    • An App Secret

    • An Access Token—This token is valid for 7200 seconds.

  • Credentials Provided to WeChat from ODA:
    • The webhook URL generated by ODA.

Step 1: Configure the WeChat Channel in ODA
  1. First, get the App ID WeChat. You can find it by clicking Basic Configuration (located in the Developer section in the left navbar of the WeChat Official Account Admin Platform). Copy the App ID.

  2. In ODA, click Channels in the left menu, then choose Users.

  3. Click Add Channel.

  4. In the Create Channel dialog:
    • Enter a name and then choose WeChat from the Channel Type menu.

    • Enter the App ID from WeChat, the App Secret and the token.

    Switch on Channel Enabled.
  5. Click Create.

  6. Copy the generated Webhook URL.

Step 2: Link the Bot to the WeChat Account
  1. In the Basic Configuration section of the WeChat Official Account Admin Platform, paste in the App Secret.

  2. Go to the Server Settings section and then click Edit.

  3. Paste in the Webhook URL generated by ODA in the URL field.and then click Submit.

  4. Paste the token in the Token field.

    Important:

    The values for the App Secret and token must match the ones you entered in the ODA’s WeChat configuration dialog.
  5. Click Submit and then click Enable.