obboワークスペースを開く
メニュー

導入ガイド

チャットウィジェットガイド

チャットボットは自社サイト上で訪問者に回答します。設置は2行。それ以外はすべて任意です。

ほとんどのサイトでは第1節から第5節だけで完了します。第6節と第7節は「注文はどこですか?」に答えさせるための一組で、開発者と半日ほどが必要です。残りは各種の上限、方針、うまくいかないときの対処です。

01チャット ID

チャットボットはひとつの ID で識別されます。チャットページの「ホーム」タブにある「サイト用コード」のスニペット内、コピーボタンの横で確認できます。

識別するのはチャットボットだけです。アカウントも API キーも、サイト上のログインもありません。

公開して問題ありません。 ページの HTML に置かれ、誰でも読めます。できるのはチャットボットに質問することだけで、しかも許可したウェブサイト上だけです。

02ウェブサイトに設置する

どのページでも、閉じ body タグの直前に2行を追加します。

<script src="https://www.obbo.me/obbochat.js" async></script>
<div data-obbo-chat="YOUR_CHAT_ID"></div>

スクリプトはページごとに一度読み込まれ、隅にチャットバブルを表示します。サイトのテンプレートに入れれば全ページで有効になります。

まず自分のサイトを許可してください。チャットボットが回答するのは、Brand Center のチャットページの「名前とあいさつ」タブに記載したウェブサイトだけです(最初は Brand Center 自身のウェブサイト)。テスト用のコピーなど、チャットを表示するほかのウェブサイトもすべて追加してください。それ以外のサイトでは丁寧にお断りし、どのサイトが試みたかはチャットページに表示されます。

ページ読み込み後にマークアップを追加する場合 スクリプトが探すのはページ準備完了時の一度だけです。シングルページアプリ、タグマネージャー、同意バナーなどで後からチャットを挿入する場合は、その後に ObboChat.mount() を呼んでください。

03見た目

チャットボットの「外観」設定で見た目を決めてコードをコピーすると、これらの属性とスタイル値が自動で書き込まれます。必須なのはチャット ID だけで、ほかは手で編集することもできます。

<script src="https://www.obbo.me/obbochat.js" async></script>
<div data-obbo-chat="YOUR_CHAT_ID"
     data-obbo-title="Acme Help"
     data-obbo-position="left"
     data-obbo-launcher="Ask us a question"
     style="--obbo-accent: #0f766e; --obbo-accent-text: #ecfdf5; --obbo-bottom: 96px"></div>
属性内容
data-obbo-chatチャット ID。必須 — どのチャットボットを表示するかを決めます。
data-obbo-titleパネルのヘッダーに表示するテキスト。通常は会社名。
data-obbo-theme"dark" でダークパネル。既定はライトです。
data-obbo-position"left" でバブルを左下に配置。既定は右です。
data-obbo-launcherチャットボタンの文字(例:"お気軽にご質問ください")。指定しないとボタンは丸いアイコンになります。
data-obbo-icon"lines" または "dots" で、吹き出しに線や点が入ったチャットボタンになります。既定はシンプルな吹き出しです。
data-obbo-font"site" でページ自身のフォントを使います。既定は標準のシステムフォントです。
styleデザインのスタイル値:ブランドカラー、文字色、端からの距離、角、ウィンドウサイズ。下の「カスタムスタイル」を参照してください。

見た目を変えたら、コードをもう一度コピーしてください。 見た目はコードに含まれているため、置き換えるまでサイトは以前の見た目のままです。

色

「色」の表では 6 つの色を設定します。ブランド、チャットボットの回答、チャットウィンドウのそれぞれについて、背景と文字の色です。ブランドは、チャットボタン、送信ボタン、おすすめの質問、訪問者のメッセージなど、訪問者がタップしたり送ったりするものすべてです。チャットウィンドウはタイトル、入力欄、リンク、注記で、線は文字色を薄くしたものです。枠をタップすると色の選択画面が開きます。「ウェブサイトに合わせる」はブランドカラーを設定し、ロゴの色など、ホームページで見つかった色をどの選択画面でも一番上に表示します。

「開始」でライトかダークを選ぶと、「自動」の色がすべて決まります。「自動」の文字は、背景の上で読みやすい白か黒になります。文字の枠には読みやすさが表示され、読みにくい色を選ぶと選択画面で「自動」に戻せます。

