Web SDK 安装指南

本页面介绍了如何安装和使用 Contact Center AI 平台 (CCAI 平台) Web SDK。为了帮助您入门,Google 建议您下载并使用我们的 Web SDK 版本 2 示例文件

准备工作

  1. 在 Web 客户端中包含 CCAI 平台 Web SDK 加载程序。

    <script src="https://websdk.ujet.co/v2/loader.js"></script>
    
  2. 使用 COMPANY_KEY 初始化 CCAI 平台 Web SDK。

  3. 使用后端代码通过 COMPANY_SECRET 初始化身份验证。

安装工作流

安装工作流

开始使用

以下部分提供了有关如何开始使用 CCAI 平台 Web SDK 的信息。

初始化 Web SDK

您可以使用公司密钥初始化 Web SDK。

获取公司密钥

如需获取公司密钥,请按以下步骤操作:

  1. 使用管理员凭据登录 CCAI Platform 门户。

  2. 依次点击 菜单设置 > 开发者设置

  3. 前往公司密钥和密钥代码窗格,然后将代码保存在公司密钥字段中。

然后,您可以使用 UJET(config) 方法和 ujet.on('created', function) 事件初始化 Web SDK。提供 CCAI 平台实例主机,例如 myccaip.uc1.ccaiplatform.com。

// INITIALIZE WEB SDK
var ujet = new UJET({
  companyId: "YOUR_COMPANY_ID",
  host: "https://myccaip.uc1.ccaiplatform.com",
});

ujet.on('created', function () {
  ujet.authenticate(getAuthToken);
});

或者,您也可以使用不含已创建事件的身份验证选项:

var ujet = new UJET({
  companyId: "YOUR_COMPANY_ID",
  authenticate: getAuthToken,
  host: "https://myccaip.uc1.ccaiplatform.com",
});

其中,getAuthToken() 是一个函数,用于调用后端中的 JWT 签名机制:

function getAuthToken() {
  // YOU SHOULD HAVE THIS KIND OF API ON YOUR SERVER
  return fetch('/auth/token')
    .then(function(resp) {
      // { token: '....' }
      return resp.json();
    });
}

其中,fetch() 调用了后端中的 JWT 签名机制。如需了解详情,请参阅 Mozilla Fetch API

为共同浏览配置 Web SDK

共同浏览是一项可选功能,可让客服人员查看最终用户的屏幕,并可选择性地控制该屏幕。如需使用共同浏览,您需要在 SDK 初始化期间提供 CCAI Platform 实例的共同浏览网域和许可密钥。

如需为共同浏览配置 Web SDK,请按以下步骤操作:

  1. 如需获取 CCAI Platform 实例的共同浏览网域和许可密钥,请执行以下操作:

    1. 使用管理员凭据登录 CCAI Platform 门户。

    2. 依次点击 菜单设置 > 开发者设置

    3. 前往共同浏览窗格,然后点击切换开关以将其切换到开启位置。

    4. 保存共同浏览网域许可密钥字段中的值。

  2. 如需在 SDK 初始化期间提供共同浏览网域和许可密钥,请在初始化 Web SDK 时添加以下代码:

    var ujet = new UJET({
      // other options
      cobrowseOptions: {
        license: "LICENSE_KEY",
        trustedOrigins: ["CO-BROWSE_DOMAIN"],
        api: "CO-BROWSE_DOMAIN"
      },
      // other options
    })
    

    替换以下内容:

    • LICENSE_KEY:您在上一步中保存的许可密钥

    • CO-BROWSE_DOMAIN:您在上一步中保存的共同浏览网域

如需了解详情,请参阅设置共同浏览

使用公司密钥初始化身份验证

函数 getAuthToken() 应调用您的 API 并使用 COMPANY_SECRET 对载荷进行编码。

以下是使用 ExpressJS 进行 JWT 签名的示例:

const express = require('express')
const jwt = require('jsonwebtoken')

const port = process.env.PORT || 3000
const secret = process.env.COMPANY_SECRET || 'secret'

const app = express()

app.use(express.json())

app.post('/auth/token', function (req, res) {
  const payload = {}
  payload['iss'] = 'YOUR_COMPANY_NAME'
  const iat = parseInt(Date.now() / 1000, 10)
  payload['iat'] = iat
  payload['exp'] = iat + 600
  const token = jwt.sign(payload, secret, { algorithm: 'HS256' })
  res.json({ token })
})

app.listen(port, function () {
  console.log(`Listing at http://localhost:${port}`)
})

您可以使用任何后端服务。

内容安全政策

如果您的生产服务器具有内容安全政策,请将 https://websdk.ujet.co/ 添加到 script-srcframe-src 中。

支持 Internet Explorer 11

为了支持 Internet Explorer,我们的代码中使用了 babel-polyfill。如果您的网站也使用 babel-polyfill,请勿将其导入到 Web SDK,因为在全局范围内和在 Web SDK 中使用同一库可能会导致异常。在导入软件包之前,我们建议您添加代码来检查并防止出现此问题。

跟踪用户

上一个示例不会跟踪用户。如果您想在 CRM 中识别回头客,并使用包含用户信息的预设回答,则必须为用户添加标识符。

