LoginSignup
19
19

Service Cloud チャット設定の基礎と実践

Last updated at Posted at 2020-02-22

Salesforce (Service Cloud) のチャットでは、CRM データと連携し高度な顧客対応を実現できますが、その設定コンポーネントは数が多く、初心者にはややとっつきにくいのも事実です。この記事では、Service Cloud のチャット設定の全体像を俯瞰し、基礎的なユースケースに対する設定・開発例を示します。なお、Service Cloud は有人チャットとチャットボット両方の受付チャネルをサポートしていますが、この記事では有人チャットのカスタマイズを扱います。

基礎編

Lightning Experience では、顧客からのチャット要求は必ず「オムニチャネル」機能を通してオペレータ (エージェント) に転送する必要があります。オムニチャネルは、チャット要求やケース、カスタムオブジェクト等を抽象化した「作業項目 (AgentWork)」として、事前定義したルールに沿ってエージェントに割り振る仕組みです。このオムニチャネルの設定とチャット固有の設定が混在していることが、初めての方にとってチャットの設定が複雑に感じる原因です。以下に設定の全体像を示します。まずはミニマムな設定を試した上で、細かな設定を掘り下げていきましょう。

Chat setting overview

クイックスタート

「とりあえず動くようにする」ための設定手順は、以下の通りです。

  1. エージェントがチャットのステータスをオンラインにできる

  2. エージェントがチャット要求を処理できる

    • ユーザを、エージェントの作業項目・チャットのトランスクリプト・チャットセッションをサポートするキューに加える
    • ルーティング設定を作成し、キューからそのルーティング設定を参照する
      • ルーティングモデルと業務単位/業務率は任意で良いが、業務単位にする場合は5以下とすること (デフォルトのキャパシティが5のためこれより大きいと転送されない)
  3. 顧客が Web ページでチャットを起動できる

    • 3-1. コードスニペットを作成する
    • 3-2. コードスニペットを配置する
      • Experience Cloud の場合は、組み込みサービスチャットコンポーネントを配置する
        • CSP エラーが発生する場合は、コミュニティのセキュリティ設定 → CSP 設定からインラインスクリプトを許可し、チャットリリースの liveagent.init() 内のドメイン (e.g., https://d.la1-c2-ia5.salesforceliveagent.com ) を追加する
      • 一般のWebサイトの場合は、組み込みサービスリリースの詳細に表示されるコードスニペットを Web サイトの HTML に組み込む
        • CORS 設定で Web サイトのドメインを追加する (Visualforce ページで試す場合も同様)

Salesforce のオムニチャネルコンポーネントからチャットをオンラインにし、ブラウザの別タブで、組み込みサービスを配置した Web サイトを開くと、チャットが開始できるはずです。個々の設定内容の詳細は後述します。

Chat request

クイック設定について

ちょっと試すだけでも設定画面が多い!そこで提供されている設定 UI が「クイック設定」です。クイック設定は、コンソールアプリケーションから遷移できる「サービスの設定」のホームからアクセスでき、複数の設定コンポーネントを1つのウィザードを通して簡単に設定することができます。

Service quick setup

クイック設定の利点はその簡易さにありますが、将来の拡張を考慮すると、どこにどのような設定が行われているのかを理解しておいた方が良いでしょう。また、クイック設定では API 名が自動設定されることにも注意してください。

この記事ではクイック設定は使用せず、必要な設定を1つずつ行っていく方法を記載しています。

組み込みサービスかチャットボタンの直接使用か

Web サイトから顧客がチャットを起動するためには、1) 組み込みサービス(旧名Snap-ins)のコードスニペットを埋め込む 2) チャットボタン設定にあるコードスニペットを埋め込む の2通りがあります。1

組み込みサービスは比較的新しい機能で、チャットボタンとチャットリリースのコードを直接使用するのは、組み込みサービスが登場する以前から提供されていた機能になります。組み込みサービスと、チャットボタンの直接使用との比較は以下の通りです。

組み込みサービス チャットボタンの直接使用
継続的なアップデート 直近数回のメジャーリリースによる機能追加あり 最近の機能追加はない
ブランディング設定 設定である程度カバー Visualforce ページでの上書きのみサポート
チャットウィンドウの起動方法 同一ページ上にフロート表示 別ウィンドウで表示
(window.open)
標準でサポートされるオブジェクト チャットの他、ケースや問い合わせ要求の作成も可能 チャットのみ