カスタムスタイル

ウィジェットの色・大きさ・距離は、それぞれ専用のスタイル値を読み込みます。チャットの div やサイト独自のスタイルシートで設定すると、コード内の値より優先されます。

[data-obbo-chat] {
  --obbo-accent: #0f766e;
  --obbo-assistant-text: #1f2937;
  --obbo-font: "Inter", sans-serif;
  --obbo-radius: 0;
  --obbo-bottom: 96px;
}
スタイル値変わるもの
--obbo-accent --obbo-accent-textチャットボタンと送信ボタン、おすすめの質問、訪問者のメッセージ、その上の文字
--obbo-panel-bg --obbo-text --obbo-borderチャットウィンドウの背景、文字、入力欄、リンク、線
--obbo-assistant-bg --obbo-input-bg回答の吹き出しと入力欄
--obbo-visitor-text --obbo-assistant-text訪問者のメッセージとチャットボットの回答の文字色
--obbo-radius --obbo-launcher-radius --obbo-chip-radius角の丸み(画面、ボタン、回答ボタン)
--obbo-font --obbo-font-size書体と文字の大きさ
--obbo-width --obbo-height開いたチャット画面の大きさ
--obbo-bottom --obbo-side下端と選んだ側の端からの距離
--obbo-shadow --obbo-z影と、どの要素より前面に出るか

変わらないもの

パネル自身の言葉(あいさつ、送信ボタン、評価の依頼)は現在は英語で、レイアウトはこちらで決めています。マークアップをすべて自分で作りたい場合は、下のヘッドレスエンジンで独自の画面を作ってください。チャットボットは同じまま、HTML と CSS はあなたのものです。

回答の言語はひとつです。 チャットボットは、訪問者がどの言語で書いても、あなたのBrand Centerの言語で回答します。翻訳ではなく、会社自身の言葉で話すためです。

04独自のインターフェースを作る

バブルは省略できます。同じスクリプトがヘッドレスエンジンを公開しており、質問の送信、会話状態の購読、サイト独自の表示が可能です。

<script src="https://www.obbo.me/obbochat.js" async></script>
<script>
  addEventListener('load', function () {
    var chat = ObboChat.createChat({ widgetId: 'YOUR_CHAT_ID' });
    chat.subscribe(function (state) {
      // state.turns is the conversation; state.busy while answering.
    });
    chat.ask('What do you sell?');
  });
</script>
呼び出し内容
createChat({ widgetId })チャットボットごとに 1 つのエンジン。以下のハンドルを返します。
ask(text)訪問者の質問を 1 件送信します。返答が状態に反映されると完了します。
subscribe(fn)現在の会話状態と、その後の変更ごとに呼び出されます。購読解除の関数を返します。
getState()現在の会話状態:やり取りと、質問が処理中かどうか。
startEstimate()「見積もりを依頼」をタップしたときと同じように見積もりを始めます。あいさつの後に始まり、見積もりの途中やチャットボットが見積もりを出さない場合は始めません。
destroy()すべてのリスナーを解除します。フレームワークが UI をアンマウントするときに呼んでください。
ObboChat.mount()マークアップが遅れて入った場合に、ページ内のスニペットを再探索します。
ObboChat.startEstimate(id?)ページ上のチャットを見積もりから開きます。渡した ID のチャット、または最初のチャットです。チャットがない場合は false を返します。

チャットボットごとにエンジンは1つです。バブルが行うこと(これまでの会話、見積もり用の写真、ログイン中の訪問者)はすべて購読した state に届くので、独自パネルでも失われるものはありません。

05費用見積もり

設定した質問と価格にもとづいて、チャットボットは会話の中で金額を提示できます。

チャットボットに費用見積もり機能がある場合、費用を尋ねた訪問者は、作業を数語で説明するか写真を追加するよう案内されます。写真はあなた自身の見積もり質問に沿って読み取られ(規模の区分、数量、計測値のおおよその範囲)、分かった内容は訪問者に表示され、確定する前に確認または修正できます。写真だけで価格が決まることはなく、数値は常に訪問者が確定し、訪問者の言葉が写真より優先されます。

訪問者が受け取るもの

