コンテンツにスキップ

Slackに架電結果を通知する

エージェントの「Slack通知」で「Slackと連携」を選び、Slackの認可画面で通知先チャンネルを選択します。登録した接続先は同じProjectの複数エージェントから利用できます。

通知ルールでは送信条件と「標準/カスタム」本文を設定できます。カスタム本文の入力上限は2,500文字です。差し込み後に長くなる場合は本文を省略し、通話詳細への案内を表示します。投稿タイトルは固定です。通話詳細は本文のURLから開けます。カスタム本文でリンクを表示する場合は「通話詳細URL」変数を差し込んでください。通知バナー向けの文章は「nocall 通話通知 - 通知設定名」になります。

差し込みボタンは「デフォルトの変数」と「目標分析の変数」に分かれています。画面では日本語の変数名を表示しますが、既存設定との互換性のため保存時は既定の英語キーを保持します。分析項目は名前ではなくIDで保存するため、項目名を変更しても同じ項目を参照します。例:

@here {{エージェント名}} の通話が終了しました :tada:
*結果:* {{通話状態}}
*商談化:* {{目標分析:商談化}}
{{分析結果一覧}}

「分析結果一覧」は分析項目をまとめて表示する変数です。特定の項目だけ表示したい場合は「目標分析の変数」から項目を選びます。項目名が重複する場合はチップにIDが表示されます。削除済み・未確認の個別項目は別の項目へ置き換えず、通知では - と表示します。

メンションや書式の詳しい入力例は、メンション・書式の使い方を参照してください。

「サンプルプレビュー」はSlackへ送信せずに本文を確認する機能です。画面では {{エージェント名}} などの変数名をハイライト表示し、値は展開しません。テスト送信時にエージェント名・通知設定名は現在の設定、通話状態・電話番号・日時・分析結果などはサンプル値へ置き換えます。実際の分析結果によって長さが変わります。IDの表示名は解決しません。

プレビュー画面左下の「テスト送信」を押すと、選択中のチャンネルへ編集中の本文をサンプル値で送信できます。保存前でも利用できます。送信先を確認してから押してください。本文に書いたメンションも実際に通知されます。テストのタイトルには「[テスト送信]」が付き、本文に含まれる通話詳細URLは現在のエージェント画面へ案内します。実際の通話や通常の通知送信履歴は作成しません。

送信中はボタンが無効になり、完了後に成功・失敗を表示します。連続送信は制限されるため、再送する場合は30秒以上待ってください。

接続一覧の「連携解除」はnocallに保存した接続情報を削除します。Slack側のチャンネル・アプリ・Webhook自体は削除しません。有効な通知ルールがある場合だけ「使用中」と表示され、解除できません。ボタンにカーソルを合わせると理由を確認できます。利用中のルールを無効にするか、別の接続先へ変更すると解除できます。解除後も無効なルールの本文・条件は残り、通知先は「—」になります。そのルールを再び保存する際は、通知先を選び直してください。送信履歴は残ります。

カスタム本文では、Slack用の記法を直接入力できます。画面の「メンション・書式の使い方」リンクから、このガイドを別タブで開けます。

個人・ユーザーグループをメンションする

Section titled “個人・ユーザーグループをメンションする”
通知する相手 本文に入力する例
個人 <@U123ABC456>
ユーザーグループ <!subteam^S123ABC456>
チャンネル内のオンラインのメンバー @here
チャンネル全体 @channel

例のIDはダミーです。個人はSlackで相手のプロフィールを開き、「その他」のメニューから「メンバーIDをコピー」を選び、<@ と > の間に貼り付けます。

ユーザーグループのIDは、次のどちらの方法でも取得できます。

  1. Slackで対象グループのプロフィールを開き、右上の「⋮」メニューから「グループIDをコピーする」を選ぶ。
  2. 対象グループのプロフィールURLに含まれる、S から始まるグループIDを確認する。

取得したIDを <!subteam^S123ABC456> のID部分に貼り付けます。<!subteam^ と > はそのまま残してください。IDだけ、または @担当者名 や @グループ名 を書くだけではメンションになりません。

<@U123ABC456> 通話結果をご確認ください。
<!subteam^S123ABC456> 新しい問い合わせがありました。
@here 至急の確認をお願いします。

@here・@channel は前後に空白や改行を入れてください。nocallがSlackのメンション形式に変換します。コード内やURL内の表記は変換しません。チャンネルへの参加状況やSlack側の通知設定によって、通知の届き方は異なります。

表現 入力例・操作
太字 *重要なお知らせ*(半角の * で囲む)
斜体 _補足_(半角の _ で囲む)
取り消し線 ~対応前~(半角の ~ で囲む)
改行 入力欄で実際に改行する。文字として \n を入力する必要はない
絵文字 🎉・✅ などを直接入力する、または :tada:・:white_check_mark: と入力する
箇条書き 各行の先頭に ・ や - を入力する

