Chatbot Integration

Chatbot Integration

Champion Chatbot Integration allows a developer to Embed the Champion Chatbot into a Client Application.

Table of Contents

Steps

  1. Client Credentials Token Exchange with Champion

    1. Create an application through The Champion Web Experience Portal to obtain your Client ID and Client Secret
  2. Embed Champion TypeScript within your Web Application

    1. Include TypeScript and Initialize

    2. Include champion.ai domain in your Content Security Policy headers:

      • 'unsafe-eval' *.champion.ai;
      • frame-src *.champion.ai
    3. Retrieve Client User Token:

      1. Have your Client Web Application call your Client API Above
      2. Client API should call Champion API to retrieve Client User Token - OpenAPI Specification
      3. Return Client User Token to your Client Web Application
    4. Initialize Champion with Client User Token

Sequence Diagram

This diagram demonstrates how a user would initialize the Champion Chatbot into a Client Application for Generative Use Cases

Code Examples

Below is some example code that may help you with your integration.

Champion OpenAPI Specification

openapi: 3.0.0
info:
  title: Champion Auth
  version: "1.0.0"
  description: >
    The APIs handling the client credentials flow for issuing champion-client tokens to be used for accessing champion endpoints.
servers:
  - url: https://api.champion.ai/champion/api
paths:
  /oauth/token:
    post:
      summary: Generate Champion Client JWT
      description: Creates a champion client JWT on behalf of the provided client user.
      operationId: generate-oauth-token
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TokenRequest'
      responses:
        '200':
          $ref: '#/components/responses/TokenResponse'
        '400':
          $ref: '#/components/responses/BadRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '403':
          $ref: '#/components/responses/ForbiddenError'
        '404':
          $ref: '#/components/responses/NotFoundError'
        '405':
          $ref: '#/components/responses/MethodNotAllowedError'
        '429':
          $ref: '#/components/responses/TooManyRequestsError'
        '500':
          $ref: '#/components/responses/InternalServerError'
        '501':
          $ref: '#/components/responses/NotImplementedError'
        '502':
          $ref: '#/components/responses/BadGatewayError'
        '503':
          $ref: '#/components/responses/ServiceUnavailableError'
components:
  schemas:
    TokenRequest:
      type: object
      description: >
        Request payload for generating a JWT.
        Includes **userId** for the client application's user identifier,
        along with **clientId** and **clientSecret** for authentication.
      properties:
        userId:
          type: string
          description: The client application's user identifier.
        clientId:
          type: string
          description: The client identifier for authentication.
        clientSecret:
          type: string
          description: The client secret for authentication.
      required:
        - userId
        - clientId
        - clientSecret
    TokenResponse:
      type: object
      description: Response payload containing the issued JWT and token details.
      properties:
        access_token:
          type: string
          description: The JWT issued by the champion-server.
        scope:
          type: string
          description: Scopes granted in the token.
        expires_in:
          type: integer
          description: Lifetime in seconds of the JWT.
        token_type:
          type: string
          description: The type of the token (typically "Bearer").
      required:
        - access_token
        - scope
        - expires_in
        - token_type
    ErrorResponse:
      type: object
      description: Standard error response providing details about the error.
      properties:
        error:
          type: string
          description: Error code indicating the type of error.
        error_description:
          type: string
          description: A detailed description of the error.
      required:
        - error
        - error_description
  responses:
    TokenResponse:
      description: >
        Successful operation. The champion client JWT is generated and returned along with token details such as scope, expiry, and token type.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/TokenResponse'
    BadRequestError:
      description: >
        Bad Request. The request payload is missing required parameters or contains invalid data.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    UnauthorizedError:
      description: >
        Unauthorized. Client authentication failed due to invalid credentials.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    ForbiddenError:
      description: >
        Forbidden. The client does not have sufficient privileges to perform this operation.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    NotFoundError:
      description: >
        Not Found. The requested resource or endpoint could not be located.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    MethodNotAllowedError:
      description: >
        Method Not Allowed. The HTTP method used is not supported by this endpoint.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    TooManyRequestsError:
      description: >
        Too Many Requests. The client has sent too many requests in a given amount of time.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    InternalServerError:
      description: >
        Internal Server Error. An unexpected error occurred on the server.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    NotImplementedError:
      description: >
        Not Implemented. The requested functionality is not supported by the server.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    BadGatewayError:
      description: >
        Bad Gateway. The server received an invalid response from an upstream server.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    ServiceUnavailableError:
      description: >
        Service Unavailable. The server is currently unable to handle the request due to temporary overloading or maintenance.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'

Champion TypeScript Example

The below is a code example of how Champion may be included w/in your Application.

  • championLoadJWT (Required) - This method needs to return a championJWT. Typically this method will call an API endpoint of the client application API that implement a client Credentials Token Exchange with Champion Server.

  • championGetContext (Required) - This method allow the host to provide some context to champion, the context is divided into two objects:

    • uiConfig - which is the configuration needed for champion webapp to display properly
    • organizationId - which is the id to represent the current organization
    • hostContext (Optional) - which is the context to pass to the agent
  • championNeedSupport (Optional) - This method will be called when the user click on the support button (enabled in the host context).

  • championNeedAction (Optional) - This method will be called when the user click on a recommended actions

  • championPosition (Optional) - This method is called if fabLocation.custom is selected, to allow the host to provide a custom position to Champion webapp.

Code Example:

export {} //To treat this file as a module
export interface ChampionContext {
  uiConfig: {
    id: string
    name: string
    fabLocation: string
    showFabIcon?: boolean
    enableSupport: boolean
    colorScheme?: string
    lang?: string
  }
  organizationId: string
  tenantId?: string // legacy for ERP
  hostContext: Record<string, string>
}