標準機能ベースで実装を開始するのであれば、組み込みサービスの方が使いやすいでしょう。最初の設定でも挙げたように、この記事では組み込みサービスを中心とした設定方法を記載しています。ちなみに、Salesforce 公式の Web サイト でも組み込みサービスを使用したチャットサポートが受けられます。

実践編

次のようなシナリオを実装してみましょう。

Intermediate scenario
  • ベテランさんは新人さんと比較して2倍の数だけ、同時にチャット対応ができる。
  • 対応できるエージェントが一杯の場合は、一定数の顧客を待ち行列に待機させたい。
  • 主なチャット問い合わせの種類は、「料金」「テクニカルサポート」「注文」の3種類で、それぞれ対応できるエージェントが異なる。
  • 料金に関する問い合わせに回答するのは複雑であり、他の問い合わせよりも2倍の負荷がかかる。
  • チャットを開始する前に、顧客にフォームで問い合わせカテゴリを選択させ、選択されたカテゴリのキューにチャット要求を転送したい。

これらは次のような設定で実現できます。

スクリーンショット 2020-02-20 12.48.17.png
  1. エージェントのステータスに関する設定

    • 特に追加設定なし
  2. チャット要求の処理方法に関する設定

    • ベテランと新人で異なるプレゼンス設定を割り当てる
    • チャットボタンの設定からキュー(待ち行列)を有効化する
    • 問い合わせ種別毎のキューとチャットボタンを作成する
    • ルーティング設定を分けることで作業項目の重みに差をつける
  3. 訪問者と Web ページに関する設定

    • 組み込みサービスリリースで事前フォームを設定する
    • 組み込みサービスのスクリプトで direct-to-button を設定する

以下で個々の設定内容の詳細を確認していきます。

エージェントと待ち行列のキャパシティ

各エージェントが同時対応可能なチャットの数 (※正確にはチャット以外の作業項目も含む業務量) は、[プレゼンス設定] で設定し、ユーザまたはプロファイルに割り当てます。何も設定しない場合はデフォルトのプレゼンス設定(最大業務量5)が割り当てられます。シナリオに当てはめると、ベテランさんには最大業務量4のプレゼンス設定を作成し割り当て、新人さんには最大業務量2のプレゼンス設定を作成して割り当てます。

プレゼンス設定

チャットボタンが参照するキューに所属するエージェントの業務量がフルの場合、顧客を待ち行列に待機させることが可能です。待ち行列のサイズは、チャットボタンのルーティング情報セクションで設定します。

スクリーンショット 2020-02-18 22.02.34.png

「Salesforce の設定としてのキュー(ユーザの集合)」 と「待ち行列としてのキュー」が同じ設定画面内で使われていて紛らわしいですね😂 このセクションでの [キューを有効化] は待ち行列の有効化を指します。待ち行列のサイズについては、待ち時間が長くなりすぎるとチャット開始前に離脱する場合(電話でいう放棄呼)が増えてしまい、不満につながる可能性があります。電話ほどシビアに考える必要はないと思いますが、つながらない場合の他チャネルへの誘導方法は決めておくと良いでしょう。オフラインフォームは簡単に利用できる機能の1つです。また、待ち行列のサイズを考慮するにあたっては、状況が「見逃し」のトランスクリプトの件数をレポートで出せるようにしておくとシステム運用上参考になるでしょう。

ちなみに、組み込みサービスリリースの設定では顧客に待ち行列の位置を表示するかどうかを選択できます。
キューの位置を表示

チャット要求の割り振り

オムニチャネルでは、顧客(訪問者)からのチャット要求(作業項目)は、次の2つの設定に従いエージェントに到達します。

  1. チャットボタン設定でエージェントの集合を決める
    • ここで「エージェントの集合」とは、キューに所属するエージェントまたは、特定のスキルを保持するエージェント達を指します。チャットボタンでこれを設定します。
  2. ルーティング設定で優先度と重みを決める
    • チャットボタンで指定されたキューまたはスキルを満たすエージェントの集合に対して、ルーティング設定で指定した優先度とサイズでチャットがエージェントに転送されます。

Step1. チャットボタン設定でエージェントの集合を決める

キューベースかスキルベースか

チャットボタンの設定ではキューまたはスキルを指定することができます。キューベースとスキルベースのルーティングの比較は以下の通りです。

