こういう人に向けて書いてます
本記事には、
・面倒くさい事務作業を減らしたい人
・会社のために、何かを作りたいけど、バックエンドが苦手な人
・みんなが使えるツールを作りたい人
に向けて書いています。
なぜ社内検索botを作ったのか?
去年、ジーズアカデミーに入学して、プログラミングを学ぶきっかけの一つっは、どうしても解決したい会社での小さな問題であった。それは、社内でいつも発生する、カスタマー対応の煩雑さ
。
流れはこちら:
メールが読み→該当するテンプレを探す→お客様の名前を書き換わる→自分のお名前を書き換わる→確認する→送信
(自分の業務じゃないけど、だるい!)
ここで考えたのが:
1、全社にテンプレ共有
2、書き換わる部分をわかりやすくする。ミスの少なくする。
目的
・問い合わせメールをもっと早く返したい
・テンプレを探す手間を省きたい
・担当不在の時でも、情報共有によって、誰でもある程度業務を引き継げられる環境作りたい
・顧客対応関連で、社内で小さな衝突をなくしたい
・内容更新も簡単で、誰でも使える簡単なシステムにしたい(めちゃくちゃ重要)
こんなものです!
-
選択式で、親カテゴリーから絞っていき、該当テンプレを探し出す。
-
担当スタッフの名前を選択
-
お客様のお名前を入力
-
検索ボタンをクリックすると同時に、スタッフ、お客様の名前が入った状態でテンプレを出す。
-
コピーボタンを押してから、メールを貼り付けて完了。
-
探す手間も、全選択(Ctrl+A)の手間も省けます。
仕組み
JavaScriptからfetch関数を使って、スプレッドシートの情報を取得
整列して、ブラウザに表示する。
Google Cloud Platform (GCP)の設定
前回の記事で、LaravelでGoogleSheetAPIを使ってみたが、今回はサーバーなど関係なし、ローカルで使っていただくことになりますので、比較的にセキュリティーへの懸念が少なく、APIキーを取得するやり方にしました。
サービスアカウントのやり方に興味ある方はこちらの記事へ ^^
設定方法はまず、GCPでAPI / サービス詳細
ページで、SheetAPIキーを有効にする
そして、認証情報
ページに、APIキーを生成。大事なのは、必ずキーの制限
を設定すること。設定しない場合、動かなかったりします > <
JavaScriptでデータを取得する
次は、API経由で、スプレッドシートの情報を取得する。
そして、取得したスプシのjsonデータを配列にする。
const apiKey = // あなたのAPIキーに置き換える
const spreadsheetId = // あなたのスプレッドシートのIDに置き換える
const sheetName = // データがあるシート名に置き換える
const endpoint = `https://sheets.googleapis.com/v4/spreadsheets/${spreadsheetId}/values/${sheetName}?key=${apiKey}`;
// endpointからデータを取得する
fetch(endpoint)
.then(response => response.json())
.then(data => {
const qaPairs = data.values.slice(1).map(row => ({
course: row[0],
category: row[1],
question: row[2],//同じコードを使い回ししていますので、ここを保留しています。
answer: row[3]
}));
あとは取得したデータを処理する。
やることが主に3つ
- セレクトボックスを並び替えた状態で表示
- 選んだ結果を
textarea
で表示 - コピー機能つつける
1 セレクトボックスを並び替えた状態で表示
HTMLタグにあるデータを取得し、セレクトボックスの中身を綺麗に整理する。
データ取得
→カテゴリーなど並べ替え
→セレクトボックスのオブションを更新
// データを取得したら、検索ボタンを有効にする
const searchBtn = document.getElementById("searchBtn");
// セレクトボックスを取得
const categorySelect = document.getElementById("categorySelect");
const courseSelect = document.getElementById("courseSelect");
// カテゴリーのオプションを追加
const queryInput = document.getElementById("query");
const resultsDiv = document.getElementById("results");
// カテゴリー、コースのオプションを追加
const categories = [...new Set(qaPairs.map(qaPair => qaPair.category))];
const courses = [...new Set(qaPairs.map(qaPair => qaPair.course))];
// カテゴリーやコースのオプションを昇順に並び替え
const sortedCategories = categories.sort();
const sortedCourses = courses.sort();
// カテゴリーセレクトボックスのオプションを更新
categories.forEach(category => {
const option = document.createElement("option");
option.value = category;
option.textContent = category;
categorySelect.appendChild(option);
});
// コースセレクトボックスのオプションを更新
courses.forEach(course => {
const option = document.createElement("option");
option.value = course;
option.textContent = course;
courseSelect.appendChild(option);
});
// コース選択時に関連するカテゴリーオプションを更新する関数
function updateCategoryOptions(relatedCategories) {
// カテゴリーセレクトボックスのオプションを一旦クリア
categorySelect.innerHTML = '<option value="">すべてのカテゴリー</option>';
// 重複を除去して昇順にソート
const uniqueCategories = [...new Set(relatedCategories)].sort();
uniqueCategories.forEach(category => {
const option = document.createElement("option");
option.value = category;
option.textContent = category;
categorySelect.appendChild(option);
});
}
2 選んだ結果をtextarea
で表示
ここは一番簡単だけど、ちゃんとmarginもここで調理できるのはチャッピが教えてくれたおかげです。
const spacingDiv = document.createElement("div");
spacingDiv.style.marginBottom = "20px"; // 適切な間隔に調整
const separator = document.createElement("hr");
separator.style.margin = "20px 0"; // 適切な間隔に調整
resultsDiv.appendChild(courseDiv);
resultsDiv.appendChild(spacingDiv);
resultsDiv.appendChild(categoryDiv);
resultsDiv.appendChild(spacingDiv);
resultsDiv.appendChild(answerDiv);
resultsDiv.appendChild(answerTextarea); // テキストエリアを追加
resultsDiv.appendChild(copyButton);
resultsDiv.appendChild(separator);
3 コピー機能つつける
コピーボタンは割と検索したらすぐ出てきますが、今回面倒くさかったのが、変数で置き換えたスタッフ名とお客様の名前をコピーするので、replaceVariables
の関数で、置き換えたものを取得する。ここに気づくまで、3時間溶けました
// コピーするボタンの作成
const copyButton = document.createElement("button");
copyButton.textContent = "回答をコピー";
copyButton.addEventListener("click", () => {
const answerText = replaceVariables(result.answer); //←ここが重要!!
//const answerText = result.answer; // ←最初これにして、詰んだ ^^;;;
const textArea = document.createElement("textarea");
textArea.value = answerText;
document.body.appendChild(textArea);
textArea.select();
document.execCommand("copy");
document.body.removeChild(textArea);
alert("回答がコピーされました!");
});
分類や質問や回答からキーワード検索
もしくは分類から検索
スプシを記入
スプレットシートはとても簡単。コース、カテゴリー、答えを設定します。
そして、{staff_select}
と{customer}
を表示させたい場所に設定すれば、完成 \^0^/
今回の件で実現できたこと(&伝えたいこと)
オフラインでの社内共有なので、分類ができれば、意外とすぐ実現しちゃう。
逆に、テンプレの取捨選択が難しかった。汎用性の高いテンプレを使うが、使えないものをどう処理するのか、その基準を考えるのに、1日かかりました。
そして、プログラミングを勉強した時、技術を使いたい欲があったが、時間が経ち、誰のために、何を作るにフォーカスできたら、すごいモノを作るより、誰でも触れる、誰でも改善できるモノがいいに気づいた。だから、誰でも更新できるスプレッドシートにしました。スプレッドシートをどんどん更新していけば、テンプレが貯めていける仕組みとなります。(やさしい世界!)
最後に、非エンジニアで、めちゃくちゃコードを書けるわけじゃないけど、限られてる能力で、少しでも身近にある面倒なことを減らせるのも幸せやん〜
という、今回の気づきでした。おしまい〜