コードとして表示する部分はバッククォートで囲みます。たとえば `@here` はメンションに変換されません。複数行のコードは前後をバッククォート3つで囲みます。Slackの書式は一般的なMarkdownと一部異なり、太字は **本文** ではなく *本文* を使います。

変数ボタンを押すと、カーソル位置に {{エージェント名}} などが入ります。目標分析の項目は「目標分析の変数」を開いて選んでください。目標ステータスもここから対象項目を選びます。

*{{エージェント名}} の通話が終了しました* :tada:
・通話状態: {{通話状態}}
・電話番号: {{電話番号}}
・通話時間: {{通話時間}}
{{分析結果一覧}}

メンションを追加したい場合は、本文の先頭などに相手のIDを使った記法を追記します。差し込まれた通話情報や分析結果に含まれるメンションは通知対象になりません。

入力は2,500文字までです。変数の差し込み後に本文が3,000文字を超える場合は省略されます。サンプルプレビューは実際の通話データを使わないため、本文の長さや一部のSlack書式・絵文字の表示は実際の投稿と異なる場合があります。IDから表示名への変換も行いません。

「テスト送信」は実際のチャンネルへ投稿し、本文に記述したメンションも有効になります。送信先とメンション対象を確認してから使用してください。

Slack側の記法の詳細は、Slack公式のメッセージ書式ガイドを参照してください。

nocall の通話完了 Webhook を Google Apps Script(GAS)で受け取り、Slack の Incoming Webhook へ架電結果を通知します。

このサンプルが Slack へ送信する項目は、エージェント名、通話結果、電話番号の末尾 4 桁、通話時間、nocall の通話詳細画面へのリンクです。会話本文、コンタクト属性、通話後分析は Slack へ送信しません。

  • Google アカウントと nocall アカウントがある
  • nocall で対象エージェントの Webhook 設定を変更できる
  • Slack アプリを作成し、通知先チャンネルへ追加できる

1. SlackのIncoming Webhookを作成する

Section titled “1. SlackのIncoming Webhookを作成する”
  1. Slack API のアプリ管理画面で「Create New App」を選択します。
  2. 「From scratch」を選択し、アプリ名と通知先のワークスペースを設定します。
  3. 「Incoming Webhooks」を開き、「Activate Incoming Webhooks」を有効にします。
  4. 「Add New Webhook to Workspace」を選択します。
  5. 通知先チャンネルを選択して許可します。
  6. 作成された Webhook URL をコピーします。

Webhook URL は、その URL を知っている人が Slack へ通知を投稿できる秘密情報です。チャット、チケット、ソースコードへ貼り付けないでください。

  1. Google Apps Scriptで新しいプロジェクトを作成します。
  2. プロジェクト名を「nocall Slack 通知」など、用途が分かる名前へ変更します。
  3. Apps Script の「プロジェクトの設定」→「スクリプト プロパティ」に次の値を追加します。
プロパティ 値
SLACK_WEBHOOK_URL 手順 1 でコピーした Slack の Webhook URL
NOCALL_WEBHOOK_SECRET 英数字、-、_ だけで生成した 32 文字以上のランダムな文字列

NOCALL_WEBHOOK_SECRET はパスワード管理ツールなどで生成し、記号を含める場合も - と _ だけを使用してください。

Apps Script の Code.gs を開き、元の内容をすべて削除してから、次のコードをそのまま貼り付けて保存します。