为此,您必须在以下位置添加标识符:

  1. getAuthToken() 中传递到后端

    function getAuthToken() {
      // YOU SHOULD HAVE THIS KIND OF API ON YOUR SERVER
      return fetch('/auth/token', {
        headers: {
          'Content-Type': 'application/json'
        },
        method: "POST",
        body: JSON.stringify({
          payload: {
            identifier: 'c727f2851b64b29761da170d0adee67a9a89c2d9960c8eee0ae53737413cfa4e',
            name: 'Test user',
            email: 'test@user.com',
            phone: '1800UJETSDK'
          }
        })
      }).then(function(resp) {
        return resp.json();
      });
    }
    
  2. 在对 JWT 进行编码时添加到载荷

    const express = require('express')
    const jwt = require('jsonwebtoken')
    
    const port = process.env.PORT || 3000
    const secret = process.env.COMPANY_SECRET || 'secret'
    
    const app = express()
    
    app.use(express.json())
    
    app.post('/auth/token', function (req, res) {
      const payload = req.body.payload
      payload['iss'] = 'YOUR_COMPANY_NAME'
      const iat = parseInt(Date.now() / 1000, 10)
      payload['iat'] = iat
      payload['exp'] = iat + 600
      const token = jwt.sign(payload, secret, { algorithm: 'HS256' })
      res.json({ token })
    })
    
    app.listen(port, function () {
      console.log(`Listing at http://localhost:${port}`)
    })
    
  3. authentication() 中添加更多选项

    new UJET({
      // ...
      authenticate: function() {
        return getAuthToken().then({ token } => {
          return {
            token: token,
            user: {
              identifier: YOUR_UNIQUE_USER_ID,
              name: 'Test user' //optional,
              email: 'test@user.com', //optional,
              phone: '000000000' //optional
            }
          };
        });
      },
    })
    

外部聊天机器人转移

当您将对话从虚拟客服转接到人工客服时,可以通过将 external_chat_transfer 字段回填到自定义数据来替换问候消息并将对话记录传递给人工客服。greeting_override 支持 Markdown 格式。

{
  "external_chat_transfer": {
    "greeting_override": "Please hold while we connect you with a human agent.",
    "agent": {
      "name": "Agent Name",
      "avatar": "https://ujet.s3.amazonaws.com/default-virtual-agent-avatar-1.png"
    },
    "transcript": [
      {
        "sender": "agent",
        "timestamp": "2021-03-15 12:00:00Z",
        "content": [
          {
            "type": "text",
            "text": "Hello! How can I help you today?"
          },
          {
            "type": "buttons",
            "buttons": [
              {
                "label": "Create New Order",
                "selected": false
              },
              {
                "label": "Check Order Status",
                "selected": true
              },
              {
                "label": "Check Account Balance",
                "selected": false
              }
            ]
          }
        ]
      },
      {
        "sender": "end_user",
        "timestamp": "2021-03-15 12:00:15Z",
        "content": [
          {
            "type": "txt",
            "text": "Ceck Order Status"
          }
        ]
      },
      {
        "sender": "aget",
        "timestamp": "021-03-15 12:00:16Z",
        "content": [
          {
            "type": "txt",
            "text": "Ican help you with that, what's your order number?"
          }
        ]
      },
      {
        "sender": "enduser",
        "timestamp": "021-03-15 12:00:20Z",
        "content": [
          {
            "type": "mdia",
            "media": {
              "type": image",
              "url": "https://ujet.s3.amazonaws.com/default-virtual-agent-avatar-1.png"
            }
          }
        ]
      }
    ]
  }
}

Chat 未签名自定义数据

开始聊天时,您可以通过聊天对象传递自定义数据。自定义数据可以是操作系统、版本号、位置,也可以是可能与对话相关的任何其他数据。此数据未加密,因此不应包含个人身份信息 (PII)。

您还可以将这些自定义数据传递到虚拟客服中。如需了解详情,请参阅虚拟代理

var ujet = new UJET({
  // other parameters
  customData: {
    version: {
      label: 'Version',
      value: '1.1.0'
    },
    platform: {
      label: 'Platform',
      value: navigator.platform
    }
  },
});

自定义数据格式与 JSON 类似。每个数据字段都包含一个键、一个标签和一个值。示例如下:

{
  "k1": {
    "label": "Version",
    "value": "1.2.3"
  },
  "k2": {
    "label": "Dashboard",
    "value": "http://example.com"
  }
}

在此示例中,k1k2 是键。label 是 CRM 页面上的标签,value 是标签的值。

防止显示自定义数据

您可以将 invisible_to_agent 属性与 customData 对象搭配使用,以防止在代理适配器中显示已签名或未签名的自定义数据。在以下示例中,代理适配器中显示了版本,但未显示平台。

var ujet = new UJET({
  // Other parameters
});

ujet.config({
  customData: {
    version: {
      label: 'Version',
      value: '1.1.0'
      invisible_to_agent: true
    },
    platform: {
      label: 'Platform',
      value: navigator.platform
      invisible_to_agent: false
    }
  }
});

如果您在自定义数据对象中添加 "invisible_to_agent" : true 属性,则会发生以下行为:

如需了解详情,请参阅在代理适配器中查看会话数据

预留的数据属性

您可以在会话开始时,以签名自定义数据的形式将预留数据属性发送到 Contact Center AI 平台 (CCAI Platform)。如需了解详情,请参阅发送预留数据属性

以下是自定义数据中预留的数据属性的示例:

  {
    "custom_data": {
      "reserved_verified_customer": {
        "label": "Verified Customer",
        "value": "VERIFIED_CUSTOMER_BOOLEAN": ,
        "type": "boolean"
      },
      "reserved_bad_actor": {
        "label": "Bad Actor",
        "value": "VERIFIED_BAD_ACTOR_BOOLEAN": ,
        "type": "boolean"
      },
      "reserved_repeat_customer": {
        "label": "Repeat Customer",
        "value": "REPEAT_CUSTOMER_BOOLEAN": ,
        "type": "boolean"
      }
    }
  }
  