ルーティング種別 挙動 管理するオブジェクト
キューベースのルーティング チャット要求を1つのキューに転送する 返品対応の問い合わせを、返品他チーム内の誰かに転送する
(※返品対応チームキューを作成しユーザを入れる)
・ユーザ (User)
・キュー (Group)
・GroupMember
スキルベースのルーティング チャット要求を1つ以上のスキルをもった(=スキル・スキルレベルを満たす)ユーザに転送する キャッシュバックキャンペーンに関する問い合わせを、料金問い合わせ対応チーム内の、研修受講済みのユーザに転送する
(※料金問い合わせ対応と研修のスキルを作成しサービスリソースに割り当て)
・ユーザ (User)
・サービスリソース (ServiceResource)
・スキル (Skill)
・ServiceResourceSkill

一般にキューは1つのスキルを指しますが、スキルベースのルーティングを用いるとより細かな粒度でエージェントへチャット要求を転送できます。チャット要求を、複数のスキル要件を満たすエージェントだけに転送したい場合は、スキルベースのルーティングを考慮する必要があるでしょう。ただし、スキルベースのルーティングは管理するオブジェクトが多くなるため、まずはキューベースでスモールスタートするのがおすすめです。

検討ポイント
  • 問い合わせ対応に必要なスキルの数はどれだけあるか
    • 複数のスキルが必要だが数が多く無い場合は、そのスキルを愚直にそのまま Salesforce のスキルに当てはめるのではなく、新たな1つのキューとして定義する方法も
  • キューまたはスキル・スキルレベル・サービスリソースを、誰が・どのくらいの頻度でメンテナンスするのか
    • 繁忙期などでエージェントが特定の期間に臨時で増員される場合はあるか、異動は多いか
    • キューの方がメンテナンスはやや容易
  • 同じキューの中での対応レベルの差異をどれだけ許容できるか
    • 異なるキュー・異なるスキルレベルにするか、単にキャパシティに差をつけるだけで良いか

なお、最近 GA となった、属性ベースのルーティングは、種別が製品サポートのケースを、製品サポートスキルレベル3以上のユーザに転送するといったような、「転送するレコードの値とスキル・スキルレベルをマッチングする仕組み」です。チャットは非対応なのでこの記事では詳細を割愛します。

Step2. ルーティング設定で優先度と重みを決める

ルーティング設定で、特定のエージェントの集合にチャット要求が到来したときの、その作業の相対優先度とサイズを決めます。

Routing settings

まず、ルーティング優先度については、小さな設定から先に転送されます。例えば、例えば、先のシナリオでエージェントAがテクニカルサポートのキューにも所属することになり、業務単位2のルーティング設定の方が優先度の値が小さいとした場合、エージェントAには料金のチャット要求が先に転送されます。

ルーティングモデルでは、同時対応中のチャット会話が少ないエージェントから割り当てる(=対応中件数が最小)か、空きの多いエージェントから割り当てる(=対応余力が最大)かを選択します。

作業項目サイズでは、チャット1件あたりの重み付け(サイズ)を指定します。先のシナリオに当てはめると、料金の問い合わせ用に業務単位2のルーティング設定と、それ以外の問い合わせ用に業務単位1のルーティング設定を作成します。

組み込みサービスの設定

組み込みサービスでは、Web サイトに設置するチャット起動 UI のブランディング設定や、フォームの設定を行うことができます。

スニペットのカスタマイズ

チャットウィンドウの大きさや背景画像など、設定画面にはない追加のブランディング設定を、コードスニペットのカスタマイズで行うことができます。対応しているパラメータの一覧はHelpを参照してください。なおパラメータは embedded_svc.init()の手前に記載する必要があります。

var initESW = function(gslbBaseURL) {
   //この位置に追加の設定を記載する
   embedded_svc.settings.widgetHeight = '680'; //例
   embedded_svc.init(
   //中略
   )
}

Experience Cloud でもこのスニペットのカスタマイズが利用可能です。以下のようなフォーマットで JavaScript ファイルを静的リソースとして保存し、エクスペリエンスビルダー上の設定から参照してください。プロパティが embedded_svc.settings ではなく embedded_svc.snippetSettingsFile となることに注意してください。

window._snapinsSnippetSettingsFile = (function() {
    //ここに設定
    embedded_svc.snippetSettingsFile.autoOpenPostChat = true; //例
})();

フォームの内容に応じたチャットボタンの切り替え

組み込みサービススニペットの directToButtonRouting を用いると、事前フォームの入力内容に応じてチャットボタンを切り替えることができます。これは、配列 prechatFormData を受け取り、チャットボタンのレコード ID を返す関数です。

