背景と適用シナリオ
現代のビジネス環境において、顧客との接点は急速に多様化しています。顧客は、従来の電話やメールだけでなく、Webサイト上のチャットやモバイルアプリ内のメッセージングといった、より手軽で即時性の高いコミュニケーションチャネルを求めています。この期待に応えることが、顧客満足度の向上とロイヤルティの確立に不可欠です。このような顧客とのデジタルな繋がりを強化・最適化する戦略的アプローチを Digital Engagement (デジタルエンゲージメント) と呼びます。
Salesforce は、この Digital Engagement を実現するための強力なプラットフォームを提供しており、その中核をなす機能の一つが Messaging for In-App and Web (MIW) です。MIW は、Webサイトやモバイルアプリケーションに、Salesforce Service Cloud と直結した高機能なメッセージング機能を簡単に組み込むことを可能にします。これにより、顧客は使い慣れたインターフェースで企業と対話でき、企業側はエージェントが Service Console 上で顧客情報と連携しながら、効率的に対応できるというメリットがあります。
開発者の視点から見ると、MIW は単なるチャットウィジェットではありません。JavaScript SDK を通じて柔軟なカスタマイズが可能であり、既存の Web アプリケーションのユーザー体験を損なうことなく、シームレスに統合できる点が大きな魅力です。例えば、以下のようなシナリオでその真価を発揮します。
- Eコマースサイトでの購入サポート: 顧客が商品ページで疑問を持った際、ページを離れることなくチャットを開始し、商品の詳細や在庫についてリアルタイムで質問できます。
- 金融機関のモバイルアプリでの本人確認: 複雑な手続きについて、顧客がアプリ内のメッセージングでオペレーターのサポートを受けながら進めることができます。
- SaaSプロダクトのオンボーディング支援: 新規ユーザーが製品の使い方でつまずいた際、アプリケーション内から直接サポートチームに問い合わせ、迅速な解決を図ることができます。
本記事では、Salesforce 開発者として MIW の導入を検討している方々を対象に、その技術的な仕組みから具体的な実装方法、そして運用上の注意点までを、コード例を交えながら詳細に解説していきます。
原理説明
Messaging for In-App and Web (MIW) のアーキテクチャは、クライアントサイド(顧客のブラウザやアプリ)と Salesforce バックエンドの連携によって成り立っています。開発者が理解すべき主要な構成要素は以下の通りです。
1. lightningsdk.js (JavaScript SDK)
MIW の中核をなすクライアントサイドのライブラリです。この SDK を Web ページに読み込むことで、Salesforce との通信チャネルを確立し、メッセージングUIの制御やイベントのハンドリングを行うための API が提供されます。開発者はこの SDK のメソッドを呼び出すことで、会話の開始、終了、事前チャットフォームのデータ送信などをプログラム的に制御できます。
2. Embedded Service Deployment (組込みサービスリリース)
Salesforce の設定画面で作成する構成レコードです。どのメッセージングチャネル(例えば、特定の Facebook Messenger アカウントや、カスタムの Web チャットなど)を使用するか、チャットウィンドウのデザイン、事前チャットフォームの項目などを定義します。ここで生成されるコードスニペット(JavaScriptのコード断片)には、デプロイメントIDや組織IDといった、SDK が Salesforce 組織を特定するために必要な情報が含まれています。
3. Connected App (接続アプリケーション)
MIW は、安全な通信を確立するために Salesforce の Connected App フレームワークを利用します。Web サイトが Salesforce と通信する際の認証・認可の仕組みを提供し、指定されたドメインからのリクエストのみを受け付けるように CORS (Cross-Origin Resource Sharing) 設定もここで行います。MIW の設定プロセス中に自動的に作成されるため、通常は開発者が手動で作成する必要はありませんが、その存在と役割を理解しておくことは重要です。
4. Salesforce Core Platform
バックエンドでは、Service Cloud が中心的な役割を担います。顧客との会話が始まると、MessagingSession (メッセージングセッション) と MessagingEndUser (メッセージングエンドユーザー) といった新しいオブジェクトのレコードが作成されます。エージェントは Service Console 上でこれらのセッションを受け入れ、Omni-Channel (オムニチャネル) 機能によって適切なスキルを持つエージェントに自動的にルーティングされます。会話の履歴はすべて Salesforce 上に記録され、顧客の連絡先レコードやケースレコードと関連付けることが可能です。
全体のフローは以下のようになります。
- ユーザーが MIW が組み込まれた Web ページを訪問します。
- ページに埋め込まれた JavaScript スニペットが `lightningsdk.js` を非同期で読み込みます。
- SDK は Embedded Service Deployment の設定情報を元に Salesforce への接続を初期化します。
- ユーザーがチャット開始ボタンをクリックすると、開発者が実装した `lightningsdk.startConversation()` メソッドが呼び出されます。
- Salesforce バックエンドで MessagingSession レコードが作成され、Omni-Channel を通じて待機中のエージェントにルーティングされます。
- エージェントがセッションを受け入れると、ユーザーとエージェント間でリアルタイムのメッセージングが開始されます。
このアーキテクチャにより、開発者はフロントエンドの実装に集中しつつ、バックエンドの堅牢な Salesforce プラットフォームの恩恵を最大限に受けることができるのです。
示例代码
ここでは、MIW をカスタムの Web ページに組み込むための基本的な JavaScript コードを示します。このコードは、Salesforce の「組込みサービスリリース」設定ページで生成されるスニペットをベースに、より実践的なイベントハンドリングを追加したものです。
前提: Salesforce の設定で「メッセージング設定」と「組込みサービスリリース」が完了しており、コードスニペットが取得済みであること。
以下の HTML ファイルを作成し、`YOUR_` から始まるプレースホルダーをご自身の環境の値に置き換えてください。
<!DOCTYPE html> <html> <head> <title>MIW Developer Demo</title> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" /> </head> <body> <h2>Messaging for In-App and Web 開発者デモ</h2> <p>下のボタンをクリックして、サポートとの会話を開始します。</p> <button id="startChat">サポートとチャットを開始</button> <!-- Salesforceから提供されるコードスニペットをここに貼り付け --> <script type='text/javascript'> // この関数は、lightningsdk.jsがロードされ初期化された後に呼び出されるコールバックです。 function initESW(gslbBaseURL) { embedded_svc.settings.displayHelpButton = false; // 標準のヘルプボタンは非表示にし、カスタムボタンで制御します。 embedded_svc.settings.language = 'ja'; // UIの言語を日本語に設定 // 会話を開始する前に顧客情報を渡すための設定(事前チャット) embedded_svc.settings.prechatBackgroundCallback = function(prechatFields) { // 例として、ログイン中のユーザー情報などを取得して渡すことができます。 // ここでは固定値を渡していますが、実際にはAPIから取得した動的な値を使用します。 var fields = [ { "label": "FirstName", "value": "太郎", "transcriptFields": ["FirstName__c"], // トランスクリプトフィールドにマッピング "displayToAgent": true }, { "label": "LastName", "value": "山田", "transcriptFields": ["LastName__c"], "displayToAgent": true }, { "label": "Email", "value": "taro.yamada@example.com", "transcriptFields": ["Email__c"], "displayToAgent": true } ]; // 取得した情報をコールバックに渡します。 embedded_svc.prechatAPI.setHiddenPrechatFields(fields); }; // SDKの初期化処理 embedded_svc.init( 'https://YOUR_SALESFORCE_ORG_URL.my.salesforce.com', 'https://YOUR_COMMUNITY_SITE_URL.force.com/community', gslbBaseURL, 'YOUR_ORGANIZATION_ID', 'YOUR_DEPLOYMENT_NAME', { baseLiveAgentContentURL: 'https://c.la2-c2-ukm.salesforceliveagent.com/content', deploymentId: 'YOUR_DEPLOYMENT_ID', buttonId: 'YOUR_BUTTON_ID', baseLiveAgentURL: 'https://d.la2-c2-ukm.salesforceliveagent.com/chat', eswLiveAgentDevName: 'YOUR_ESW_DEV_NAME', isOfflineSupportEnabled: false } ); } // コードスニペットの残りの部分 if (!window.embedded_svc) { var s = document.createElement('script'); s.setAttribute('src', 'https://YOUR_SALESFORCE_ORG_URL.my.salesforce.com/embeddedservice/5.0/esw.min.js'); s.onload = function() { initESW(null); }; document.body.appendChild(s); } else { initESW('https://service.force.com'); } </script> <!-- スニペットここまで --> <!-- カスタムボタンとSDKを連携させるためのJavaScript --> <script type='text/javascript'> document.addEventListener("DOMContentLoaded", function() { const startChatButton = document.getElementById('startChat'); // `lightningsdk` オブジェクトが利用可能になるのを待つ // `esw.min.js` のロードは非同期のため、このチェックは重要です。 const intervalId = setInterval(() => { if (window.embedded_svc && window.embedded_svc.liveAgentAPI) { clearInterval(intervalId); // オブジェクトが見つかったらインターバルを停止 // カスタムボタンにクリックイベントリスナーを追加 startChatButton.addEventListener('click', function() { console.log('チャット開始ボタンがクリックされました。'); // lightningsdk の API を使用して会話を開始 // このメソッドは Promise を返します。 embedded_svc.liveAgentAPI.startChat() .then(function() { console.log("会話が正常に開始されました。"); startChatButton.disabled = true; // 会話中はボタンを無効化 }) .catch(function(error) { console.error("会話の開始に失敗しました。", error); }); }); // 会話が終了したときのイベントを捕捉 window.addEventListener("onchatended", function(e) { console.log("会話が終了しました。"); startChatButton.disabled = false; // ボタンを再度有効化 }); } }, 100); // 100ミリ秒ごとにチェック }); </script> </body> </html>
コードの解説
- `initESW` 関数: この関数は `esw.min.js` がロードされた後に実行される中心的な初期化関数です。
- `embedded_svc.settings.displayHelpButton = false;`: Salesforceが標準で表示するフローティングアクションボタンを非表示にしています。これにより、ページデザインに合わせた独自のUI(この例では `startChat` ボタン)でチャットを開始できます。
- `embedded_svc.settings.prechatBackgroundCallback`: これは非常に強力な機能で、会話が始まる「前」にバックグラウンドで顧客情報を Salesforce に送信します。この例ではハードコードされた値を渡していますが、実際のアプリケーションでは、Webサイトのログイン情報やクッキーからユーザーIDを取得し、API経由で詳細な顧客情報を取得して設定することが一般的です。これにより、エージェントは誰からの問い合わせかを即座に把握できます。
- `embedded_svc.init(...)`: SDK の本体を初期化します。引数には組織IDやデプロイメントIDなど、Salesforce 環境に固有の値が渡されます。これらの値は組込みサービスリリースの設定ページからコピーします。
- カスタムスクリプト部分: `DOMContentLoaded` イベント内で、カスタムの「チャット開始」ボタンにクリックイベントを追加しています。`window.embedded_svc` オブジェクトが利用可能になるまで待機する処理は、非同期読み込みに起因するエラーを防ぐための重要なポイントです。
- `embedded_svc.liveAgentAPI.startChat()`: これが会話を開始するメインの API コールです。Promise を返すため、`.then()` で成功時の処理、`.catch()` で失敗時の処理を記述できます。
- `window.addEventListener("onchatended", ...)`: SDK は会話のライフサイクルに応じてカスタムイベントを発行します。`onchatended` は顧客またはエージェントが会話を終了したときに発火します。このイベントをリッスンすることで、UIの状態を更新する(例:ボタンを再度有効化する)といった後処理が可能です。
注意事項
MIW を実装・運用する際には、以下の点に注意する必要があります。
1. 権限 (Permissions)
・ゲストユーザープロファイル: Webサイトの未ログインユーザーがチャットを利用する場合、その通信はサイトのゲストユーザープロファイルの権限で行われます。このプロファイルに対して、MIW が使用する Apex クラスへのアクセス権を付与する必要があります。設定が不十分な場合、チャットの接続に失敗します。
・エージェントの権限セット: エージェントとなるユーザーには、「メッセージングユーザー」権限を含む権限セットを割り当てる必要があります。また、Omni-Channel で「在席」ステータスになれるように設定されていることも確認してください。
2. API 制限 (API Limits)
MIW 自体は、Salesforce の日々の API コールリミット(例: REST/SOAP API のコール数)を直接消費するわけではありません。しかし、同時に対応可能なセッション数にはエディションやライセンスに基づく制限が存在します。また、Einstein Bots (アインシュタインボット) を連携させる場合、ボットのセッション数にも制限があるため、大規模な導入を計画する際は、自社の Salesforce 契約内容を確認することが重要です。
3. エラー処理 (Error Handling)
サンプルコードで示したように、`startChat()` のような非同期メソッドは Promise の `.catch()` を使って適切にエラーハンドリングを行うべきです。例えば、Salesforce 側でメンテナンス中であったり、ネットワークの問題で接続に失敗した場合、ユーザーに「現在サポートに接続できません。しばらくしてからお試しください。」といったフィードバックメッセージを表示するUIを実装することが、良いユーザー体験に繋がります。SDK が発するイベント(例: エラーイベント)を監視し、堅牢なエラー処理を組み込むことを推奨します。
4. セキュリティ (Security)
・CORS (Cross-Origin Resource Sharing): MIW をホストする Web サイトのドメインは、Salesforce の「CORS 許可リスト」に正確に登録されている必要があります。`https://www.yourcompany.com` のようにプロトコルまで含めて完全なドメインを登録してください。登録がない場合、ブラウザの同一オリジンポリシーにより、SDK から Salesforce へのリクエストがブロックされます。
・事前チャットで渡す情報: `prechatBackgroundCallback` で渡す情報は、エージェントの対応効率を上げるために非常に有用ですが、センシティブな個人情報を安易にクライアントサイドの JavaScript にハードコードしないよう注意が必要です。サーバーサイドで認証・認可を行った上で、必要な情報のみをクライアントに渡し、SDK に設定するようにしてください。
まとめとベストプラクティス
Salesforce の Messaging for In-App and Web (MIW) は、開発者にとって非常に強力で柔軟なツールです。単にチャット機能を追加するだけでなく、Salesforce の CRM データと深く連携した、パーソナライズされた顧客体験を構築することが可能になります。
最後に、MIW を実装する上でのベストプラクティスをいくつか紹介します。
- カスタムUIとの調和: 標準のヘルプボタンに頼らず、Webサイトのデザインに合わせた独自のボタンやエントリーポイントを用意することで、ユーザー体験の一貫性を保ちます。SDK の API を活用すれば、UIの制御は自由自在です。
- 事前チャットの戦略的活用: 顧客が誰であるか、どのページを見ていたか、カートに何が入っているかといったコンテキスト情報を `prechatBackgroundCallback` を通じてエージェントに提供しましょう。これにより、エージェントは「どのようなご用件でしょうか?」からではなく、「商品ABCについてですね。ご不明な点はございますか?」といった、より的確な会話を始めることができます。
- Einstein Bots との連携: よくある質問 (FAQ) への自動応答や、エージェントに繋ぐ前の情報収集は Einstein Bots に任せることで、エージェントの負荷を大幅に軽減し、24時間365日の一次対応を実現できます。
- 段階的な導入とテスト: まずは限定されたページや特定のユーザーセグメントに対して機能をリリースし、フィードバックを収集しながら改善サイクルを回すことをお勧めします。特に、本番環境にデプロイする前には、必ず Sandbox 環境で、CORS の設定やゲストユーザーの権限を含めたすべてのシナリオを徹底的にテストしてください。
MIW を正しく理解し、その機能を最大限に活用することで、開発者は顧客エンゲージメントを次のレベルへと引き上げる、価値あるソリューションを構築することができるでしょう。