通貨に合わせた項目別の価格帯で、作業の各部分が1行ずつ表示されます(ご希望なら、合計額とその根拠だけの表示も可能です)。各見積もりの下には御社の文が表示されます。これはあくまで概算で、正式な見積書ではありません。計算は御社の価格に基づき、価格が設定されていない部分は「別途見積もり」として表示されます。

設定すること

チャットページの料金の見積もりで行う5つの短いステップです。コードは一切不要です:

  1. サイトをスキャン:チャットボットが既に把握しているページから料金・追加料金・条件を読み取り、金額を左右する質問を提案します。
  2. 価格表:すべての価格を1枚のシートで管理します。セルを直接変更するか、ダウンロードしてExcelやGoogle Sheetsで編集し、再度アップロードできます。自動で算出された価格は、確認するまで「見積もり」と表示されます。
  3. あなたの見積もり:訪問者に表示されるとおりの見積もり例です。どの行でも変更・削除・追加でき、訪問者に各項目を表示するか、合計額とその根拠だけを表示するかを選べます。
  4. 質問:訪問者への質問を、設定した順に尋ねます。形式は1つ選択、複数選択、数値、日付、はい/いいえ、文章、写真から選べます。各質問には、回答が金額にどう影響するかが表示されます。
  5. 料金と制限:追加料金と上限、各見積もりの下に表示する文、ご自身で見積もりたい案件の規模、そして見積もり機能をオンにするスイッチです。

金額はあなたのものです。 自動で算出された価格はすべて価格表で「見積もり」と表示され、お客様との会話の各見積もりには、御社の価格ではなく一般的な相場に基づく割合が示されます。納得できない価格帯が隠れることはありません。

見積もりの行き先

すべての見積もりはお客様との会話に、作成の元になった回答とともに表示されます。各回答には、訪問者の文章・写真・検索のどれから読み取ったかが示され、連絡先を残した場合はその情報も表示されます。完成した見積もりをメールで受け取ることもできます。

写真は90日間保存され、そこから1枚ずつ削除できます。どの質問でも尋ねていない内容が写真に写っていた場合は、各見積もりにその点も記録されます。

作るものはありません。 バブルもヘッドレスエンジンも見積もりに対応しており、独自画面では会話の state に各見積もりが届きます。ここで作るものはありません。

サイトに「見積もりを依頼」リンクを置く

チャットを設置したページなら、どのボタンやリンクからでもチャットを見積もりから開けます。好きな場所に貼り付けて、サイトの他の部分と同じスタイルを付けてください。チャットページの「コードを取得」にコピー用のものがあります。

<a href="#get-estimate" data-obbo-estimate>Get an estimate</a>

このリンクは他の場所からも使えます。別のページ、メール、広告、SNS の投稿などです。チャットを設置したページのアドレスの末尾に #get-estimate を付けると、そのページを開いたときにチャットが見積もりから始まります。

独自のボタン。 任意の要素に data-obbo-estimate を付けるか、独自のコードから ObboChat.startEstimate() を呼び出してください。見積もりの途中の訪問者はやり直さずにその続きに戻り、見積もり機能が公開されていないチャットボットは開くだけです。

06ログイン中の訪問者をチャットに伝える

訪問者が誰であるかはあなたのサーバーが保証し、チャットボットはその人自身の情報をふまえて回答します。

訪問者があなたのサイトにログインする場合、チャットはあなたのサイトが共有すると決めた情報をもとに、その訪問者自身のアカウントに関する質問(「注文はどこ?」など)に答えられます。Brand Center のチャットページで「ログイン中の訪問者」をオンにすると、訪問者キーを取得できます。

訪問者キーはサーバー側の秘密情報です。訪問者キーはサーバーだけに置いてください。ウェブページ、アプリ、コードリポジトリには絶対に入れないでください。漏れた場合はチャットページでキーを交換し、古いキーをすぐに停止してください。

全体の流れ

担当行うこと
あなたのサーバーログイン中の訪問者についての短いトークンに、訪問者キーで署名します。
あなたのページトークンをチャットに渡し、訪問者がログアウトしたら知らせます。
チャット署名と有効期限を確認し、その訪問者の情報を踏まえて答えます。確認に失敗したトークンは無視され、訪問者にはゲストとして回答します。

トークンの中身

