こんにちは、スマートニュース メディア事業開発の杉山 早(すぎやま さき)です。
大学時代に社交ダンスにのめり込んでそのままプロ競技ダンサーになり、その後フリーランスのダンス衣装デザイナーをやっていました。それがなぜだか3年半ほど前にスマニューのコンテンツチームで働くことになって、現在はコンテンツ監視チームの運用まわりを見つつエンジニアと一緒にアルゴリズムや業務ツールの改善を進める仕事をしています。
入社する前はバリバリの肉体派(毎日踊ったり布を切って縫ったりしていました)だったので最初にアルバイトで入った頃はITの右も左もわかりませんでした。「ダンスシューズと針と糸」を「MacBook Pro」に持ち替え、必要に駆られてシステムの処理の流れを把握して改善点を模索したり、SQLを書いてデータ分析をしたり……。試行錯誤しているうちに、いつのまにか社員になっていました。人生わからないものですね。
最近SlackとAirtableをZapierで連携させた業務ツールを作ってチームで運用を始めたら、「そのやり方書いてよ!」と言われたので、今日はそのあたりを紹介します。非エンジニアで、なんとなくスプレッドシートでデータ管理をしたりしていて、ITの便利なサービスには関心があるけどコードは昔HTMLとCSSかじったくらい、いちいちマクロ組んだりGoogle Apps Script(GAS)書いたりPython勉強したりせずにサクッと自動化とかできないかな……というようなことを思っている人、つまり1~2年前の私のような人が対象です。なるべくみなさんの仕事に明日から役立てられるようなものを目指して、詳しくお伝えしたいと思います。
目次
- 目次
- チームのミッションと課題
- Slackのスタンプがトリガー、Airtableにデータ送信
- ここまでの振り返り
チームのミッションと課題
SmartNewsは機械が自動的にコンテンツを集め、分析し、適切なチャンネルに振り分けて配信しているサービスです。 配信する記事を人が選ぶ必要はなく、寝ている間もずっと止まらずに最新のコンテンツを配信し続けています。とても便利なこの仕組みなのですが、しかし機械も完璧ではないので、必ず一定の確率で間違いが起きます。例えば、「政治」というチャンネルに「今月のおすすめコスメ」の記事が出てしまう、というようなケースです。
私たちコンテンツ監視チームのミッションは、大きくふたつ。ひとつめは、日々スマートニュースで配信されているコンテンツをチェックし、このような間違いがあったらその場で修正して正しくユーザーさんに届くようにすること。もうひとつは、そのような間違いを今後なるべく減らしていくためにエンジニアチームと協力してシステムを進化させることです。
Slackに残される大量のフィードバックに対応しきれない、優先順位がつけられない問題
コンテンツ監視チームの立ち上げ当初から、日々のモニタリング結果をメンバーに都度Slackで報告してもらう運用をしていました。それを元に設定の間違いを修正したり、エラーをエンジニアにフィードバックしたり、媒体社さんにご連絡をして修正対応してもらったりと細かく対応していきます。コンテンツが届く最後の「タッチポイント」を見守るメンバーからのフィードバックは、コンテンツを適切に配信するためには大変重要な情報です。
しかし、SmartNewsは日々膨大な数のコンテンツを配信しており、モニタリングチームの目に触れて何かしらの報告が上がってくるものに絞っても1日に100や200は軽く超えます。増えていくコンテンツに対して限られた人数で効率よくチェックし対応していくには、このやり方では限界がありました。またコメントの形で残されるフィードバックだけでは、それがどの程度の規模や頻度で起きている問題なのかなど、対応の緊急度をはかることが難しく、都度手を止めて詳しい調査をする必要がありました。
もちろんシステムにもログは残っていますが、修正結果など作業内容自体のログはわかっても「なぜ」そうしたかはデータ上には残っていません。この「なぜ」の部分を定量的に把握し効果的な改善につなげたい、という課題を長い間持っていました。
やりたいこと:「Slackのコメント」を「データ」の形に置き換えて蓄積する
整理すると、今回実施した改善はこのようになります。
目指すもの
ひとつひとつのフィードバックを有効活用しシステム改善の効率を上げる
問題点
大量に上がるモデレーターからのフィードバックがSlackのコメントの形でしか残っておらず、把握しきれていない
やること
言葉で書かれたフィードバックコメントを、なるべく手間なくデータベース化し、定量的に把握できる形にして蓄積する
Slackのスタンプがトリガー、Airtableにデータ送信
作業の概要
まず作業に入る前に、最終的にどんなデータをどのような方法で溜めるのかを整理します。
やりたいことは前述のとおり「Slackに言葉で書かれたフィードバックの必要情報を、なるべく手間なく『データ』の形に置き換えて溜めていく」ことです。スプレッドシートに手入力するとかフォームをいちいち開いて記録する、というような方法ではなく、今までどおりのSlackへの投稿になるべく簡単な一手間だけでこれができるようにしたいと思います。
そこで「Slackのメッセージにリアクションスタンプをつけること」をトリガーにして、自動的にメッセージ内の必要情報を取得しデータベースに送る、という仕組みを作りました。
使用ツール: Airtable・Zapier
データを溜めていく場所としてAirtable、Slackとの連携にZapierを使用しました。どちらも全ての機能を使うには有料プランになりますが、無料プランでも一定の機能は使えます。
Airtable
Airtableはスプレッドシートとリレーショナルデータベースを組み合わせたようなサービスです。数万件単位のデータ処理には向いていないスプレッドシートとは異なり、重くならずにサクサク動き、見やすく扱いやすいUIが魅力。スマートニュースでは法務やメディアパートナーリレーションなど他のチームでもすでに使用されており、導入のハードルが低かったこと、社内に使い方に詳しい人がいたこともありこちらを使うことにしました。
Zapier
複数のサービスやアプリを連携させて、AをしたらBをする、という自動化の仕組みを非エンジニアにも簡単に作れる素敵なサービスです。スマートスピーカーと連動させるときの定番サービスIFTTTも有名ですが、ZapierはIFTTTより連携できるアプリ数が多く、いくつものアプリを組み合わせた複雑なフローを作ることができます。今回はSlackとAirtableのつなぎ込みにこちらを利用しました。
Airtableを構築
では、ここからは具体的な手順です。まずはAirtableの基本的な使い方と合わせて、実際にやった内容を紹介します。
Workspaceの中に新規Baseを作成
Airtableには、まずWorkspaceというスペースがあり、その中に更にBaseという作業スペースが作れます。Workspaceは会社や部門など大きなグループ単位でBaseを集めた場、Baseはチームや用途によって使い分けた具体的な作業場所という形です。JP Content(私の所属するチーム)というBaseを作り、その中に必要なテーブルを構築していきます。
AirtableはBase内のテーブルをリレーショナルにして、あるテーブルのカラムで他のテーブルのデータを参照する、という使い方ができるので、メインのフィードバックを溜めるテーブルの他、参照用のデータを溜めておくテーブルも作ります。
Base内に必要なテーブルを作成
今回の作業で作ったテーブルは以下。
テーブル名 | 内容 |
---|---|
Feedback | フィードバックを溜めていくメインのテーブル |
Channel list | 監視チャンネル情報の一覧 |
Site list | 記事の配信元媒体リスト |
Topic | フィードバック内容の分類項目一覧 |
もしスプレッドシートなどですでにテーブルがある場合、CSVデータにしてインポートすれば、簡単にデータも移行できます。
Channel list とTopicは元からあったデータをインポートして、FeedbackとSite listは報告に応じてレコードが増えていく予定なので、まずカラムだけを先に作りました。
フィードバックとして記録するのに必要な要素を書き出して、それをFeedbackテーブルのカラム名にします。必要な項目はこのようになります。
カラム名 | 内容 |
---|---|
Created time | 報告の日時 |
Reporter | 報告者 |
Channel | 監視していたチャンネル |
Site | 媒体サイト名 |
Note | フィードバックコメント |
Topic | フィードバックコメントの分類項目 |
URL | 記事のURL |
Title | 記事のタイトル |
URL->HOST | ホスト+ドメインの形にURLを変形して入力 |
Slack | 取得したSlackメッセージのURL |
Airtableの設計は基本的にはスプレッドシートと同じようにすればよいのですが、スプレッドシートと違うAirtableならではの機能がいくつかあります。どれも使いこなすと大変便利なので、少し解説します。
Airtableの便利機能① カラムに「type」を付与できる
Airtableは、カラム右側の▼内Customize field typeからtypeを選択できます。選択したtypeに応じて自動的にレコードが変換されます。例えばMultiple selectを選べば選択項目が設定でき、Collaboratorを選べばBaseのユーザーを自動的に選択肢にしてくれます。
Airtableの便利機能② レコードを他のテーブルとLinkできる
リレーショナルデータベース的な使い方ができるArirTableの1番特徴的な機能がこちら。カラムのtypeで Link to another recordを選んでリンクするテーブルを指定すると、指定したテーブルのkeyとなるレコードを参照して表示することができます。SQLで言うJOINみたいなものですね。
レコードをLinkすると、参照元のテーブルにも自動的に新しいカラムが追加され、紐付いているレコードが参照できるようになります。
Airtableの便利機能③ Viewを作成して自由に切り替えられる
大量のデータを入力していくと、それをいろいろなグループにまとめてそれぞれチェックしたり、ソートしたりなど整理したい場面が増えてきます。そのときにいちいちフィルターを編集するのは面倒です。Airtableでは簡単にデータをGroup byで項目ごとにまとめて表示することができ、さらにそのようにフィルターした結果をViewとして保存し、いつでもさっと切り替えることができます。
作成できるViewはGrid、Form、Calendar、Gallery、Kanbanがあり、フィルターしたViewを保存する他にも、Kanban形式にしてタスク管理に利用する、Calendarにしてスケジュール管理に使う、といったことも可能です。
ZapierでSlackとAirtableを連携
データを溜めるためのAirtableができたら、いよいよ自動化の仕組みを作っていきます。 ZapierのHome画面右上Make a Zap!からから新規zapを作成します。
トリガーを指定する
Zap作成画面では、必ず最初にトリガーとなるアクションを選びます。「これをしたら、こうする」の「これをしたら」部分です。どんなアクションをトリガーに指定できるかは連携するアプリの種類によって異なります。今回はSlackのリアクションスタンプをトリガーにします。
このあとの画面でトリガーになるリアクションスタンプの種類、Slackチャンネル、ユーザーの指定が任意でできます。何も指定しない場合すべてのリアクションがトリガー対象になるので、誤作動のないように運用方法によって適宜絞り込みをしたほうがよいでしょう。今回は特定のスタンプとChannelをトリガーにするよう設定しました。
もっと細かいフィルター条件を指定したい場合、このあとのStepでFilterを追加することで、さらに絞ることも可能です。例えば、リアクションスタンプがついたメッセージ内に〇〇というワードがあったものだけをトリガーにする、というようなものです。
Airtableに新規レコードを作成
トリガー設定ができたら、次にアクションを指定します。「これをしたら、こうする」の「こうする」部分です。今回やりたいことは「Airtableに新規レコードを作成すること」なので、ActionでAirtableを連携し、Create Recordを選択、AirtableのアカウントをさきほどのSlack同様に連携します。
連携が完了すると、テーブルのそれぞれのカラムにどんなレコードを入力するのかを指定する画面に移ります。
トリガーのスタンプをつけたSlackメッセージから、いろいろな情報を自動的に取得して選択することが可能です。SlackはURLを貼るとプレビューが出ますが、そのOGP情報も利用できるので、タイトルやサイト名はそこから引っ張ってきて使用しています。いちいち記録のためにコピペする必要もないし、表記ゆれも防げるので大変便利です。
Siteのカラムは先ほどの手順に従いSite listのテーブルにリンクしています。もし初めて入力されるサイト名だった場合、自動的にSite listテーブルのレコードが新規作成され、以後同じサイトのレコードが増えると勝手にそこに紐づくようになります。つまりフィードバックを送れば送るほど、自動的にSite listが完成していく仕組み。テクノロジーって素晴らしい。
また、自動でうまく取得できなかったときに確認できるように、「Slack URL」というカラムを作って元のメッセージのURLも入れておくと便利です。Slack URLはこの画面でMessage Permalinkを選ぶと取得できます。
Formulaを使ってURLからホスト+ドメインを抜き出す
Airtableのカラムでは、さまざまな関数や式を使ってデータを変形することもできます。ちょっとだけレコードを変形して記録したい、というときもこれで自由自在です。
自動入力できたカラム
カラム名 | 内容 | 自動取得 |
---|---|---|
Created time | 報告の日時(レコード作成時に自動的に記録) | ◯ |
Reporter | 報告者 | ◯ |
Channel | 監視していたチャンネル | ✗ |
Site | 媒体サイト名 | ◯ |
Note | フィードバックコメント | ◯ |
Topic | フィードバックコメントの分類項目 | ✗ |
URL | 記事のURL | ◯ |
Title | 記事のタイトル | ◯ |
URL->HOST | ホスト+ドメイン | ◯ |
Slack | Slack URL | ◯ |
ということで、テーブル内のカラム「Channel」と「Topic」以外はすべて自動入力することができました!
「Channel」と「Topic」の二つはどうしてもSlackから取得できないので、あとから少しメンテナンスが発生してしまいますが、最初から手入力するよりとても楽。スプレッドシートに手で入力してデータを溜める、などの面倒な手順を踏むと作業が億劫になり結局やらなくなってしまったりしますが、スタンプをぽちっと押して自動で送れるので、無理なく続けることができます。あとぽちぽち送るの、ちょっと楽しいです。
Formを用意して直接レコードを追加できるようにする
Slackとの連携でかなりの部分を自動化することができましたが、念のため別途入力フォームも用意しました。フォームはViewのひとつとして作成でき、URLでフォームの画面だけをshareすることが可能です。
Airtableは権限設定がわりとざっくりとしていて、1つのTableにだけ編集権限をつける、といった細かい使い分けができないのですが、フォームを経由すれば、Baseの編集権限を持たないメンバーもレコードが作成できます。
Airtableの新規レコード作成をSlackに自動通知
最後に、報告者がきちんと報告完了したか確認できるように報告内容の通知をZapierで設定してSlackに送るようにしました。やり方はここまでとほぼ同じで、もう一つ別のZapを新規で作成し、トリガーをAirtableのNew RecordにしてSlackの部屋を指定しメッセージを送信するようにします。
ここまでの振り返り
できたこと
メンバーの作業コストを大きく増やすことなく、フローの情報をストックに変換して溜めることができるようになり、これは非常に効果的でした。約2ヶ月運用していますが、続々とデータが溜まってきており、一覧管理することで「いつ・どこで・どのような問題が起きたか」を格段に把握しやすくなりました。また、サイトごとやトピックごとに情報が紐付いているので「ここは繰り返し同じ問題が報告されているので早めに対応するべき」など定量的な優先順位の判断ができるようになり、適切にコンテンツをお届けするためのより細やかな対応が可能になりました。
できなかったこと、これからやりたいこと
さっきも書いた通り、ChannelとTopicとの紐付けはまだ自動化できておらず手動でメンテをしています。また、人間の送ったメッセージは大抵上手くいくのですが、BotからのメッセージをZapierでAirtableに送ろうとしたとき、上手く情報が取得できるものと取得できないものがありました。連携できないBotは、運用が安定してきたら改修可能かどうかエンジニアに依頼したいと思っています。目指せ完全自動化。
現在は、溜まったデータを人の目で見てピックアップして対応していますが、いずれは「フィードバックが同じトピックで◯件溜まったら自動的に通知する」といった仕組みを作ったりして、人が目で見て優先順位を判断するコストを下げていきたいと考えています。
最終的には、人が見て直さなくても常に問題が起きない仕組みを作るのがゴール。人間の定性的な違和感をいかにデータの形に換えてシステムに教え改善していけるか、これからもチャレンジを続けていきます。
SlackとAirtableのZapier連携のやり方、ちょっとマニアックすぎたような……と心配ですが、明日からの誰かの業務のお役に立てたら嬉しいです。「ここわからないからもっと詳しく教えろ」というリクエストや「もっといいやり方があるよ!」などの情報もお待ちしています。非エンジニアなりに頑張って工夫して効率化や自動化に取り組んでいる勢のみなさま、ぜひランチご一緒しましょう。SmartKitchenでお待ちしています!