embedded_svc.settings.directToButtonRouting = function(prechatFormData) {
    if (prechatFormData[1].value === "Billing") {
        return "5736g000000XXXXXXX";
    } else if (prechatFormData[1].value === "Technical_Support") {
        return "5736g000000YYYYYYY";
    }
    return "5736g000000ZZZZZZZ";
}

prechatFormData には、フォームの値の後ろに extraPrechatInfo の値も入りますので、これを用いてチャットボタンを切り替えることもできます。

現状、素直にこの仕組みを利用しようとすると、チャットボタンの ID をハードコードする必要がある(残念な仕様ですね…😭)ため、環境間の差異に注意してください。API コールでチャットボタンの ID を取得する処理を実装しても良いですが、ボタンの ID は SOQL (e.g., SELECT Id, DeveloperName FROM LiveChatButton) で取得可能ですので、開発に自信のない方は、事前に SOQL を準備しておいて張り替えるような運用でも良いでしょう。

その他発展的な機能

カスタム事前フォームの作成

標準機能で、取引先責任者やケースを検索・作成する事前フォームを設定することができますが、Lightning Web Component を用いてカスタムの事前フォームを作成することができます。例えば連動項目にある選択リストは標準の事前フォームでは機能しませんので、これに対応する事前フォームを作成してみましょう。以下は、取引先責任者のメールアドレス、ケースの種別、ケースのカスタム選択リスト項目(SubType__c, 種別の連動項目) の3つをフォームに表示する例です。

<template>
    <div class="slds-p-around_medium">
        <template for:each={fields} for:item="field">
            <div key={field.name}>
                <template if:true={field.isPicklist}>
                    <lightning-combobox key={field.name} name={field.name} label={field.label} value={field.value} required={field.required} options={field.options} onchange={onPicklistChange}></lightning-combobox>
                </template>
                <template if:false={field.isPicklist}>
                    <lightning-input key={field.name} name={field.name} label={field.label} value={field.value} max-length={field.maxLength} required={field.required}>           
                    </lightning-input>
                </template>    
            </div>
        </template>
        <div class="slds-p-around_medium">
            <lightning-button label="チャットを開始" onclick={handleStartChat}>
            </lightning-button>
        </div>
    </div>
</template>
import BasePrechat from 'lightningsnapin/basePrechat';
import { api, track, wire } from 'lwc';
import { getObjectInfo } from 'lightning/uiObjectInfoApi';
import { getPicklistValues } from 'lightning/uiObjectInfoApi';
import CASE_OBJECT from '@salesforce/schema/Case';
import TYPE_FIELD from '@salesforce/schema/Case.Type';
import SUBTYPE_FIELD from '@salesforce/schema/Case.SubType__c';

export default class PrechatDemo extends BasePrechat {
    @api prechatFields;
    @track fields;
    subTypeFieldData;
    nameList;

    connectedCallback() {
        this.fields = this.prechatFields.map(field => {
            const { 
                label, name, value, required, maxLength,
                isPicklist = (field.type === 'inputSelect'), 
                options = (field.name !== SUBTYPE_FIELD.fieldApiName) ? field.picklistOptions : undefined
                } = field;
            return { label, name, value, required, maxLength, isPicklist, options };
        });
        this.nameList = this.fields.map(field => field.name);
    }

    @wire(getObjectInfo, { objectApiName: CASE_OBJECT })
    caseInfo;

    @wire(getPicklistValues, { recordTypeId: '$caseInfo.data.defaultRecordTypeId', fieldApiName: SUBTYPE_FIELD })
    subTypeFieldInfo({ data, error }) {
        if (data) {
            this.subTypeFieldData = data;
        } 
    }

    onPicklistChange(event) {
        //制御項目の選択リスト値変更以外は無視
        if(event.target.name !== TYPE_FIELD.fieldApiName) return;
        //連動項目の位置を特定
        const subTypeFieldIndex = this.fields.findIndex((field) => {
            return (field.name === SUBTYPE_FIELD.fieldApiName);
        });
        //連動項目の選択リスト値を絞り込み
        const controllerValueIndex = this.subTypeFieldData.controllerValues[event.target.value];
        this.fields[subTypeFieldIndex].options = this.subTypeFieldData.values.filter(
            option => option.validFor.includes(controllerValueIndex)
        );
    }