替换以下内容:

  • VERIFIED_CUSTOMER_BOOLEAN:如果您认为相应最终用户是合法客户,则为 True。
  • VERIFIED_BAD_ACTOR_BOOLEAN:如果您认为此最终用户可能是恶意行为者,则为 True。
  • REPEAT_CUSTOMER_BOOLEAN:如果已确定相应最终用户之前曾联系过您的联络中心,则为 True。

停用附件

您可以使用 disableAttachment 选项阻止消费者上传附件:

new UJET({
// ...
  disableAttachment: true
});

使用 disableAttachment: true 时,聊天输入区域中不会显示附件图标,并且消费者无法将文件拖动到消息区域。

Chat 分流

如果客服人员无法提供服务,您可以指定选项,以便在网页聊天和移动聊天中自动处理这种情况。

您可以在 CCAI Platform 门户中找到聊天分流选项,具体位置为设置>聊天>网站和移动应用分流

非营业时间转接

非工作时间转接是指联络中心或队列不在工作时间内。如需启用非工作时间转接,请执行以下操作:

  1. 在 CCAI 平台门户中,依次前往设置 > Chat > 网站和移动设备分流

  2. 如果非工作时间转接处于关闭状态,则可以选择非工作时间转接选项来启用该功能。

  3. 更改允许转移选项,以允许在营业时间以外将呼叫转移到队列,从而实现以下行为:

    • 代理将能够在代理适配器中看到以下队列,并可选择将通话转接到这些队列:

      • 工作时间内的所有队列

      • 所有在营业时间之外且未启用转接功能的队列,以及已登录的客服人员

      • 所有非工作时间且已分配虚拟客服的队列(24 小时可用性模式)

    • 客服人员将无法看到以下类型的队列:

      • 所有在非工作时间启用非工作时间转接的队列

      • 所有在营业时间之外且分配了虚拟代理的队列(虚拟代理的队列营业时间有限)

容量过载分流

超出容量分流是指当前客服人员容量和会话所分配到的队列的当前等待时间。如需启用此选项,请执行以下操作:

  1. 在 Contact Center AI Platform 门户中,依次前往设置 > Chat > 网站和移动应用分流

  2. 如果超额容量分流处于关闭状态,请选择超额容量分流切换开关以将其开启。

  3. 设置等待时间(以分钟为单位),该时间会使队列的状态更改为“超负荷”。

    此时间阈值设置还用于设置最终用户看到超容量消息的频次。

偏转选项

可以指定在发生转接时可供最终用户选择的选项。

电子邮件

启用电子邮件选项后,最终用户可以转为通过电子邮件进行沟通。如果最终用户在下班时间后建立网页或移动聊天会话,系统会询问他们是否要撰写电子邮件。

具体行为如下:

  • 移动设备:在启用电子邮件分流功能并达到估计等待时间阈值后,当最终用户点按 Chat 选项时,系统会将他们定向到其默认电子邮件应用。应用版本和 iOS/Android 版本会自动插入到电子邮件正文中,主题为[所选菜单路径]的支持。或者,电子邮件表单可能已启用。如需了解详情,请参阅适用于移动和 Web SDK 的集成式电子邮件表单

  • 网站:向最终用户显示电子邮件选项。点击后,系统会显示电子邮件表单。如需了解详情,请参阅适用于移动和 Web SDK 的集成式电子邮件表单

  • 继续等待(仅限网页版):允许最终用户点击某个选项来继续等待。

借助共同浏览意见征求对话框,最终用户可以同意初始共同浏览会话请求,以及后续的远程控制请求或完整设备访问权限请求。当您为共同浏览配置 Web SDK 时,Web SDK 会提供默认的意见征求对话框和会话结束按钮。不过,您可以向 cobrowseOptions 对象添加可选字段,以便自定义意见征求对话框以及会话结束按钮。这样一来,您不仅可以控制这些元素的外观和风格,还可以根据自己的需求定制意见征求对话框中的意见征求声明。

同意声明会显示在同意对话框中。同意声明会向最终用户说明他们可以从共同浏览体验中获得哪些行为,以及他们同意了哪些行为。如果您打算录制共同浏览会话,应在同意声明中说明这一点。如需查看包含意见征求声明的自定义意见征求对话框示例,请参阅自定义意见征求对话框的代码示例

过程

如需配置 Web SDK 以进行共同浏览并自定义同意对话框,请按以下步骤操作:

  1. 如需获取 CCAI Platform 实例的共同浏览网域和许可密钥,请执行以下操作:

    1. 使用管理员凭据登录 CCAI Platform 门户。

    2. 依次点击 菜单设置 > 开发者设置

    3. 前往共同浏览窗格,然后点击相应开关,将其切换到开启位置。

    4. 保存共同浏览网域许可密钥字段中的值。

  2. 如需初始化 Web SDK 并添加共同浏览自定义字段,请运行以下代码:

    var ujet = new UJET({
      // other options
      cobrowseOptions: {
        license: "LICENSE_KEY",
        trustedOrigins: ["CO-BROWSE_DOMAIN"],
        api: "CO-BROWSE_DOMAIN"
        cobrowseRequestHtml: "COBROWSE_REQUEST_HTML",
        remoteControlHtml: "REMOTE_CONTROL_HTML",
        fullDeviceHtml: "FULL_DEVICE_HTML",
        styles: "STYLES",
        sessionControlsHtml: "SESSION_CONTROLS_HTML"
      },
      // other options
    })
    

    替换以下内容:

按钮类

