訪問者の本人確認と状況情報の受け渡し
ReactiveChat('identify')でログイン済みユーザーを通知し、サーバーでHMAC-SHA256のuserHashに署名する方法、シークレットの更新、商品やカートなどの構造化したページ情報の受け渡し。
Webサイトが訪問者を把握しているなら、チャットにも伝えてください。オペレーター画面に「訪問者4f2a」の代わりに名前が表示され、顧客データや顧客ポータルなどの機能が利用可能になります。
原則は、ブラウザーの情報は証明にならないということです。ページがidentifyで申告する内容は、誰でもコンソールで偽装できます。ブラウザーに渡らないシークレットを使い、運営側のサーバーが計算した署名がある場合だけ、ユーザーを確認済みと見なします。
ブラウザーでの呼び出し
ReactiveChat('identify', {
userId: '4711',
email: 'kim@example.com',
name: 'Kim Berger',
userHash: '9c1f…',
exp: 1792503600
});
- userId(文字列、推奨) – 運営側の永続的なユーザーID。メールアドレスや、変わる可能性のある連番ではありません。
- email(文字列、任意) – オペレーター画面に表示します。署名に含めた場合だけ確認済みになります(下記)。
- name(文字列、任意) – オペレーター画面の表示名。
- userHash(文字列、本人確認には必須) – サーバーで計算した16進数64文字。
- exp(整数、推奨) – ハッシュの有効期限。Unix秒で、最大24時間先です。
他のフィールドは破棄します。identifyはウィジェットの読み込み前にも呼べます。キューに入り、早期読み込みは発生させません。接続時に値を送り、すでに接続済みなら即座に送ります。
シークレット
アカウントのプロジェクト → 本人確認で、プロジェクトのシークレットを生成します(必要権限:プロジェクトの編集)。16進数64文字で、全文の表示は1回だけ、以降はマスクします。サーバーの環境に保存し、ブラウザーのスクリプト、アプリ、リポジトリには絶対に置かないでください。
計算上の重要事項: HMACキーは、表示された64文字の文字列そのものです。デコードしたバイト列ではありません。
署名を計算する
userHash = hex( HMAC_SHA256( secret, userId + "." + exp ) )
小文字の16進数64文字です。メールアドレスも確認する場合:
userHash = hex( HMAC_SHA256( secret, userId + "." + exp + "." + email ) )
メールアドレスが確認済みになるのは、2つ目の形式だけです。expが必要です。
PHP:
<?php
$geheim = getenv('RC_IDENT_SECRET'); // 64 hex characters from the account
$userId = (string) $kunde->id;
$exp = time() + 3600; // at most 24 h
$userHash = hash_hmac('sha256', $userId . '.' . $exp, $geheim);
?>
<script nonce="<?= $cspNonce ?>">
ReactiveChat('identify', {
userId: <?= json_encode($userId) ?>,
userHash: <?= json_encode($userHash) ?>,
exp: <?= (int) $exp ?>
});
</script>
Node.js:
const crypto = require('crypto');
function rcIdentitaet(kunde) {
const userId = String(kunde.id);
const exp = Math.floor(Date.now() / 1000) + 3600;
const userHash = crypto.createHmac('sha256', process.env.RC_IDENT_SECRET)
.update(userId + '.' + exp)
.digest('hex');
return { userId, userHash, exp };
}
Python:
import hmac, hashlib, os, time
def rc_identitaet(kunde_id: str) -> dict:
exp = int(time.time()) + 3600
msg = f"{kunde_id}.{exp}".encode()
key = os.environ["RC_IDENT_SECRET"].encode() # the hex string as text
return {"userId": kunde_id, "exp": exp,
"userHash": hmac.new(key, msg, hashlib.sha256).hexdigest()}
メールアドレスを含む場合(PHP):
$userHash = hash_hmac('sha256', $userId . '.' . $exp . '.' . $email, $geheim);
アドレスは、identifyに渡すものと完全に同じ形で署名してください。
インラインスクリプトを使わない方法(厳格なCSP)
Content Security Policyがインラインスクリプトを許可しない場合、値をデータとして出力し、独自のスクリプトファイルからidentifyを呼び出します。
<meta name="rc-ident" content='{"userId":"4711","userHash":"9c1f…","exp":1792503600}'>
// /js/chat-ident.js
var m = document.querySelector('meta[name="rc-ident"]');
if (m) { ReactiveChat('identify', JSON.parse(m.content)); }
シングルページアプリでは、ログイン後にfetchでサーバーから3つの値を取得します。
サーバーの検証内容
expが整数(Unix秒)で、未来かつ24時間以内(許容差5分を加算)であること。- ハッシュが
userId + "." + exp(またはメール付きの形式)と一致すること。ハッシュの大文字は許容します。 - 比較は定時間で行います。
有効なハッシュとexpがあるユーザーを、確認済みで有効期限内と見なします。その場合だけ、顧客データと顧客ポータルを利用できます。
expのない旧形式: userHash = HMAC_SHA256(secret, userId)も確認済みとして受け付けますが、有効期限内とは見なしません。会話履歴やオペレーター画面の表示には十分ですが、顧客データには使えません。既存の連携はexp付きの形式に切り替えてください。
検証に失敗した場合
チャットは匿名で動作し続けます。ウィジェットは、detail.reasonに理由を持つauth_failedエラーを受け取ります。
- no_hash –
userHashがありません。 - no_secret – プロジェクトにシークレットがありません。
- bad_exp –
expが秒単位の有効な整数ではありません。よくある原因はミリ秒での指定です。 - expired –
expが過去です。ページを長時間開いているか、サーバーの時計が誤っています。 - exp_too_far –
expが24時間を超えて先です。 - bad_hash – ハッシュが一致しません。シークレットや順序の誤り、
userIdを文字列ではなく数値として署名、メールアドレスの表記の違いなどです。
開発者ツールのNetworkタブでは、WebSocket接続のerrorフレームに理由があります。init_ok.identityにはverifiedとreasonを表示します。
「確認済み訪問者のみ許可」という設定はありません。未確認の訪問者は常に匿名でチャットします。
シークレットをローテーションする
- 新しいシークレットを生成: 以前のものはさらに24時間有効です。その間にサーバーに新しいものを設定してください。
- 削除: 両方を直ちに無効にします。新しいシークレットを設定するまで、全ユーザーが未確認になります。
ユーザーの切り替えとログアウト
- SPAでアカウントを切り替えた場合など、別のユーザーで
identifyを呼ぶと、入力中の下書きを前のユーザーのものと分離します。 - 専用のログアウトコマンドはありません。本人情報は現在のページ表示にだけ適用するため、ログアウト後は
identifyなしのページを配信します。会話と訪問者IDはブラウザーに残ります。共有端末で何も表示したくない場合、訪問者がウィジェットから自分のデータを削除できます。
状況情報を渡す
本人情報に加え、表示中の商品やカートの内容など、現在の状況をアシスタントやチームに伝えられます。trackを使用します。
ReactiveChat('track', 'warenkorb', {
page_type: 'cart',
cart_value: 129.80,
cart_items: 3,
currency: 'EUR'
});
次のフィールドだけを受け取り、それ以外は破棄します。
- ページ:
url、path、title、referrer、page_type、landing_path - 商品:
product_id、variant_id、category、price、currency、in_stock - カート:
cart_value、cart_items - キャンペーン:
utm_source、utm_medium、utm_campaign、gclid、msclkid、fbclid - シグナル:
intent、intent_confidence、rage_score、scroll_pct、dwell_ms
アドレス、タイトル、リファラー、キャンペーンパラメーターは、ウィジェットがページ変更のたびに自動で記録します。状況情報を送るのは、同意がある場合だけです(プライバシーの連携)。これらのフィールドに個人データを書かないでください。個人データにはidentifyを使います。
モバイルアプリ
アプリでは、WebViewの読み込み後にJavaScriptで本人情報を渡し、アドレスでは渡しません。ここでも、ハッシュはアプリではなくサーバーで計算します。モバイルアプリをご覧ください。
最終更新: