採用管理システムのユーザーフィードバックを集められるSalesforceアプリ(AppExchange)を開発してみた

この記事はfreee Developers Advent Calender 2020の8日目の記事です。

どうもどうも、freeeでfreeeTechNightの司会をやっていたり採用管理システムを開発している @noblejasper です。

今日も採用管理システムの話を書いていこうと思います。社内で開発している採用管理システムが日々進化出来ている事を少しでも感じていただけたら嬉しいです。

採用管理システムをSalesforce上で開発しています

今年の5月にfreeeの採用活動を効率化していくために採用管理システムを開発している話を書きました。採用管理システムの詳細な話は是非そちらの記事を読んでいただけたら嬉しいです。

社内からのフィードバックを集めて改善してみた

リリース後しばらくして使い勝手に関するアンケートを取って改善して再度アンケートを取って効果を測定して良くなった話を9月に書きました。

この記事の中ではGoogleフォームを使い、使用している全社員に送信して回収を行いました。これによって大幅な改善を行う事が出来、使い勝手が向上した手応えを感じました。

これだけではまだ開発者が気づけていない使いづらい点もっと改善出来る点が見つけきれていないのではないかと感じていました。

社内アプリケーションへのフィードバックを集める上での課題

もっとフィードバックを集められる方法はないのだろうかと考えてみました。

  • 毎回毎回アンケートを作成するのは大変
  • 回答する側もアンケート回答は心理的障壁が高い(めんどくさい)
  • 数日以上も前に使ったシステムにフィードバックしろと言われても思い出せない

こういった点を考えている内に、世の中の多くのソフトウェアでは使用直後や使用時にその場でフィードバックを集められる仕組みがあることに気づきました。

簡単に社内ユーザーからフィードバックを集められる仕組みを作りたい

Salesforce上で開発しているのだから、AppExchange(Salesforceプラットフォーム上にインストールするアプリケーション)で開発してみようと思いました。使用直後や使用時にその場で簡単にフィードバックを送る事が出来るAppExchangeです。

開発する上でイメージしたのは、普段よく使っているUber Eatsでした。Uber Eatsでは、注文した後に「いかがでしたか?」のような評価画面が出てきます。それの簡易的なものをイメージして開発しました。

開発合宿で初めてのAppExchange開発にチャレンジ!

freeeでは開発合宿という、開発者が普段の業務から離れて、短期集中で取り組むイベントがあります。

developers.freee.co.jp

そこでFeedbackStockerというAppExchangeを開発しました。

FeedbackStockerのホーム画面のスクリーンショット
FeedbackStockerのホーム画面

初めてのAppExchange開発だったため、調べながら開発を進めましたがSalesforce開発ではドキュメントが豊富に提供されているためスムーズに2日間で形になるところまで開発することができました。

今回は『ロック解除済みパッケージ』というAppExchangeの形式で作成しました。ロック解除済みパッケージとは、外部向けAppExchangeとは違いインストール後に設定などメタデータの上書きが出来るようになっているパッケージの事です。詳しく知りたい方はSalesforce社が提供しているTrailheadにチャレンジしてみるのがよいと思います。私もここで覚えながら開発しました。

trailhead.salesforce.com

FeedbackStockerで提供する機能

FeedbackStockerが提供する機能はシンプルです。

  • 色んな画面に埋め込めるフィードバック画面
  • フィードバックがカテゴリ毎に格納される
  • レポートで振り返りや分析が出来る

簡単にそれぞれを説明していきます

色んな画面に埋め込める

Lightning Web Component(LWC)というJavaScript, HTML, CSSを使ってSalesforce上に機能を追加出来る仕組みを使って実装しています。

フィードバックを入力するフォームのスクリーンショット。Goodボタン、Badボタン、ひとことを入力するフォームが表示されています。
Good/Bad と ひとことコメントを書き込めるようにしました

フォームを表示するだけであればこれぐらいのHTMLとJavaScriptを書けば表示が出来ます。一部抜粋ではありますが、実際に使用しているHTMLとJavaScriptを記載しておきます。似たような事をしている方の参考になれば嬉しいです。

FeedbackStockerのHTML一部抜粋
<template if:false={isFinishCreate}>
  <div class="slds-m-around_small">
    <lightning-button-stateful
      label-when-off="Good"
      label-when-on="Good済"
      icon-name-when-off="utility:like"
      icon-name-when-on="utility:check"
      selected={isGood}
      onclick={handleGoodClick}
      class="slds-m-horizontal_small"
    >
    </lightning-button-stateful>
    <lightning-button-stateful
      label-when-off="Bad"
      label-when-on="Bad済"
      icon-name-when-off="utility:dislike"
      icon-name-when-on="utility:check"
      selected={isBad}
      onclick={handleBadClick}
      class="slds-m-horizontal_small"
    >
    </lightning-button-stateful>
  </div>
  <div class="slds-m-around_small">
    <lightning-input
      type="text"
      label="ひとことでよいので理由を教えてください"
      placeholder="◯◯が良かった,悪かった,困った など..."
      onchange={handleTextChange}
      disabled={isDisabled}
    ></lightning-input>
  </div>
  <div class="slds-m-around_small">
    <lightning-button
      variant="brand"
      label="フィードバックを送信する"
      title="フィードバックを送信する"
      onclick={handleSubmitClick}
      disabled={isDisabled}
    ></lightning-button>
   </div>