    handleStartChat() {
        this.template.querySelectorAll("lightning-input, lightning-combobox").forEach(input => {
            this.fields[this.nameList.indexOf(input.name)].value = input.value;
        });
        if (this.validateFields(this.fields).valid) {
            this.startChat(this.fields);
        } else {
            //エラー処理
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
  <apiVersion>48.0</apiVersion>
  <isExposed>true</isExposed>
  <targets>
    <target>lightningSnapin__PreChat</target> <!--これがないと組み込みサービスの設定画面でコンポーネントを選択できない-->
  </targets>
</LightningComponentBundle>

ポイント

  • カスタムコンポーネントを作成する場合も、組み込みサービスリリースの設定で表示項目を選択しておく必要があり、カスタムコンポーネントではその項目だけを扱うことができます。
  • 変数 prechatFields に組み込みサービスリリース設定で選択された項目が渡されます。これは Object の配列で、各項目は以下のように表現されます。選択リスト項目の場合は、キー picklistOptions に選択リスト値が含まれます。
{
  "type":"inputEmail",
  "name":"Email",
  "label":"メール",
  "required":false,
  "readOnly":false,
  "className":"Email slds-style-inputtext",
  "maxLength":80
}
  • 事前フォームを実装する LWC は BasePrechat を extends します。
  • value を含む、prechatFields の要素と同じような Object の配列を fields として新たに定義し、これをループすることでフォーム要素を描画します。
  • lightning/uiObjectInfoApi を用いて連動関係を取得します。
  • startChat() メソッドを呼び出す前に必ず validateFields() メソッドを呼び出す必要があります。

バックグラウンドでチャットにパラメータを渡す

フォームの入力項目とせずにパラメータを Salesforce に渡したい場合があります。例えば、訪問者が表示しているWeb サイトのページ情報をエージェントに表示する、Web サイトから会員 ID を顧客紐付けのキーとしてトランスクリプトに保存する、など。これは、組み込みサービスのスニペットで extraPrechatFormDetails を用いることで実装できます。以下は固定の番号をエージェントに表示し、トランスクリプトのカスタム項目に保存する例です。

embedded_svc.settings.extraPrechatFormDetails = [{
        "label": "お客さま番号",
        "value": "123456",
        "displayToAgent": true,
        "transcriptFields": ["CustomerNumber__c"]
}];
スクリーンショット 2020-02-22 23.14.39.png

同じような方法で、extraPrechatInfo を用いるとレコードの検索や新規作成が可能です。詳細は開発者ガイド(英語) を参照してください。

補足

  • Enterprise Edition 以下の場合、チャットの利用にはアドオンのライセンス(Digital Engagement)が必要になります。
  • 設定名が最近変更されましたので、Web 上のドキュメントを探す場合は注意してください。
    • 旧) Live Agent → 新) チャット
    • 旧) Snap-ins → 新) 組み込みサービス

チャットの標準オブジェクト

チャットで主に利用されるオブジェクトは以下の通りです。

  • チャットの訪問者 (LiveChatVisitor)
    • チャット開始時に訪問者の Cookie に基づき作成・検索されトランスクリプトから参照されます。
  • チャットのセッション (LiveChatSession)
    • エージェントがオンライン〜オフラインになる度に作成されます。エージェントの活動のレポートに使用できます。
  • チャットのトランスクリプト (LiveChatTranscrtipt)
    • チャット会話を管理するオブジェクトです。会話内容はロングテキストに保存されます。
  • チャットのトランスクリプトイベント (LiveChatTranscriptEvent)
    • チャット会話中に発生する特定のイベント毎に作成されます。詳細はオブジェクトリファレンスの Type 項目を参照 してください。このオブジェクトは意外とストレージ容量を消費するので注意してください。必要に応じて古いレコードは削除・アーカイブしても良いでしょう。

標準機能ではできないこと

  • エージェントが支援フラグを挙げたときに、SV へオムニスーパバイザ以外の箇所に通知する (タブを点滅させるなど)
    • 現状はオムニスーパバイザを開いている状態でないと気がづきません。
    • トランスクリプトイベントで支援フラグが立ったことを判定できますので、Apex トリガから通知用のプラットフォームイベントを発火して非表示のユーティリティ項目で Subscribe するような開発を行えば、(かなり無理くりですが) 一応実装はできそうです。
  • エージェントから顧客へ画像やファイルを転送する
    • 顧客からのファイル添付は標準機能で実現可能ですが、逆はサポートされていません。

参考リンク

  1. 主にインテグレーションやモバイルアプリ等の目的で、Live Agent REST APIを用いてチャットを開始・制御することもできますが、ここでは省略します。

19
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
19