意见征求对话框包含一些按钮,用户可以通过这些按钮允许或拒绝共同浏览请求,或者关闭意见征求对话框。为了让这些按钮能够与 Web SDK 通信,您必须将以下按钮类与相应的按钮类型相关联。Web SDK 会在代码中搜索这些类,并为每个类添加一个事件监听器。以下是按钮类:

  • cobrowse-allow:供最终用户允许请求的按钮

  • cobrowse-deny:供最终用户拒绝请求的按钮

  • cobrowse-close:供最终用户关闭意见征求对话框的按钮

以下代码示例包含自定义意见征求对话框、会话结束按钮以及这些元素的样式信息。示例中的每个意见征求对话框都包含一条意见征求声明。以下是三种共同浏览模式的意见征求对话框的属性:

"cobrowseOptions": {
    "license": "example_license",
    "trustedOrigins": "[https://example.com]",
    "cobrowseRequestHtml": "<div class=\"custom-backdrop\">\n <div class=\"cobrowse-confirm-dialog\">\n <div class=\"title\">\n <div></div>\n <span>Co-browse</span>\n <div class=\"cobrowse-close cobrowse-deny\">\n <svg width=\"14\" height=\"14842 13.1765 11.5294L8.64706 7L13.1765 2.47059C13.6313 2.01577 13.6313 1.27835 13.1765 0.823529C12.7216 0.368707 11.9842 0.368706 11.5294 0.823529L7 5.35294Z\" fill=\"#919191\"/>\n </svg>\n </div>\n </div>\n <div class=\"body\">\n <h2>Get step-by-step live and secure guidance with a Care Expert</h2>\n \n <ul>\n <li>Stop screen sharing at any time</li>\n <li>Personal info automatically hidden</li>\n  <li>Only your_company_name screens are shared</li>\n </ul>\n </div>\n <div class=\"description\">\n <svg id=\"loader\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"12\" y1=\"2\" x2=\"12\" y2=\"6\"></line><line x1=\"12\" y1=\"18\" x2=\"12\" y2=\"22\"></line><line x1=\"4.93\" y1=\"4.93\" x2=\"7.76\" y2=\"7.76\"></line><line x1=\"16.24\" y1=\"16.24\" x2=\"19.07\" y2=\"19.07\"></line><line x1=\"2\" y1=\"12\" x2=\"6\" y2=\"12\"></line><line x1=\"18\" y1=\"12\" x2=\"22\" y2=\"12\"></line><line x1=\"4.93\" y1=\"19.07\" x2=\"7.76\" y2=\"16.24\"></line><line x1=\"16.24\" y1=\"7.76\" x2=\"19.07\" y2=\"4.93\"></line></svg>\n <span>\n Co-browse lets us view your active session in a limited way to give you live, on-screen assistance. We won't be able to view any other applications on your device.\n </span>\n </div>\n <div class=\"footer\">\n <span>\n By tapping accept & continue, you are consenting to allow the your_company_name Expert to view your screen to initiate assisted navigation. <a href=\"https://www.example.com\">View the your_company_name Privacy Policy</a>\n </span>\n <button class=\"cobrowse-allow\">Accept & continue</button>\n </div>\n </div>\n </div>\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M7 5.35294L2.47059 0.823529C2.01577 0.368707 1.27835 0.368707 0.823529 0.823529C0.368707 1.27835 0.368706 2.01576 0.823529 2.47059L5.35294 7L0.823529 11.5294C0.368707 11.9842 0.368707 12.7216 0.823529 13.1765C1.27835 13.6313 2.01576 13.6313 2.47059 13.1765L7 8.64706L11.5294 13.1765C11.9842 13.6313 12.7216 13.6313 13.1765 13.1765C13.6313 12.7216 13.6313 11.9",
    "remoteControlHtml": "<div class=\"custom-backdrop\">\n <div class=\"cobrowse-confirm-dialog\">\n <div class=\"title\">\n <div></div>\n <span>Co-browse</span>\n <div class=\"cobrowse-close cobrowse-deny\">\n  <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M7 5.35294L2.47059 0.823529C2.01577 0.368707 1.27835 0.368707 0.823529 0.823529C0.368707 1.27835 0.368706 2.01576 0.823529 2.47059L5.35294 7L0.823529 11.5294C0.368707 11.9842 0.368707 12.7216 0.823529 13.1765C1.27835 13.6313 2.01576 13.6313 2.47059 13.1765L7 8.64706L11.5294 13.1765C11.9842 13.6313 12.7216 13.6313 13.1765 13.1765C13.6313 12.7216 13.6313 11.9842 13.1765 11.5294L8.64706 7L13.1765 2.47059C13.6313 2.01577 13.6313 1.27835 13.1765 0.823529C12.7216 0.368707 11.9842 0.368706 11.5294 0.823529L7 5.35294Z\" fill=\"#919191\"/>\n  </svg>\n </div>\n </div>\n <div class=\"body\">\n <h2>Get step-by-step live and secure guidance with a Care Expert</h2>\n \n <ul>\n  <li>Stop screen sharing at any time</li>\n  <li>Personal info automatically hidden</li>\n <li>Only your_company_name screens are shared</li>\n</ul>\n</div>\n<div class=\"description\">\n<svg id=\"loader\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"12\" y1=\"2\" x2=\"12\" y2=\"6\"></line><line x1=\"12\" y1=\"18\" x2=\"12\" y2=\"22\"></line><line x1=\"4.93\" y1=\"4.93\" x2=\"7.76\" y2=\"7.76\"></line><line x1=\"16.24\" y1=\"16.24\" x2=\"19.07\" y2=\"19.07\"></line><line x1=\"2\" y1=\"12\" x2=\"6\" y2=\"12\"></line><line x1=\"18\" y1=\"12\" x2=\"22\" y2=\"12\"></line><line x1=\"4.93\" y1=\"19.07\" x2=\"7.76\" y2=\"16.24\"></line><line x1=\"16.24\" y1=\"7.76\" x2=\"19.07\" y2=\"4.93\"></line></svg>\n<span>\n Co-browse lets us view your active session in a limited way to give you live, on-screen assistance. We won't be able to view any other applications on your device.\n</span>\n</div>\n<div class=\"footer\">\n<span>\n By tapping accept & continue, you are consenting to allow the your_company_name Expert to view your screen to initiate assisted navigation. <a href=\"https://www.example.com\">View the your_company_name Privacy Policy</a>\n </span>\n <button class=\"cobrowse-allow\">Accept & continue</button>\n </div>\n </div>\n </div>",
    "fullDeviceHtml": "<div class=\"custom-backdrop\">\n <div class=\"cobrowse-confirm-dialog\">\n <div class=\"title\">\n <div></div>\n <span>Co-browse</span>\n <div class=\"cobrowse-close cobrowse-deny\">\n  <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M7 5.35294L2.47059 0.823529C2.01577 0.368707 1.27835 0.368707 0.823529 0.823529C0.368707 1.27835 0.368706 2.01576 0.823529 2.47059L5.35294 7L0.823529 11.5294C0.368707 11.9842 0.368707 12.7216 0.823529 13.1765C1.27835 13.6313 2.01576 13.6313 2.47059 13.1765L7 8.64706L11.5294 13.1765C11.9842 13.6313 12.7216 13.6313 13.1765 13.1765C13.6313 12.7216 13.6313 11.9842 13.1765 11.5294L8.64706 7L13.1765 2.47059C13.6313 2.01577 13.6313 1.27835 13.1765 0.823529C12.7216 0.368707 11.9842 0.368706 11.5294 0.823529L7 5.35294Z\" fill=\"#919191\"/>\n </svg>\n </div>\n </div>\n <div class=\"body\">\n <h2>Get step-by-step live and secure guidance with a Care Expert</h2>\n \n <ul>\n <li>Stop screen sharing at any time</li>\n <li>Personal info automatically hidden</li>\n <li>Only your_company_name screens are shared</li>\n </ul>\n </div>\n <div class=\"description\">\n <svg id=\"loader\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"12\" y1=\"2\" x2=\"12\" y2=\"6\"></line><line x1=\"12\" y1=\"18\" x2=\"12\" y2=\"22\"></line><line x1=\"4.93\" y1=\"4.93\" x2=\"7.76\" y2=\"7.76\"></line><line x1=\"16.24\" y1=\"16.24\" x2=\"19.07\" y2=\"19.07\"></line><line x1=\"2\" y1=\"12\" x2=\"6\" y2=\"12\"></line><line x1=\"18\" y1=\"12\" x2=\"22\" y2=\"12\"></line><line x1=\"4.93\" y1=\"19.07\" x2=\"7.76\" y2=\"16.24\"></line><line x1=\"16.24\" y1=\"7.76\" x2=\"19.07\" y2=\"4.93\"></line></svg>\n <span>\n Co-browse lets us view your active session in a limited way to give you live, on-screen assistance. We won't be able to view any other applications on your device.\n </span>\n </div>\n <div class=\"footer\">\n <span>\n By tapping accept & continue, you are consenting to allow the your_company_name Expert to view your screen to initiate assisted navigation. <a href=\"https://www.example.com\">View the your_company_name Privacy Policy</a>\n </span>\n  <button class=\"cobrowse-allow\">Accept & continue</button>\n </div>\n </div>\n </div>",
    "styles": ".some-end-button {\n border-radius: 20px;\n background-color: blue;\n color: white;\n display: marquee;\n width: 20rem;\n font-size:200%;\n height: 20rem;\n }\n .custom-backdrop {\n background: rgba(0, 0, 0, 0.1);\n position: fixed;\n z-index: 2147483647;\n bottom: 0;\n top: 0;\n left: 0;\n right: 0;\n }\n .cobrowse-confirm-dialog {\n color: #232424;\n font-family:sans-serif;\n line-height:140%;\n position:fixed;\n background:white;\n border-radius:5px;\n z-index:2147483647;\n top:50px;\n left:50%;\n width:75%;\n max-width:450px;\n transform:translateX(-50%);\n box-shadow:2px 2px 30px rgb(0,0,0,0.08);\n padding: 1.5rem;\n }\n .title {\n text-align:center;\n display: flex;\n align-items: center;\n justify-content: space-between;\n font-size: 125%;\n line-height: 25px;\n padding: 20px;\n border-radius: 5px 5px 0 0;\n }\n \n .description {\n height: 8rem;\n display: flex;\n flex-direction:column;\n justify-content: center;\n align-items: center;\n background-color: #F3F3F3;\n }\n \n #loader {\n height:4rem;\n }\n \n .footer {\n margin-top: 1rem;\n margin-bottom: 1rem;\n display: flex;\n flex-direction: column;\n justify-content: flex-start\n }\n .cobrowse-allow {\n background-color: pink;\n color: white;\n flex-grow: 2;\n height: 3rem;\n }\n #cobrowse-end-button {\n cursor: pointer;\n position: fixed;\n z-index: 2147483647;\n top: 50%;\n left: 25%;\n transform: translateX(-50%);\n display: flex;\n justify-content: center;\n align-items: center;\n }\n #cobrowse-end-button:hover {\n background-color: #92162D;\n }",
    "sessionControlsHtml": " <div class=\"some-end-button\">\n End Session\n </div>"
  }