クレーム内容
sub必須。この訪問者に対するあなた独自の ID。
name任意。呼びかけに使う名前。
account任意。共有すると決めた情報(注文、予約、プランなど)を 6 KB までの JSON オブジェクトで。
exp必須。有効期限(Unix 秒)。最長 1 時間先まで。10 分で十分です。期限が切れると、チャットがページに新しいトークンを求めます。
iat任意。発行時刻(Unix 秒)。

訪問者キーをシークレットとして、HS256 の JWT として署名します。どの JWT ライブラリでも可能です。Node の例:

// Your server (Node + Express). npm install jsonwebtoken
import jwt from 'jsonwebtoken';

app.post('/chat-token', (req, res) => {
  res.set('Cache-Control', 'no-store');
  const user = req.user; // your own sign-in
  if (!user) return res.json({ token: null });
  const token = jwt.sign(
    {
      sub: String(user.id),
      name: user.firstName,
      account: { orders: recentOrdersFor(user) }, // whatever you choose to share
    },
    OBBO_VISITOR_KEY, // from your server's secret settings
    { algorithm: 'HS256', expiresIn: '10m' },
  );
  res.json({ token });
});

Python の例:

# Your server (Python + Flask). pip install PyJWT
import time
import jwt

@app.post("/chat-token")
def chat_token():
    user = current_user()  # your own sign-in
    if user is None:
        return {"token": None}
    now = int(time.time())
    claims = {
        "sub": str(user.id),
        "name": user.first_name,
        "account": {"orders": recent_orders_for(user)},  # whatever you choose to share
        "iat": now,
        "exp": now + 600,
    }
    return {"token": jwt.encode(claims, OBBO_VISITOR_KEY, algorithm="HS256")}

ページ側

サーバーからトークンを取得する関数をチャットに渡します。チャットがこの関数を呼ぶのは、質問が送られ、有効なトークンを持っていないときだけです。ページを読み込んだだけでは呼びません。

<script>
  addEventListener('load', function () {
    ObboChat.identify(async function () {
      const res = await fetch('/chat-token', { method: 'POST' });
      return (await res.json()).token;
    });
  });
  // When the visitor signs out: ObboChat.identify(null);
</script>

サイトが Cookie で訪問者をログインさせている場合は、属性 1 つで同じことができます。チャットはあなたのサイト上のそのアドレスに POST を送ります。そのルートは POST のみを受け付け、あなた自身のログインを確認し、CORS ヘッダーを送らず、誰もログインしていないときは null のトークンを返すようにしてください。

<script src="https://www.obbo.me/obbochat.js" async></script>
<div data-obbo-chat="YOUR_CHAT_ID" data-obbo-identity-url="/chat-token"></div>

訪問者がログアウトしたら ObboChat.identify(null) を呼んでください。チャットはその会話をすぐに消去するので、同じコンピューターを使う次の人は最初から始められます。

動作の確認

チャットの各返信は、トークンがどうなったかをページに伝えます。visitor.status は signed_in、anonymous、refused のいずれかで、拒否されたトークンには理由が付きます。Brand Center のチャットページでも、最後に受け付けたトークンと拒否したトークンを確認できます。

理由意味
bad_signature現在の訪問者キーで署名されていません(または猶予期間を過ぎた交換済みのキーです)。
expiredexp を過ぎています。
not_yet_validiat または nbf が未来になっています。サーバーの時計を確認してください。
too_long_livedexp が 1 時間より先になっています。
invalid_claimssub または exp がないか、項目の型や長さが正しくありません。
too_largeトークンまたはアカウント情報がサイズ上限を超えています。
malformed正しい形式の JWT ではありません。
unsupported_algorithmHS256 以外で署名されています。
not_enabledこのチャットボットではログイン中の訪問者がオフになっています。
keys_unavailableその時点でキーを確認できませんでした。あなた側で直すことはありません。

公開前に試せます。 チャットページの「お試し」タブで「ログイン中のお客様」を選び、名前と、サイトが送るはずのアカウント情報を入力すると、あなたのキーで署名した本物のトークンでテストチャットが質問します。検証も実際の訪問者とまったく同じです。

保存するもの。アカウント情報は各回答の作成のために AI プロバイダーへ送られます。会話やログには保存されませんが、回答に含まれることがあります。

07アカウントに関する質問に答える

「注文はどこですか?」に、自社システムから答えます。