const SLACK_WEBHOOK_URL_PROPERTY = "SLACK_WEBHOOK_URL";
const NOCALL_WEBHOOK_SECRET_PROPERTY = "NOCALL_WEBHOOK_SECRET";
const MAX_SLACK_MESSAGE_LENGTH = 2900;
function doPost(event) {
const expectedSecret = getRequiredProperty(NOCALL_WEBHOOK_SECRET_PROPERTY);
const actualSecret = String(event.parameter?.key ?? "");
if (!constantTimeEqual(actualSecret, expectedSecret)) {
throw new Error("Webhook secretが一致しません");
}
if (!event.postData?.contents) {
throw new Error("Webhook payloadが空です");
}
const call = JSON.parse(event.postData.contents);
const response = UrlFetchApp.fetch(
getRequiredProperty(SLACK_WEBHOOK_URL_PROPERTY),
{
method: "post",
contentType: "application/json",
payload: JSON.stringify(buildSlackMessage(call)),
muteHttpExceptions: true,
},
);
const responseCode = response.getResponseCode();
if (responseCode < 200 || responseCode >= 300) {
const responseText = truncate(response.getContentText(), 200);
throw new Error(`Slack通知に失敗しました: HTTP ${responseCode} ${responseText}`);
}
return ContentService.createTextOutput("ok");
}
function buildSlackMessage(call) {
const agentName = escapeSlack(call.agent?.name ?? "不明");
const status = escapeSlack(formatCallStatus(call.callStatus));
const lines = [
"*nocall 架電結果*",
`・エージェント: ${agentName}`,
`・ステータス: ${status}`,
`・通話先: ${escapeSlack(maskPhoneNumber(call.to))}`,
`・通話時間: ${escapeSlack(formatDuration(call.duration))}`,
];
if (call.isVoicemail === true) {
lines.push("・留守番電話: はい");
}
if (isNocallDetailsUrl(call.detailsUrl)) {
lines.push("", `<${call.detailsUrl}|nocallで通話詳細を開く>`);
}
return { text: truncate(lines.join("\n"), MAX_SLACK_MESSAGE_LENGTH) };
}
function formatCallStatus(status) {
const labels = {
preparing: "準備中",
ringing: "呼び出し中",
in_progress: "通話中",
completed: "完了",
no_answer: "応答なし",
failed: "失敗",
unreachable: "到達不能",
};
return labels[status] ?? String(status ?? "不明");
}
function formatDuration(duration) {
if (!Number.isFinite(duration) || duration < 0) return "未取得";
const minutes = Math.floor(duration / 60);
const seconds = String(Math.floor(duration % 60)).padStart(2, "0");
return `${minutes}分${seconds}秒`;
}
function maskPhoneNumber(value) {
const digits = String(value ?? "").replace(/\D/g, "");
if (digits.length < 4) return "未取得";
return `****${digits.slice(-4)}`;
}
function isNocallDetailsUrl(value) {
return /^https:\/\/console\.nocall\.ai\//.test(String(value ?? ""));
}
function escapeSlack(value) {
return String(value)
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;");
}
function truncate(value, maxLength) {
const text = String(value);
return text.length <= maxLength ? text : `${text.slice(0, maxLength - 1)}…`;
}
function getRequiredProperty(name) {
const value = PropertiesService.getScriptProperties().getProperty(name);
if (!value) throw new Error(`${name}が設定されていません`);
return value;
}
function constantTimeEqual(leftValue, rightValue) {
const left = String(leftValue);
const right = String(rightValue);
const length = Math.max(left.length, right.length);
let difference = left.length ^ right.length;
for (let index = 0; index < length; index += 1) {
difference |= (left.charCodeAt(index) || 0) ^ (right.charCodeAt(index) || 0);
}
return difference === 0;
}

4. Webアプリとしてデプロイする

Section titled “4. Webアプリとしてデプロイする”
  1. Apps Script 右上の「デプロイ」→「新しいデプロイ」を選択します。
  2. 種類に「ウェブアプリ」を選択します。
  3. 「次のユーザーとして実行」は自分を選択します。
  4. 「アクセスできるユーザー」は、外部システムからアクセス可能な「全員」を選択します。
  5. 「デプロイ」を選択し、権限の確認を完了します。
  6. /exec で終わるウェブアプリ URL をコピーします。
  1. nocall で対象のエージェントを開きます。
  2. 「Webhook設定」を開き、「Webhookを追加」を選択します。
  3. Webhook 名に「Slack 通話結果通知」など、用途が分かる名前を入力します。
  4. URL に、GAS のウェブアプリ URL と NOCALL_WEBHOOK_SECRET を次の形式で入力します。
https://script.google.com/macros/s/DEPLOYMENT_ID/exec?key=NOCALL_WEBHOOK_SECRETの値
  1. 保存します。

この URL は共有シークレットを含むため、チャットやチケットへ貼り付けないでください。

  1. nocall の Webhook 設定で「テスト」を選択します。
  2. 「Webhookの送信に成功しました」と表示されることを確認します。
  3. Slack の通知先チャンネルにテスト用の架電結果が表示されることを確認します。
  4. Apps Script の「実行数」で doPost が「完了」になっていることを確認します。

テスト送信は固定のダミーデータを使用し、実際の電話は発信しません。

nocall の対象エージェントで Webhook 設定を開き、「Slack 通話結果通知」の Webhook を削除します。削除後に完了した通話は、この連携から Slack へ通知されません。

連携自体を廃止する場合は、Apps Script のデプロイとスクリプト プロパティを削除し、Slack アプリの設定から Incoming Webhook を削除してください。すでに Slack へ投稿されたメッセージは Incoming Webhook から削除できません。

  • nocall のテストが失敗する
    • GAS の URL が /exec で終わっているか確認する
    • URL の key と NOCALL_WEBHOOK_SECRET が完全に一致しているか確認する
    • Apps Script の「実行数」でエラー内容を確認する
  • nocall のテストは成功するが Slack に表示されない
    • SLACK_WEBHOOK_URL が正しいか確認する
    • Slack アプリが通知先チャンネルへ追加されているか確認する
    • 通知先チャンネルがアーカイブされていないか確認する
  • Slack通知に失敗しました: HTTP 429 と表示される
    • Slack への通知が集中しているため、時間を空けてテストする
    • 正式な架電結果は nocall の通話履歴で確認する

Webhook URL や共有シークレットが漏えいした可能性がある場合は、Slack の Incoming Webhook と NOCALL_WEBHOOK_SECRET の両方を新しい値へ変更してください。