如需了解详情,请参阅设置共同浏览

多种语言和视觉消息自定义

新的 CCAI 平台(选项)方法包含两个字段,可支持多种语言和视觉消息自定义:

  • lang:表示最终用户未选择首选语言时的默认语言。此代码符合 ISO 639-1 标准,如果省略,则默认为“en”。

  • translation:Web SDK 支持多种语言的显示文本。借助翻译对象,您可以自定义现有语言的文本,甚至可以添加新语言的文本。例如:de、es、fr、ja。

以下是一个用于自定义英文文案的翻译对象示例。如您所见,翻译对象的顶级键应该是语言代码。

// ES6
let translation = `{
  "en": {
    "ujet_start_title": "Hi!"
  },
  "es": {
    "ujet_start_title": "¡Hola!"
  },
  "fr": {
    "ujet_start_title": "Salut!"
  },
  "de": {
    "ujet_start_title": "Hallo!"
  },
  "it": {
    "ujet_start_title": "Ciao!"
  },
  "ja": {
    "ujet_start_title": "こんにちは!"
  },
  "ko": {
    "ujet_start_title": "안녕하세요!"
  },
  "pt": {
    "ujet_start_title": "Olá!"
  },
  "pt-BR": {
    "ujet_start_title": "Olá!"
  },
  "sv": {
    "ujet_start_title": "Hej!"
  }
}`;