お客様のサーバー上の 1 つのエンドポイントに問い合わせることで、訪問者自身のアカウントに関する質問(注文の状況、支払いが完了したかなど)にチャットが答えられます。当社がお客様のシステムに接続することはなく、鍵も保持しません。1 つの質問に必要な内容を記述して送るだけで、何を返すかはお客様が決めます。

  1. ログイン中の訪問者を有効にします(第6節)。チャットボットが問い合わせられるのは、あなたのサイトが名前を示した相手だけです。
  2. サーバーにエンドポイントを1つ作ります。GET はカタログを返し、POST はそこから作られた1件のリクエストに答えます。
  3. チャットページの「名前とあいさつ」タブで「開発者向け」を開き、「アカウントに関する質問」で、そのアドレスを「データエンドポイント」に貼り、「エンドポイントに接続」を押します。回答できる内容がすぐに読み取られます。
  4. 「オンにする」を押します。以後そのパネルに、問い合わせ回数、エンドポイントの所要時間、直近の問題がわかりやすい言葉で表示されます。

すべての回答をトークンの範囲に限定してください。すべての応答を、お客様自身の鍵で検証した訪問者トークンの sub に限定し、リクエストの他の部分が示す識別子は無視してください。これにより、ある訪問者に別の訪問者のデータが表示されることが原理的に起こりません。

データを記述する

エンドポイントへの GET はカタログを返します。返せるデータの種類と各項目のフィールドです。だからこそ、訪問者がしそうな質問を列挙する必要はありません。質問された時点で、チャットがカタログと照合します。

// GET https://your-site.com/obbo-chat/data
// Describe the data you have. You never list the questions your visitors
// might ask — the chat matches a question to one of these itself.
{
  "version": 1,
  "resources": [{
    "name": "orders",
    "title": "Orders",
    "description": "Orders on this customer's account, newest first.",
    "scope": "visitor",
    "fields": [
      {"name": "status", "type": "string", "description": "Where it stands.",
       "values": ["paid", "shipped", "delivered"]},
      {"name": "ship_date", "type": "date", "description": "When it shipped."},
      {"name": "tracking", "type": "string", "description": "Carrier tracking link."}
    ],
    "filters": [{"field": "status", "ops": ["eq"]}],
    "default_request": {"fields": ["status", "ship_date", "tracking"], "limit": 10},
    "max_limit": 25
  }]
}
フィールド内容
nameこの種類のデータを表す小文字の識別子。リクエストはこれを指定します。
title回答の中での呼び方。
scopevisitor — 唯一のスコープで、常に質問している本人についてです。
description何が入っているかを1文で。質問はこの説明と照合されるので、訪問者の言い方で書いてください。
fields[]各フィールドの名前、型、短い説明、決まった選択肢がある場合は values。
filters[]絞り込めるフィールドと使える演算子:eq、neq、gte、lte、contains、in。
default_request質問がそれ以上を示さないときに使うフィールドと件数。
max_limit一度に返す件数の上限。

1 件のリクエストに答える

POST では、あなたのカタログから作られた構造化リクエストと、あなたのサーバーが署名した訪問者トークンが届きます。中身はすべてカタログ由来で、カタログに記載のないリクエストが送られることはありません。

// POST https://your-site.com/obbo-chat/data
// "Where is my order?" becomes this. Operators are only:
// eq, neq, gte, lte, contains, in. There is no SQL and no free text.
{
  "version": 1,
  "visitor_token": "<the token YOUR server signed for this visitor>",
  "request": {
    "resource": "orders",
    "filters": [{"field": "status", "op": "eq", "value": "shipped"}],
    "fields": ["status", "ship_date", "tracking"],
    "limit": 10
  },
  "request_id": "chat_9f2c41b8"
}

その部分だけを返してください。応答は 64 KB 未満に収めてください。

// Answer with that slice, and nothing else.
{
  "version": 1,
  "resource": "orders",
  "items": [
    {"status": "shipped", "ship_date": "2026-09-14",
     "tracking": "https://carrier.example/track/4471"}
  ],
  "item_count": 1,
  "truncated": false
}
フィールド内容
version常に 1。
resource回答した対象のリソース。
items[]各行。求められたフィールドだけを入れてください。ここに入れたものは訪問者に読み上げられる可能性があります。
item_countitems の行数。
truncated一部を返さなかった場合は true。