</template>
FeedbackStockerのJavaScript一部抜粋
export default class FeedbackStockerInputForm extends LightningElement {
  @api feedbackTitle = "feedbackTitle";
  @api recordId;
  @api fromId;
  isGood = false;
  isBad = false;
  isDisabled = false;
  isFinishCreate = false;
  freeText = "";

  get isLoading() {
    return this.isDisabled && !this.isFinishCreate;
  }
  handleGoodClick() {
    this.isGood = !this.isGood;
    if (this.isGood) this.isBad = false;
  }
  handleBadClick() {
    this.isBad = !this.isBad;
    if (this.isBad) this.isGood = false;
  }
  handleTextChange(e) {
    this.freeText = e.target.value;
    console.log(this.freeText);
  }
  async handleSubmitClick() {
    this.isDisabled = true;
    const fields = {};
    fields[FROMID_FIELD.fieldApiName] = this.fromId || "fromId未設定";
    fields[FEEDBACKTEXT_FIELD.fieldApiName] = this.freeText;
    fields[GOODORBAD_FIELD.fieldApiName] = this.isGood ? "Good" : this.isBad ? "Bad" : null;
    fields[REFERENCERECORDID_FIELD.fieldApiName] = this.recordId;
    const recordInput = { apiName: FEEDBACK_OBJECT.objectApiName, fields };
    createRecord(recordInput)
      .then(() => {
        this.dispatchEvent(
          new ShowToastEvent({
            title: "フィードバックを送信しました。ありがとうございます!",
            message: "フィードバックの送信ありがとうございます。今後の改善に役立てて参ります。",
            variant: "success"
          })
        );
        this.isFinishCreate = true;
      })
      .catch((error) => {
        this.dispatchEvent(
          new ShowToastEvent({
            title: "フィードバックの送信に失敗しました。管理者へご連絡をお願いします。",
            message: error.body.message,
            variant: "error"
          })
        );
        this.isDisabled = false;
      });
  }
}

このようなLWCを作っておけば、各種レコードのページや独自に作成した画面などに埋め込む事が可能です。

まだ運用を重ねていないので不具合はあるかもしれませんが、これぐらいの量のコードと、カスタムオブジェクトなどの設定をSalesforceのGUI上で行えば完成です。

集計したフィードバックがカテゴリ毎に格納される

どの画面やどの処理から投稿されたフィードバックなのかを整理する事も簡単にできました。さきほどのJavascriptにある、 fromId というものをSalesforceの項目として保存しています。

この項目は各種ページなどに埋め込む際に自由文として入力してもらう形にしています。たとえば「◯◯のページ」や「◯◯のフォーム入力後」などと入れてもらえれば後ほどレポートで確認する時にも整理する事ができます。

LightningページにLWCを埋め込んだ時の設定画面のスクリーンショット
LightningページにLWCを埋め込んだ時の設定画面

このスクリーンショットはLightningページというSalesforce上の画面をカスタマイズ出来る機能上で今回作成したLWCを埋め込んでいる所です。 FromIdという項目に名前を入れて作成するようにしています。

レポートで振り返りや分析が出来る

Salesforceに詳しい方であればご存知だと思いますが、Salesforceでは作成したカスタムオブジェクトのレポートを作成することも簡単にできます。今回であれば、入力してもらったフィードバックというカスタムオブジェクトに関するレポートを作成しました。先程の fromId 毎にカテゴリとしてまとめて表示するようにしてみました。

カテゴリ毎にGood/Badの分布を表示するレポートのスクリーンショット
カテゴリ毎にGood/Badの分布を表示するレポートを作成してみました

本番環境にインストール!

FeedbackStockerを本番環境にインストールし、いくつかの箇所に設置を進めています。これから多くの箇所に設置していくぞ!という段階のため結果に関してはまだわかっていません。続報をまたDevelopers Blogなどでご報告出来れば嬉しいなと思っています。

今回AppExchange開発にチャレンジ出来た事で個人的にもチームとしてもSalesforce開発の幅が一回り広がったと感じています。機能ごとに分解して開発を進めていければ、既存環境に依存しない効率的な開発が出来るのではないかと考えています。

社内アプリケーション開発だからこそフィードバックしやすい環境を

社内アプリケーションの開発は、サービス開発(freeeで言うところの、会計freeeや人事労務freeeの開発を指しています)とは異なる点が多いと思っています。

どちらがよいかという事ではなく性質が違うものだと思っています。私が大切にしているのは、「社内で開発しているからこそ遠慮のないフィードバックを集める → 自社に最適なシステムを構築、運用出来る事」です。しかし実際には使用者全員が毎回フィードバックをしてくれるわけではありません。本来の業務も忙しい中で採用に関わっているメンバーも多くいます。気になる点があったからといって、わざわざ私にチャットしてフィードバックしてくれるとは限りません。ましてや社内アプリケーションなので「使えれば問題ない」と考える人もいるかもしれません。

しかし、もしそこでフィードバックをもらうことが出来て機能を改善していければ更に効率化していけると考えています。社内の採用に関わるメンバーの時間や精度が効率化していけば、サービス開発やお客様に寄り添う時間が作れるはずです。そのためにFeedbackStockerを導入し気軽にフィードバックを送信出来る社内アプリケーションを作ろうと思っています。

GYOMUハックのメンバーを募集しています

私はfreeeのGYOMUハックというチームで採用管理システムを開発しています。セールス&マーケティングのメンバーが利用するビジネス基盤の構築や運用も行っているチームです。

今回のような開発だけでなく、社内の要望やフィードバックを受けて要件定義をする事が多いチームです。一緒に働く仲間を募集しています。興味がある方は是非応募お待ちしています!

freeecommunity.force.com