// initialize when dom ready
var ujet = new UJET({
  // other fields
  lang: 'en',
  translation: translation
});

自定义消息如下:

"ujet_ask_phone_number_button_title": "Call Me"
"ujet_ask_phone_number_description": "Provide your phone number below"
"ujet_ask_phone_number_title_instant": "We'll Call You"
"ujet_ask_phone_number_title_scheduled": "Let's Schedule a Call"
"ujet_ask_phone_number_warning": "Your call may be monitored or recorded for training and quality assurance purposes."
"ujet_call_confirm_content": "Your phone should be ringing right about - {0}"
"ujet_call_confirm_start_new_conversation": "Start A New Conversation"
"ujet_call_record_permission_subtitle": "Do you give permission for {0} to record your call for training and quality?"
"ujet_call_record_permission_title": "Permission to Record"
"ujet_channel_chat": "Let's connect you to one of our chat support specialists",
"ujet_channel_instant_call": "Let one of our support specialists give you a call now",
"ujet_channel_menu_chat": "Chat now"
"ujet_channel_menu_email": "Email"
"ujet_channel_menu_instant_call": "Call now"
"ujet_channel_menu_keep_waiting": "Keep Waiting"
"ujet_channel_menu_scheduled_call": "Schedule call"
"ujet_channel_scheduled_call": "Let's schedule a time for a support specialist to call and help you",
"ujet_channel_email": "Please send us an email so we can help",
"ujet_chat_end": "End chat"
"ujet_chat_ended": "This chat has ended"
"ujet_chat_input_placeholder": "Type your message here"
"ujet_chat_leave": "Leave chat"
"ujet_chat_timed_out": "This chat has timed out"
"ujet_chat_title_with_multiple_agent": "Multiple Agents"
"ujet_chat_title_with_one_agent": "Chatting with {0}"
"ujet_chat_title_with_two_agent": "Chatting with {0} & {1}"
"ujet_chat_transfer_failed": "Transfer has failed"
"ujet_chat_transfer_joined": "<b>{0}<\/b> just joined the conversation"
"ujet_chat_transfer_left": "<b>{0}<\/b> just left the conversation"
"ujet_chat_transfer_started_menu": "<b>{0}<\/b> is transferring this chat to another agent..."
"ujet_chat_transfer_started_user": "<b>{0}<\/b> is adding another agent to this conversation..."
"ujet_common_back": "Back"
"ujet_common_cancel": "Cancel"
"ujet_common_end": "End"
"ujet_common_no": "No"
"ujet_common_save": "Save"
"ujet_common_submit": "Submit"
"ujet_common_support": "Support"
"ujet_common_yes": "Yes"
"ujet_deflection_menu_title": "Select from the options below"
"ujet_error_no_available_language": "No Available Language"
"ujet_error_phone_number_invalid": "Please input a valid phone number."
"ujet_file_upload_button": "Choose a file to upload"
"ujet_file_upload_failure_size": "Looks like we couldn't upload. <br> Please try uploading a file <br> that is less than {0}."
"ujet_file_upload_failure_type": "Looks like we couldn't upload. <br> We only accept <br> .JPG, .PNG, or .MP4."
"ujet_file_upload_failure_unknown": "Looks like we couldn't upload. <br> Please try again!"
"ujet_file_upload_subtitle": "Drop files here to upload"
"ujet_file_upload_title": "Upload Files"
"ujet_greeting": "Hi there, how can we help?"
"ujet_instant_call_confirm_content": "Your phone should be ringing shortly"
"ujet_language_chinese": "中文"
"ujet_language_english": "English"
"ujet_language_french": "Français"
"ujet_language_german": "Deutsch"
"ujet_language_italian": "Italiano"
"ujet_language_japanese": "日本語"
"ujet_language_korean": "한국어"
"ujet_language_portuguese": "Português (Portugal)"
"ujet_language_portuguese_brazil": "Português (Brazil)"
"ujet_language_spanish": "Español"
"ujet_language_swedish": "Svenska"
"ujet_menu_title": "Select an option"
"ujet_message_back_in_menu": "Looks like you changed your mind! How else can we help?"
"ujet_message_channel": "How would you like to communicate?"
"ujet_message_chat_deflection_afterhour": "We are currently closed. We look forward to helping you during our normal business hours."
"ujet_message_chat_deflection_default": "We are currently experiencing a high volume of requests with a current wait time of <b>{0}<\/b>. How would you like to reach out?"
"ujet_message_chat_deflection_email": "Please contact us via email: <b><a href="mailto:{0}">{0}<\/a><\/b>."
"ujet_message_chat_deflection_keepwaiting": "Thank you for continuing to wait. The remaining wait time is <b>{0}<\/b>."
"ujet_message_chat_deflection_outage": "We are currently experiencing a high volume of request, how would you like to reach out?"
"ujet_message_chat_deflection_recurring": "Thanks for your patience! The remaining wait time is <b>{0}<\/b>."
"ujet_message_chat_restart": "Connecting to your ongoing chat, one moment please..."
"ujet_message_chat_start": "One moment please..."
"ujet_message_queue": "Let's help you with<br /><strong>{0}<\/strong>"
"ujet_rating_feedback_placeholder": "Let us know how we can improve."
"ujet_rating_result_subtitle": "We appreciate your feedback"
"ujet_rating_result_title": "Thank you!"
"ujet_rating_title": "Rate Your Experience"
"ujet_redirect_action_title": "Open this page in a new tab"
"ujet_redirect_url_title": "Visit the page below"
"ujet_schedule_time_description": "Pick a time that works best for you"
"ujet_schedule_time_title": "Let's Schedule a Call"
"ujet_scheduled_call_cancel_cancel": "Cancel"
"ujet_scheduled_call_cancel_content": "You scheduled a support call for<br><b>{0}<\/b> at <b>{1}<\/b>."
"ujet_scheduled_call_cancel_keep": "Keep It"
"ujet_scheduled_call_cancel_title": "Cancel the existing call?"
"ujet_screenshot_init_cancel": "No Thanks"
"ujet_screenshot_init_okay": "Accept"
"ujet_screenshot_init_title": "Screenshot Request"
"ujet_screenshot_install_cancel": "Cancel"
"ujet_screenshot_install_okay": "Install"
"ujet_screenshot_install_title": "Install Chrome Extension"
"ujet_screenshot_take_action": "Take Screenshot"
"ujet_screenshot_take_title": "Click the button below to send a screenshot to the agent"
"ujet_screenshot_verify_cancel": "No"
"ujet_screenshot_verify_okay": "Yes"
"ujet_screenshot_verify_title": "Successfully Installed Chrome Extension"
"ujet_start_title": "Need any help?"
"ujet_tap_to_minimize": "Tap to minimize"
"ujet_time_hour": "hour | hours"
"ujet_time_minute": "minute | minutes"