declare global {
  interface Window {
    championLoadJWT: () => Promise<string>
    championGetContext: () => ChampionContext
    championNeedSupport: () => void
    championNeedAction: (type: ChampionActionType, payload: any) => void
    championContextChanged: () => void
    championOpen: () => void
    championClose: () => void
    championReset: () => void
    championGetUrl: () => string
    championPosition: (iframe: any) => void
    championInitialMessage: (message: string) => void
  }
}
enum FabLocation {
  BOTTOM_RIGHT = 'bottom-right',
  BOTTOM_LEFT = 'bottom-left',
  TOP_RIGHT = 'top-right',
  TOP_LEFT = 'top-left',
  CUSTOM = 'custom'
}

enum ColorScheme {
  RED = 'red',
  BLUE = 'blue'
}

const createChatbot = () => {
  const loadChatbotScript = () => {
    const script = document.createElement('script')
    const url = `${window.championGetUrl()}/main-qad-champion.js`
    script.src = url
    script.type = 'text/javascript'
    script.async = true
    script.onload = () => console.log(`Successfully loaded script: ${url}`)
    script.onerror = () => console.error(`Failed to load script: ${url}`)
    document.head.appendChild(script)
  }
  document.addEventListener('DOMContentLoaded', loadChatbotScript)
}
const config = {
  local: {
    championUrl: 'http://localhost:3001'
  },
  dev: {
    championUrl: 'https://app-lab.champion.ai/champion/app'
  },
  staging: {
    championUrl: 'https://app-prep.champion.ai/champion/app'
  },
  prod: {
    championUrl: 'https://app.champion.ai/champion/app'
  }
}

const getCurrentConfig = () => {
  //change the return value to the desired environment
  return config.local
}
window.championGetUrl = () => {
  return getCurrentConfig().championUrl
}
window.championLoadJWT = async () => {
  // Call Your API to Exchange for Champion JWT
}
window.championGetContext = (): ChampionContext => {
  const uiConfig = {
    id: '', //Define your host id redzone or pi or erp ...
    name: '', //Define the name you want to display on champion window
    fabLocation: FabLocation.TOP_LEFT,
    showFabIcon: true, // Whether or not to show the built in FAB icon to show Champion (default to true if not set)
    enableSupport: true,
    colorScheme: ColorScheme.RED // Red or blue or nothing which will default to red
    lang: 'en' // or 'fr' or 'de' can be based on your locale e.g i18n.global.locale.value
  }
  const tenantId = //use to provide a tenantId to champion e.g an organizationId
  const hostContext = {
    //Some context to help the agent
    userId : current_user_id //useful to force champion to fetch a new token automatically on user change
  }
  return { uiConfig, tenantId, hostContext}
}
/*
  Call when the user click on the support icon of champion
  To implement if you want some support logic in your webapp
  (opening intercom for instance)
*/
window.championNeedSupport = () => {
  window.championClose()
  //To implement
}

enum ChampionActionType {
  NAVIGATION = 'NAVIGATION',
  //...
}

//To implement if champion needs to interact with the client application
window.championNeedAction = (type: ChampionActionType, payload: any) => {
  if (type === ChampionActionType.NAVIGATION) {
    router.push('/player' + payload.url)
  }
  // ...
}

//To implement if fabLocation.custom
window.championPosition = (iframe: any) => {
  if (!iframe) return
  iframe.style.top = '70px'
  iframe.style.left = '70px'
}

//The plugin creation
const ChampionAI = {
  install() {
    createChatbot()
  }
}
export { ChampionAI }

Champion Init Plugin

At the bottom of champion's initialization code a plugin named ChampionAI is defined, you can then install it in your application. This involves calling the install method of the plugin.

Code Example:

// Import the ChampionAI plugin
import { ChampionAI } from './path-to-champion-init-code';

// Example of integrating the plugin into an application
function integratePlugin(app) {
  ChampionAI.install();
}

// Example application context
const app = {}; // This could be your application instance or context

integratePlugin(app);

Managing Context Updates

Changes in the client web application's context, like a user moving to another tenant, switching lang or logging out, necessitate a refresh of Champion's context. To handle these situations, the window.championContextChanged() JavaScript method is available globally. Invoking this method prompts Champion to re-execute the window.championGetContext() method from your initialization script. With the updated context, Champion can then refresh and present the appropriate messages.

Important Considerations:

  • Champion will only be visible if both the Champion context and the organizationId within that context are defined.
  • Champion will fetch a new Champion JWT token if it detects that the organizationId or the hostContext has changed
  • You can manually refresh Champion's JWT token and clear the current conversation history by calling the window.championReset() method.

FAB(less) Installation

By default when you integrate the Champion Chatbot there is a built in FAB icon that you can click to open the chatbot. However if you want to implement your own method of opening the chatbot you can do so by supplying showFabIcon: false as a configuration option.

If you choose to go for this approach you can then use the window.championOpen() and window.championClose() methods to open and close the chatbot.

User Onboarding - Manage Initial Message

By default the Champion Chatbot will have a welcome message to great the user. However you can implement your own greeting by using the window.championInitialMessage(message: string) method and pass the chosen greeting as an argument.

Window Dimensions

The Champion Chatbot has a default height and width but depending on your screen size these defaults might not be ideal. However fear not because the chatbot has a way for the host application to provide window dimensions to it.

Below is an example implementation:

window.championGetWindowDimensions = () => {
    return {
        width: window.innerWidth,
        height: window.innerHeight,
    };
};

// on window resize call window.championResize
window.addEventListener('resize', () => {
    if (typeof window.championResize === 'function') {
        window.championResize({
            width: window.innerWidth,
            height: window.innerHeight,
        });
    }
});