リクエストの検証

確認は2つ、この順番で。リクエストが訪問者キーで署名されているか、そして誰についてかです。どちらも訪問者トークンの署名に使っているキーと同じものを使うので、新たに入れるものはありません。GET と POST の両方が署名され、GET は空のボディに対する署名です。

ヘッダー内容
X-Chat-Data-Signatureタイムスタンプと署名。t は unix 秒、v1 は下記の HMAC-SHA256(16進)です。t から5分以内のものだけを受け付けてください。
X-Chat-Key-Version署名に使われたキーの版。キーを交換すると変わり、猶予期間中は両方の版が届きます。
X-Chat-Data-Signature: t=1760000000,v1=4b1f…9c   // hex, 64 chars
X-Chat-Key-Version: 3

signature = HMAC_SHA256(
  your_visitor_key,
  "<t>.<METHOD> <path and query>." + <raw request body>
).hex()

// GET  "1760000000.GET /obbo-chat/data."            + ""
// POST "1760000000.POST /obbo-chat/data."           + the bytes that arrived
const crypto = require('crypto');
const KEY = process.env.OBBO_VISITOR_KEY;   // the key from your chat page

// 1. Is this really from the chat service? The signature covers the method,
//    the path as sent, and the RAW body — so check before you parse.
function fromObbo(req, rawBody) {
  const fields = Object.fromEntries(
    (req.get('X-Chat-Data-Signature') || '').split(',').map(p => p.trim().split('='))
  );
  const t = Number(fields.t);
  if (!Number.isInteger(t) || Math.abs(Date.now() / 1000 - t) > 300) return false;
  const mine = crypto.createHmac('sha256', KEY)
    .update(`${t}.${req.method} ${req.originalUrl}.`)
    .update(rawBody)
    .digest('hex');
  const a = Buffer.from(mine), b = Buffer.from(fields.v1 || '');
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

// 2. Who is it about? From the token YOU signed — never from the body.
function visitorId(token) {
  const [head, payload, sig] = String(token || '').split('.');
  if (!head || !payload || !sig) return null;
  const mine = crypto.createHmac('sha256', KEY)
    .update(`${head}.${payload}`).digest('base64url');
  if (mine !== sig) return null;
  const claims = JSON.parse(Buffer.from(payload, 'base64url').toString('utf8'));
  if (!claims.exp || Date.now() / 1000 > claims.exp) return null;
  return claims.sub;
}

// Your catalog. Signed too, over an empty body.
app.get('/obbo-chat/data', (req, res) => {
  if (!fromObbo(req, '')) return res.sendStatus(403);
  res.set('Cache-Control', 'no-store').json(CATALOG);
});

// One request. express.text keeps the raw bytes the signature covers;
// express.json would re-encode them and the check would fail.
app.post('/obbo-chat/data', express.text({ type: '*/*' }), async (req, res) => {
  if (!fromObbo(req, req.body)) return res.sendStatus(403);
  const body = JSON.parse(req.body);
  const customer = visitorId(body.visitor_token);
  if (!customer) return res.sendStatus(403);

  const asked = body.request || {};
  if (asked.resource !== 'orders') return res.sendStatus(422);   // not mine to answer

  // Scope EVERY query by `customer`. Ignore any id in the request body.
  const rows = await db.orders.findAll({
    where: { customer_id: customer, ...where(asked.filters) },
    limit: Math.min(asked.limit || 10, 25),
  });

  // Return the fields that were asked for, and never a field you did not
  // declare: everything you send is read out to the visitor.
  const items = rows.map(row => pick(row, asked.fields));
  res.set('Cache-Control', 'no-store')
     .json({ version: 1, resource: 'orders', items, item_count: items.length });
});

返すステータス

あなたが返すステータスが、そのままチャットページの表示になります。次のとおり使ってください。

返すもの意味
200データを返します。items が空でもまったく問題のない回答で、チャットボットはアカウントに該当がなかったと伝えます。
403署名か訪問者トークンが通らなかった場合。拒否はすべて同じ返し方にし、どの確認で落ちたかは明かさないでください。
404何も待ち受けていない状態。チャットページはアドレスの誤りとして表示します。
422カタログには記載があるが提供しないリクエスト。チャットボットはそれなしで回答し、訪問者には異常として見えません。
500あなたの側で問題が起きた場合。失敗として数えます。
301 / 302たどりません。最終的なアドレスをご指定ください。

5回連続で失敗すると問い合わせを止めます。 問い合わせは5分間停止し、チャットページに直近の理由とともに表示されます。再開は自動です。成功した問い合わせでカウントは0に戻りますが、「回答できる内容を読み取る」はエンドポイントの確認だけです。その間もチャットボットは他の質問に答え続けます。

遅いことは、無いことと同じです。送信したリクエストは 2.5 秒以内に応答がなければ、チャットはそれなしで回答します。エンドポイントが遅くても訪問者の質問が失敗することはありません。

08上限と所要時間

この仕様で定めた上限をまとめました。

上限対象
2.5 s1件のリクエストに対するエンドポイントの持ち時間。これを超えると、チャットボットはそれなしで回答します。
5 sカタログを読み取るときのエンドポイントの持ち時間。
8 KB送信するリクエストボディの最大。
64 KB返答から読み取る最大量。
8 KB返答のうち回答作成に渡される量。収まるまで、末尾から項目単位で落とします。
32 KB読み取るカタログの最大。
121つのカタログに入るデータの種類数。
401種類のデータに入るフィールド数。
101件のリクエストに入るフィルター数。
120フィルター値の文字数。
10in フィルターの値の数。
6 KB訪問者トークンに載せるアカウント情報。
1 h訪問者トークンの最長有効期間。10分で十分です。
5問い合わせを停止するまでの連続失敗回数。
5 min停止する時間。

09Content Security Policy

サイトで CSP を設定している場合は、この2つを許可してください。他は不要です。フレーム、フォント、当社の画像はありません。

ディレクティブ理由
script-src https://www.obbo.meウィジェットスクリプトの読み込み。
connect-src https://www.obbo.meチャットの質問と回答。

コード内のスタイル値はウィジェットのスクリプトが適用するため、インラインスタイルを禁止するポリシーでも見た目は保たれます。ブラウザが style 属性について警告を表示することがありますが、問題ありません。

誰が識別されるか。ゲストが特定されることはありません。ブラウザ内のランダムなセッションキーが、1 人の訪問者の質問をダッシュボード上の 1 つの会話にまとめるだけです。ログイン中の訪問者は、あなたのサイトが送った ID と名前だけで識別されます。

10うまくいかないとき

何も表示されない

div に data-obbo-chat とチャット ID があり、script タグがページにあるか確認してください。ページ準備完了後にマークアップが入る場合は、その後に一度 ObboChat.mount() を呼びます。チャットページには、チャットが最後に動作していたウェブサイトも表示されるので、スニペットが有効かどうかが分かります。

このウェブサイトでは回答できないと言われる

そのウェブサイトが許可リストに入っていません。チャットページの「名前とあいさつ」タブで追加してください。断られたサイト名も表示されるので、本当に自社のものか確認できます。

「わかりません」と繰り返す

チャットボットが答えられるのは、ウェブサイトから読み取った内容だけです。「ウェブサイト」タブを確認し、変更後は公開し、「会話」タブを読んでください。訪問者の質問はすべて残っており、答えられなかった質問こそ書くべきページです。

訪問者トークンが拒否される

理由は毎回返ってきます。visitor.status が refused になり、第6節の理由が付きます。よくあるのは、サーバー時刻のずれと、片側だけキーを交換した場合です。チャットページには直近の拒否とその理由が表示されます。

アカウントに関する質問で、エンドポイントに到達できないと表示される

チャットページに問題がわかりやすい言葉で表示されます。署名の問題なら3点を確認してください。再エンコードした JSON ではなく生のボディを対象にしているか、パスにクエリ文字列が含まれているか、メソッドが大文字か。

エンドポイントへの問い合わせが止まっている

5回連続の失敗で問い合わせは5分間停止し、その後は自動で再開します。原因を直せば、次に成功した問い合わせでカウントは0に戻ります。

11ご質問は?

ページのアドレス、チャット ID、実際にした質問をお知らせください。こちらでも同じものを確認します。お送りいただいた内容はすべて読んでいます: hello@obbo.me

Obbo のチャットボットについて

チャットウィジェットガイド