徽标和图标自定义

new UJET(option) 方法具有支持自定义徽标和图标的字段。

  • logo:徽标图片的网址

  • 微件的位置(仅适用于桌面设备)

    • right:以像素为单位设置右边缘位置(默认值为 50)

    • bottom:以像素为单位设置底部边线位置(默认值为 50)

  • 图标的位置(仅适用于桌面设备)

    • right:以像素为单位设置右边缘位置(默认值为 50)

    • bottom:以像素为单位设置底部边线位置(默认值为 50)

徽标和图标自定义示例

new UJET({
  logo: 'https://example.com/logo.svg',
  // widget position
  right: '50px',
  bottom: '150px',

  // launcher position
  launcher: {
    right: '50px',
    bottom: '50px',
  }
})

徽标和图标自定义

徽标和图标自定义

徽标和图标自定义

徽标和图标自定义

主题自定义

new UJET(option) 方法有一个字段来支持主题自定义。

  • style:主题对象支持 widget 的四种值。

    • links:网页字体的样式表链接列表

    • --primary-font:应用于整个 Web 界面的 font-family CSS 样式的值,例如 Merriweather

    • --primary-color:用作 Web 界面主色的十六进制代码值,例如 #51C3C3

    • --link-color:用作 Web 界面链接颜色的十六进制代码值,例如 #51C3C3

  • 启动器:启动器对象支持以下四个启动器值。

    • cssText:用作启动器 CSS 样式的 CSS 语法

    • chatIcon:用于常规聊天图标的 SVG 图标网址

    • closeIcon:用于关闭图标的 SVG 图标网址

    • style:此分离的主题对象支持启动器的两个值。

      • --background-color:用作启动器背景颜色的十六进制代码值,例如 #E85230 --icon-color:用作启动器图标颜色的十六进制代码值,例如 #FFF
var ujet = new UJET({
  // ...
  style: {
    links: [
      'https://fonts.example.com/css?family=Droid+Serif:400,700&display=swap',
    ],
    '--primary-font': 'Droid Serif, Georgia, serif',
    '--primary-color': '#F1684A',
    '--link-color': '#F1684A',
  },
  launcher: {
    cssText: '.wrap button {background: #E85230}',
    chatIcon: 'https://example.com/logo.svg',
    closeIcon: 'https://example.com/close.svg',
    style: {
      '--background-color': '#F1684A',
      '--icon-color': '#fff',
    }
  }
});

启动器样式

跟踪渠道选择和电子邮件提交

为了能够跟踪渠道选择和电子邮件提交情况,Web SDK 使用 postMessage 函数传递包含以下数据的消息:

  • 应用:设备类型。

  • sdk_version::Web SDK 的版本。

  • user_agent::浏览器版本。

  • 公司:租户名称。

  • menu_name::最终用户选择的队列或菜单的名称。

  • menu_path::最终用户选择的队列或菜单的路径。

  • menu_id::最终用户选择的队列或菜单的菜单 ID。

  • 网址:最终用户在选择渠道或提交电子邮件时所处的网页的网址。

  • timestamp:最终用户做出选择的时间。

  • has_attachments::电子邮件在提交时是否包含附件(仅在电子邮件提交期间显示,不在渠道选择期间显示)。

