Google メッセージを RCS と Google ウォレットで使用すると、シームレスなチェックイン フローを設計できます。ユーザーはチェックインを完了し、搭乗券を受け取ってから、メッセージ アプリから Google ウォレットに直接追加します。ウォレットに追加されたパスは、フライトの詳細が変更されると自動的に更新されます。ユーザーはスマートフォンで最新の搭乗券にすぐにアクセスできます。
このドキュメントでは、搭乗券を Google ウォレット フローに実装するための技術的な手順について説明します。また、RBM でのスムーズで効率的なチェックイン エクスペリエンスのための設計のヒントを含む会話の例も紹介します。
技術的な実装
搭乗券から Google ウォレットへのフローを実装するには、Google Wallet API と RBM API を使用します。
前提条件
Google Wallet API の使用を開始するには、次の必須の手順に沿って操作します。
- Google ウォレットのパスを作成して配布できるように、ウォレット発行者アカウントに登録します。
- Google Cloud(GCP)プロジェクトをまだ作成していない場合は作成します。
- Google Wallet API を有効にします。
- Google Wallet API を呼び出すために、サービス アカウントとキーを作成します。
- Google Pay and Wallet Console でサービス アカウントを承認します。
- 搭乗券テンプレートを使用して、新しい搭乗クラスを作成します。
Google ウォレット API
搭乗券を作成し、RBM の [Google ウォレットに追加] URL を生成する手順はこちらをご覧ください。
- 必要な認証と承認を行います。
- パス オブジェクトを作成します。
- 署名付き JSON Web Token(JWT)を取得します。エンコードされた JWT の最大長は 2,048 文字です。
- JWT を使用して、[Google ウォレットに追加] URL を生成します。
RBM API
RBM から「Google ウォレットに追加」の提案を送信するには、URL を開くアクションを送信します。メッセージ ペイロードで、次の操作を行います。
text
に「Google ウォレットに追加」と入力します。url
に、Google ウォレットに追加の URL を入力します。
Google ウォレットのアイコンは、候補のラベルに自動的に表示されます。
会話デザイン
このサンプルでは、会話の独自の機能を利用して、ユーザーを完全なチェックイン フローに案内します。自然な会話と豊富な機能(ワンタップによる候補の提示やリッチカードなど)を使用して、ユーザーが目標を達成できるようにする方法を示しています。この場合の目標は、(1)フライトをカスタマイズする、(2)搭乗券を受け取る、(3)空港ですぐにアクセスできるように Google ウォレットに追加する、です。
次に、会話の概要を示します。その後に、設計のヒントとフローの詳細な内訳が続きます。エージェントに同様の設計を実装するには、手順の後のコードサンプルをご覧ください。
設計に関するアドバイス
チェックイン フローを設計する際は、次の原則に留意してください。
- 最初のメッセージが最も重要です。会話の目的を簡単に述べて、ユーザーが関心を持つ理由を説明します。
- 各メッセージでは、情報を小さなまとまりで提供し、ユーザーの応答を促す必要があります。定型返信文と推奨される対応は、ユーザーが次のステップに進むのに役立ちます。
- エージェントは機械的ではなく、迅速に対応する必要があります。ブランドのトーンと一致する言葉を使用します。理想的なブランド担当者が顧客とチャットするとしたら、どのような対応をするでしょうか。
- 人は特別感を味わいたいものです。ユーザーのフライト履歴に基づいて座席や食事を提案することで、チェックイン エクスペリエンスをパーソナライズできます。
- リッチカードとカルーセルを使用すると、会話がよりダイナミックになります。これらのツールを使用して、お客様がオプションの中から選択するのに役立つ画像や詳細情報を共有します。
- 良い会話は良い結びで終わる。搭乗券を送信する前に、ユーザーのチェックインの詳細を確認します。親しみを込めて送り出すことで、人間味を加えます。
チェックイン フロー
エージェントは、フライトのチェックインが開始されたことをお客様に伝えます。
コードサンプル
const suggestions = [ { reply: { text: '⚡ Check in', postbackData: 'checkIn', }, }, { reply: { text: '⏰ Remind me later', postbackData: 'remindMe', }, }, { reply: { text: '✈️ View my flight details', postbackData: 'flightDetails', }, }, { reply: { text: '🔀 Change my flight', postbackData: 'flightChange', }, }, ]; const params = { messageText: 'Check-in for your flight', messageDescription: '👏 Happy morning, Jo! Check-in is now open for your flight from London to Mumbai on ' + getFlightTime() + ' at 2:00PM. What would you like to do? ', msisdn: phoneNumber, suggestions: suggestions, imageUrl: getImageUrl('fly.png'), height: 'MEDIUM', }; rbmApiHelper.sendRichCard(params);
ユーザーが返信候補をタップしてチェックインします。
エージェントは、チェックイン プロセスの見通しをお客様に伝えます。
コードサンプル
const params = { messageText: "OK, great. It's just 3 simple steps to check in. Here's the first step to get you onboard:", msisdn: msisdn, }; let self = this; rbmApiHelper.sendMessage(params, function (response, err) { self.sendPolicyImage(msisdn); });
エージェントは、安全に関するポリシーに同意するようお客様に依頼します。
コードサンプル
const suggestions = [ { reply: { text: 'Yes, I agree', postbackData: 'policy_agree', }, }, { reply: { text: "No, I don't agree", postbackData: 'policy_nack', }, }, ]; const params = { messageText: 'Baggage safety policy', messageDescription: 'To help us ensure a safe flight, please review our safety policy and let us know you agree', msisdn: msisdn, suggestions: suggestions, imageUrl: getImageUrl('policyImage.png'), height: 'MEDIUM', orientation: 'HORIZONTAL', thumbnailImageAlignment: 'LEFT', }; rbmApiHelper.sendRichCard(params);
ユーザーが候補の返信をタップして同意します。
エージェントはユーザーにお礼を述べ、次の手順を説明します。
コードサンプル
const params = { messageText: "Thank you - A safe passenger is a happy passenger! Here's the next step:", msisdn: msisdn, }; let self = this; rbmApiHelper.sendMessage(params, function (response, err) { self.sendPlan(msisdn); });
エージェントは、座席を選択するようお客様に伝えます。
コードサンプル
const suggestions = [ { reply: { text: 'View the seat map', postbackData: 'view_seat_map', }, }, ]; const outerSuggestions = [ { reply: { text: '17A', postbackData: 'seat_17A', }, }, { reply: { text: '17C', postbackData: 'seat_17C', }, }, { reply: { text: '18A', postbackData: 'seat_18A', }, }, { reply: { text: 'Show me more', postbackData: 'more', }, }, ]; const params = { messageText: 'Choose your seat', messageDescription: "It's time to sit back and get comfy! 💺 We've recommended some seats based on your last flight. Choose the one you want, or let us know your preferred seat by typing the number.", msisdn: msisdn, imageUrl: getImageUrl('seatMap.png'), height: 'TALL', orientation: 'VERTICAL', outerSuggestions: outerSuggestions }; rbmApiHelper.sendRichCard(params);
ユーザーが、選択した座席の候補の返信をタップします。
エージェントはお客様の選択を確認します。
コードサンプル
this.seatmap[msisdn] = seat; const params = { messageText: `Seat ${seat}, you got it`, msisdn: msisdn, }; let self = this; rbmApiHelper.sendMessage(params, function(res) { self.sendFoodOptions(msisdn); });
エージェントは、機内食を選択するようお客様に伝えます。
コードサンプル
const params = { messageText: `Now let's talk food 😋 You can pre-order your in-flight meal. Would you be happy with a vegetarian entree or a chicken entree?`, msisdn: msisdn, }; let self = this; rbmApiHelper.sendMessage(params, function(res) { self.sendFoodDetails(msisdn); });
エージェントに食事のオプションが表示されます。
コードサンプル
const cardContents = [ { title: 'Panzanella salad (v)', description: 'Ingredients: bread, lettuce, onions, tomatoes, olive oil', suggestions: [ { reply: { text: 'Choose vegetarian', postbackData: 'veggie', }, }, ], media: { height: 'MEDIUM', contentInfo: { fileUrl: getImageUrl('salad.jpg'), }, }, }, { title: 'Grilled chicken with greens', description: 'Ingredients: chicken, potatoes, peppers, olive oil', suggestions: [ { reply: { text: 'Choose chicken', postbackData: 'chicken', }, }, ], media: { height: 'MEDIUM', contentInfo: { fileUrl: getImageUrl('chicken.png'), }, }, }, ]; const params = { msisdn: msisdn, cardContents: cardContents, }; rbmApiHelper.sendCarouselCard(params);
ユーザーが、選択した食事に対する返信候補をタップします。
エージェントはお客様の選択を確認します。
コードサンプル
const params = { messageText: `Vegetarian it is 💚`, msisdn: msisdn, }; let self = this; rbmApiHelper.sendMessage(params, function (response, err) { self.sendAskConfirmation(msisdn); });
エージェントはチェックインの詳細を要約します。
コードサンプル
let seat = this.seatmap[msisdn]; const suggestions = [ { reply: { text: "Yes, I'm happy with that", postbackData: 'happy', }, }, { reply: { text: 'Change my seat', postbackData: 'change_seat', }, }, { reply: { text: 'Change my meal', postbackData: 'change_meal', }, }, ]; const params = { messageText: "Here's what we've noted down: You've opted for seat " + seat + " and a vegetarian meal. Please confirm your choices.", msisdn: msisdn, suggestions: suggestions }; rbmApiHelper.sendMessage(params);
ユーザーが候補の返信をタップして、チェックインの詳細を確認します。
エージェントがチェックインが完了したことを通知します。
コードサンプル
const params = { messageText: "Hooray! You're now checked in for your flight ☑️ Here's your boarding pass. We're so happy to host you soon!", msisdn: msisdn, }; let self = this; rbmApiHelper.sendMessage(params, function (response, err) { self.sendWalletPass(msisdn); });
エージェントがお客様の搭乗券を送信します。
コードサンプル
this.walletHelper.createFlightPassUrl(this.seatmap[msisdn]).then((url) => { let suggestions = [ { action: { text: 'Add to Google Wallet', postbackData: 'addToWallet', openUrlAction: { url: url }, }, }, ]; const params = { messageText: 'HS123 LHR to BOM\nPassenger: Jo Flow', messageDescription: "We'll keep you up to date! You'll get a notification if your flight details change.", msisdn: msisdn, suggestions: suggestions, imageUrl: getImageUrl('boardingPass.png'), height: 'TALL', orientation: 'HORIZONTAL', thumbnailImageAlignment: 'LEFT', }; rbmApiHelper.sendRichCard(params); });
この横向きリッチカードの画像は、航空会社から提供された完全な機能の搭乗券です。画像には、スキャン可能なバーコードなど、必要な搭乗情報がすべて表示されている必要があります。ユーザーは画像をタップして、Google のメッセージ アプリから搭乗券を表示、スキャンできます。
リッチカードに [Google ウォレットに追加] の候補が表示されます。この候補は、URL を開くアクションをトリガーして Google ウォレット アプリを開きます。ユーザーはウォレットに搭乗券を追加できます。(アプリがユーザーのデバイスにインストールされていない場合は、インストールするように求められます)。パスを Google ウォレットに追加すると、フライトのリマインダーが自動的に届き、フライトの詳細が変更された場合はステータスの最新情報も届きます。
Google ウォレットにパスを追加していないユーザーも、最新の状態に保つ必要があります。リッチカードに表示される搭乗情報の変更について、ユーザーにメッセージを送信します。
ユーザーが提案されたアクションをタップして、パスを Google ウォレットに追加します。
Google ウォレット アプリが開きます。ユーザーがボタンをタップして、パスをウォレットに追加します。
ユーザーがボタンをタップしてパスを表示します。
QR コード付きの搭乗券が表示されます。