消息数据存储在一个具有 2 个属性的 ujet 对象中:一个名为 action,是一个包含已完成操作名称的字符串;另一个名为 data,包含前面所述的数据。

如需从消息中检索数据,您可以创建一个监听“message”的事件监听器。下一部分将介绍一个将操作和数据输出到控制台的示例。您可以在 tracking-channel-selection 文件夹中找到一个可正常运行的示例。

window.addEventListener('message', (e) => {
  if (e.data && e.data.ujet) {
    console.log(`Action: ${e.data.ujet.action}`);
    console.log(`Message Data: ${e.data.ujet.data}`);
  }
});

隐藏代理徽标边框

如需隐藏代理徽标边框,请在样式属性中添加“--logo-shadow”:“none”,并在新 UJET(选项)中将其设置为 true:

new UJET({
  // ...
  style: {
    '--logo-shadow': 'none',
  }
});

隐藏启动图标

出于美观方面的考虑,您可以选择隐藏 Web 界面启动图标,改为使用主动聊天触发器或以编程方式启动聊天。如需移除启动图标,请添加启动器属性,并在新的 UJET(选项)中将其设置为 true:

new UJET({
  // ...
  launcher: false,
});

如需以编程方式启动 Web 界面,请参阅以编程方式启动 Web 界面。 如需使用主动聊天触发器启动网页界面,请参阅主动触发器

使用直接访问点

您可以使用直接访问功能将最终用户直接转到特定队列。

如需使用直连接入点,请按以下步骤操作:

  1. 登录 CCAI 平台门户。

  2. 前往设置 > 队列

  3. 通过切换使用来确保已启用 Web 渠道。

  4. 前往修改 > 查看,了解网络渠道。系统随即显示网站结构。

  5. 选择您希望最终用户直接进入的队列。

  6. 前往接入点部分,然后点击创建直接接入点

  7. 提供以下信息:

    1. 接入点类型设置为常规

    2. 提供接入点名称。此名称会显示在接入点列表中。

    3. 提供常规接入点标签。您将使用此值来配置 Web SDK。

  8. 点击创建

您可以使用 ujet.start(options) 方法传递直接访问点的名称。请参阅以下示例:

var launcher = document.getElementById('launcher');
launcher.addEventListener('click', function() {
  if (ujet.status === 'open') {
    ujet.close();
  } else {
    ujet.start({ menuKey: '__MENU_KEY__' });
  }
});

以程序化方式关闭网页界面

这是一个可选步骤。 如果不执行此步骤,Web 界面将自行完成并最小化。

此步骤可让您在消费者想要关闭 Web SDK 时调用回调函数。

ujet.on('close', function() {
  // do something here
});

以编程方式启动网页界面

这是一个可选步骤。 如果不执行此步骤,最终用户可以点击 Web 界面启动图标来启动 Web 界面。

此步骤可让您使用 ujet.start(options) 方法以程序化方式打开 Web 界面。您可能希望最终用户点击一个额外的按钮来打开网页界面,如下所示:

<button id="launcher">点击打开</button>

var ujet = new UJET({
  companyId: "YOUR_COMPANY_ID",
  host: "HOST_URL",
  launcher: false
});

var launcher = document.getElementById('launcher');
launcher.addEventListener('click', function() {
  if (ujet.status === 'open') {
    ujet.close();
  } else {
    ujet.start();
  }
});

ujet.on('ready', function() {
  launcher.textContent = 'ready to talk';
});

ujet.registerHook('loading', function() {
  launcher.textContent = 'loading';
});

ujet.registerHook('open', function() {
  launcher.textContent = 'Click to close';
});

ujet.registerHook('close', function() {
  launcher.textContent = 'Click to open';
});

ujet.on('created', function() {
  ujet.authenticate(getAuthToken);
});

您还可以使用 ujet.close() 方法关闭 widget,并使用 ujet.destroy() 方法移除 widget。

主动触发

借助主动触发器,您可以触发 Web SDK 主动向最终用户发送消息。

如需设置主动触发器,请按以下步骤操作:

  1. 在 CCAI Platform 门户中,依次前往设置 > 对话

  2. 前往网站主动聊天触发器窗格,然后点击查看触发器。系统随即会显示触发器窗格。

  3. 点击添加触发器。系统随即会显示选择名称窗格。

  4. 触发器名称字段中,输入一个名称,然后点击下一步。系统随即会显示设置条件窗格。

  5. 如需设置条件,请执行以下操作:

    1. 最终用户旁边,选择一个条件。

    2. 输入关键字字段中,输入您希望条件引用的关键字,然后按 Enter 键。

    3. 针对要输入的每个关键字重复执行上一步骤。

    4. 如需添加其他条件,请点击添加其他条件,然后点击所需的条件类型。

    5. 为条件设置配置选项。

    6. 如需添加其他条件,请重复前两个步骤。

    7. 点击下一步。系统随即会显示定义操作窗格。

  6. 如需定义操作,请执行以下操作:

    1. 队列分配下,输入您要将最终用户分配到的聊天队列节点的名称。如果存在具有此名称的聊天队列,该名称会以粗体显示在字段下方。

    2. 点击粗体显示的聊天队列名称。此时会显示一个确认对话框。

    3. 点击确定继续。

    4. 聊天消息下,输入要在触发的聊天中显示的消息。

    5. 点击完成

    6. 如需激活新触发器,请点击发布

现有工单 ID

如果您有最终用户的现有工单,可以从 CRM 中检索工单 ID,并通过调用 ujet.start() 将其传递到 Web SDK 中。

例如:

yourFunctionToRetrieveTicket()
  .then((existingTicket) => {
    ujet.start({ ticketId: existingTicket });
  });

您可以参考工单 ID 文件夹中的示例。