voicyの検索改善について

はじめに

こんにちは! 株式会社Voicyでデータアナリストをしている翔斗です。

今回は検索改善の話をしていきたいと思います。

検索改善の種類

画像はVoicyの検索を改善するにあたって分類したものになります。

voicyでは「見つける」というタブから検索することができます。 その検索結果にはチャンネル/放送という順に一列に並びます。 「英語」というワードの検索をすると画像のように並びます。

同じ窓からチャンネルと放送を検索するため、何を目的として検索しているのかを把握する必要が出てきます。 また、カテゴリ検索やハッシュタグ検索などの種類もあるため検索改善箇所を上げるとキリがありません。

UIを変更するといっても

  • 放送とチャンネルのタブを分けて表示する
  • 人気な放送と最新放送など条件でタブを分けて表示する
  • チャンネルカードのデザインを変更する

などがありますし、ほかの箇所でも

  • カテゴリ分類を変更する
  • 検索結果の並び替え最適化をする
  • 検索結果がないという状況を無くす(0マッチ問題)
  • 年齢・性別などで結果をパーソナライズする
  • 過去の聴取・検索などから求めている結果をパーソナライズする
  • etc

とさまざまな種類の改善が考えられます。 この中から効果のあるものを選定し施策として実行していく必要があります。

現状把握

指標を決めたらvoicyの検索が今どんな状態であるかを把握します。 現在一番ボリュームが大きいのは通常検索になります。

通常検索の詳細を見ていくと下記のようなことが確認できました。

  • 検索ワードの多くが1〜10回程度しか検索されていない
  • チャンネルを検索しているであろう検索ワードでもチャンネルが表示されず、放送のみが結果として出ていることがある
  • チャンネルが表示されない多くの原因が表記揺れ(普段のSNSとは違う名前での活動や略語・ローマ字とひらがなの揺れ...等)
  • 放送よりもチャンネルを目的とした検索の方がタップ率も再生率も高い

この結果から、チャンネルと出会わせる体験を向上させるのが重要そうだというのがわかりました。

Voicyの検索改善における指標

いくつもの改善施策から実際に実行するにはユーザの目的を整理し、指標を決める必要があります。

voicyでは「人を届けるメディア by voice」と社長の緒方がよく言うように、発信するパーソナリティをリスナーに見つけてもらうと言うのが重要になります。

現状の課題にもチャンネルが表示されないというものが確認できているため、まず出会ってもらうということを目標にチャンネルのタップ率を第1の指標とし、その先に聴取率・継続率とファネルがひいていきます。

仮説・施策

チャンネルが表示されない という問題はいわゆる0マッチ問題と呼ばれるものになります。

解決手段としては

  • 表記揺れなどの曖昧な検索でも結果を補完して表示する
  • 検索ワードに近いワードの結果を代わりに表示する
  • 結果なしの場合、検索に関係なくレコメンドをする

などで表示結果0を減らしていくことができます。

効果測定

施策の効果は主にA/B テストによって測定しています。

Voicyでは祝日や連休には聞かれなくなってしまったり、パーソナリティのSNSの拡散や会社のPR状況などで検索ワードのボリュームが変化することがあります。このような状況において、施策の有効性を施策前後で証明するのは難しいことがあります。 そのため検索施策に限らず多くの施策で、ABテストを利用することでその施策のみの効果を測定しています。

具体的には

  1. 施策対象のユーザー全体をランダムに 50:50 に割り振り半分のチームに施策を行う
  2. 施策を実行しない側の前後変化がないことを確認する
  3. 上記確認の上で、施策チームの前後変化を確認し、有意差があるか判断する。(前後変化がある場合その変化結果を施策実施チームでも考慮し有意差があるか確認する)

次回

今回はどんな手順で検索を改善していくか記載したので次回以降は、結果0を減らしていくためにどんな施策を行ったのかを記載していきたいと思います。

IntelliJ IDEAのHTTPクライアントが使いやすい話

はじめに

バックエンドエンジニアのなだまるです。今回は開発環境としてのHTTPクライアントの話をしてみようと思います。

APIの開発をしていて、エンドポイントの動作確認を行う際、 もし、お手元でお使いのエディタがJetBrains製品ならなんと!実はHTTPクライアントが付属してます! 結構使いやすく愛用しているので、紹介してみることにしました。 ちなみに私は以前はPostmanを使っていました。

準備

準備と言っても特段ないんですが、リクエストを記述するためのファイルを作成します。 .restか、.httpとして作ればHTTPクライアントがそれと認識してくれます。 なので、自分で適当にファイル名をつけて作成するか、Scratchファイル作成から作ればOKです。 ScratchファイルはMacなら Shift+Command+N から HTTP Request を選択します。

image.png

文法

IDEAのHTTPクライアントはGUIがあって画面のどこに何を書いてという形ではなく、スクリプトチックです。 基本はこんなかんじ↓

Method Request-URI HTTP-Version Header-field: Header-value

Request-Body

やってみる

上記の文法になぞらえていくつかリクエストの例を並べてみます。

// 普通のGET
GET http://example.com

### 

// Bodyを指定してPOST
POST http://example.com/api/users
Content-Type: application/json

{
  "id": 1,
  "name: "natacon"
}

###はファイル内で利用できるセパレーターで、同ファイルにリクエストを複数書けます。 ただのGETは特段説明不要ですね。 POSTのほうも読んだままですが、一点挙げるとしたらHeader-filedとRequest-Bodyの間は一行あける必要があります。

使ってみると地味にうれしいところがあって、

image.png

こんなふうに実行した結果を履歴で勝手に保存しておいてくれて、かつ行数のとなりに出ているアイコンからこの結果同士を比較する画面を簡単に開けたりします。このあたりは開発中の変更が見つけやすくて重宝します。 邪魔な方は@no-logをつけてあげるとでなくなります。

// @no-log
GET http://example.com

変数が使いやすい

Postmanとかでももちろんあるんですが、エンジニアの手に馴染む形ではないかなーというところ。 IDEAではJSON形式で設定できるようになっていて、http-client.env.jsonもしくはhttp-client.private.env.jsonファイルをプロジェクトに配置することによって変数定義を行えます。

例えばこんなふうに環境ごとのリクエスト先を定義しておいて、

{
  "local": {
    "baseUrl": "localhost:8080/v1/api"
  },
  "dev": {
    "baseUrl": "https://dev.example.com/v1/api"
  },
  "stage": {
    "baseUrl": "https://stage.example.com/v1/api"
  },
  "prod": {
    "baseUrl": "https://example.com/v1/api"
  }
}

リクエストファイルはこうする。 変数参照は{{variable}}として二重波括弧で囲む。

GET {{baseUrl}}/users

こうしておくと実行時に下記のようにどの変数割り当てて実行する?と聞いてくれるので実行したい環境の切り替えも楽。 image.png

おまけ

私はいまのところあまり使うことがなかったのですが、レスポンスの検証も行えます。 軽い実装例だと、こんなレスポンスがあったとします。

{
  "users": [
    {
      "id": 1,
      "name" "natacon"
    },
    {
      "id": 2,
      "name" "yuichi"
    }
  ]
}

それに対しリクエストを下記のようにするとusersオブジェクトの要素数を取得できます。 JavaScript ECMAScript 5.1で書けます。

GET http://example.com/api/users

> {%
  // IDEA側にresponseオブジェクトを作ってくれてる
  client.log(response.body.users.length)
%}

assertとかを使えるので、こういった値などをテストするように書いておけば、ミニマムに手元で一気にエンドポイントの動作確認を行えたりするのです。

おわりに

社内勉強会でもJetBrains製品マジおすすめだよという発表をしたり、またこの記事書いたりほんとズブズブの関係の私なのですが、マジオススメ。

【ナレッジをためる】施策結果の振り返りを1つのスプレッドシートにまとめて良かった3つのこと

こんにちは!Voicyデータアナリストのたからっちです。

データ分析を用いて、ユーザーがよりVoicyを快適に使えてもっと好きになっていただけるように日々業務にあたっています。

今回は、施策結果の管理方法とそれを行って良かった3つのことについて書いていこうと思います。

内容は、ごく当然のことで既に多くの方が取り組んでいるかと思いますが、まだ取り組んでいない方の参考に少しでもなれば幸いです。

これまで

何かしらのサービスを提供している企業で働いている多くの方は、施策を行ったことがあると思います。そしてほとんどの場合は、施策結果の振り返りが行われるかと思います。

Voicyもそうでした。

ただし、振り返りを行うまでではなく、振り返りの後に問題がありました。


〜〜施策結果の振り返り時〜〜

私「今回の結果はこうでした。新規ユーザーの50%が利用しているので結構利用されていますね!」

Aさん「おお、良い感じだね。ちなみに既存ユーザーはどう?」

私「既存ユーザーは10%の方しか使われていないですね、、」

Bさん「既存ユーザーはまた状況が違うから使われにくいのかなー」

Aさん「おっけい、とりあえず新規ユーザーには利用していただけているから、また既存ユーザーの体験をよくする施策考えていこう!」

私「そうですね!」

〜〜数日後〜〜

Aさん「前回の施策結果の振り返りどこにあったっけ?報告資料に載せたくて」

私「ちょっと待ってください、確かこの辺のスラックでやりとりしていたと思うので探してみます」

Aさん「よろしく!こっちも探してみる」

私「ありました!こちらですね」

Aさん「ありがとう!」

〜〜数週間後〜〜

Bさん「新しい施策を考えようと思っているんだけど、そういえばあの時の施策結果どうだったっけ?ちょっと参考にしたくて」

私「確か数週間前のやりとりなので、この辺にあったはずで、、ありました!こちらです!」

Bさん「ありがとう!」


もうお分かりかと思いますが、上記のようなやりとりが度々起こってしまっていました。 これでは、お互いの時間も勿体ないですし、ナレッジも溜まっていきにくいです。

ということで対策を考えました。

やったこと

やったことは非常に単純です。

施策結果の振り返りを1つのスプレッドシートにまとめるようにしました。

どういうことかというと、振り返りごとにスプレッドシートを新しく作ってそこにグラフやらデータやら考察やらを書いて、それを他のチームのメンバーに共有するのですが、そのスプレッドシートの重要な部分だけをかいつまんでまとめシートに書いていくようにしました。

まとめシートに記載している内容は以下の項目です。

  • 記載日
  • 記載者
  • プラットフォーム(iosandroid、webなど)
  • セグメント(新規、既存など)
  • カテゴリ(聴取率、継続聴取率など)
  • 画面(ホーム、オンボーディングなど)
  • 仮説
  • 施策内容
  • 結果(結果詳細のスプレッドシートリンクも付与)
  • 考察

改めて記載項目を書いてみると多く感じますが、まとめシートに記載する段階ではほとんどの項目は既に決まっているor別のスプレッドシートで書いている内容なので特に時間がかかるわけではありません。

地味ですが、このまとめシートは以下がポイントになっています。

  • 記載者を書くことで、後々詳細を確認したいときに誰に聞けば良いのかが明確になる

  • 仮説〜考察までを書くことで、 このまとめシートを見ただけで施策の一連がほぼ全てわかる

  • 結果は簡潔に重要な部分だけ、かつなるべく数値も書いておくことで、どれだけの効果があったのかが明確にわかる

正直、書いてみると当たり前のことすぎて恥ずかしくなってきたのですが、もしこの3つがなかったらこのシートの利便性がかなり弱まってしまうと感じたので書いておきました。

良かったこと

良かったことは大きく3つです。

  1. 施策結果を探すためのやりとりが減って色々と快適になった

  2. 誰でも、とりあえずこのシートを見れば大体の施策結果がわかる

  3. 過去施策の振り返りにも触れる機会が増えてナレッジになっていく

1つ目については、単純にやりとりの回数が減ったことで、振り返りが欲しい人も探す人もお互いに手間が減ったのと、早く探して共有しないと!という焦り?も減り快適になりました。

2つ目については、新しく入社された方や他チームで過去施策の結果を見たいとなった時に、こちらにまとまっていますよ!とまとめシートをとりあえず渡すことで、大体の施策結果がパッとわかるようになりました。

3つ目については、まとめシートがあることで過去施策の振り返りも目にする機会が増えて、今やろうとしている施策って本当にいいんだっけ?と考えることが増えました。単純に施策をやって振り返って終わりだった場合は過去の施策結果に触れることがないですが、まとめられていることでそういえばこの施策ってこうだったな、と気づくことが出てきます。これを繰り返すことでナレッジになっていくのではないかと感じています。

最後に

このまとめシートで現状は大きな問題はないのですが、今後数年かけて施策がさらに増えていくと検索性が悪くなったりはありそうだなーと思いつつも、新しい項目を追加していってまとめる手間が増えて更新しなくなったり、ここに時間がかかってしまう懸念もあるので、とりあえずはこのまま使っていきたいと考えています。

また実は、このフォーマットを施策だけでなく日頃のデータ分析からの知見でも活かせそうだなと考えて、施策以外のデータ分析からの気づきみたいなことも別タブでまとめるようにしています。

ナレッジをためていくのはなかなか難しいことだなと感じていますが(特に自分だけじゃなく他のメンバーも一緒にとなるとさらに)、読者の皆さんは何か取り組まれていることやおすすめの方法はありますか?

今後もより良いサービスを作っていくためにもナレッジをためる仕組みづくりを意識していきたいなと思います。

Voicyエンジニアの輪読会: 分厚い技術書も、みんなで読めばこわくない

こんにちは!

SREのせんちゃんこと、千田です (@thousan_da) 。

本記事では、Voicyのバックエンドエンジニアが実施している輪読会を紹介します。

こちらの内容は音声でもお届けしています。耳からのインプットする方が得意だよという方は、以下のリンクからお聞きください!

voicy.jp

それでは本題です。

概要

Voicyのバックエンドエンジニアは、技術書の輪読会を行なっています。

主な目的は以下の通りです。

  • エンジニアとしてのレベルアップ
  • 同じ本から学ぶことで共通認識を作る
  • 他のメンバーの着眼点を知る = コミュニケーション

直近で読んでいる本は『Kubernetes完全ガイド』。

インプレス社から出版されている一冊です。著者はサイバーエージェントの青山真也さん。

全20章で構成されており、紙の本で668ページ、Kindle版は1249ページというボリューミーな本です。この本に限らず、インプレス社の技術書はレベルの高い骨太本が多い印象があります。

Voicyのサービスの多くはKubernetesで動作しているため、この本が選ばれました。

次の章から、本の選出方法も含めた輪読会の流れを紹介します。

輪読会の流れ

週に1回1時間、オンラインで集まって行っています。1冊を終えるのにかかる時間は約6週間〜12週間と、選ばれた本のページ数によってまちまちです。

読む本を決める

まず、最初の週に輪読会で読む本を決めます。選書には「ビブリオバトル」を採用しています。

以下、Wikipediaからの引用です。

ビブリオバトル(Bibliobattle)は、京都大学から広まった輪読会・読書会、または勉強会の形式で「知的書評合戦」とも呼ばれている。

ビブリオバトル公式ルール

  1. 発表参加者が読んで面白いと思った本を持って集まる。
  2. 順番に1人5分間で本を紹介する。
  3. それぞれの発表の後に、参加者全員でその発表に関するディスカッションを2〜3分間行う。
  4. 全ての発表が終了した後に、「どの本が一番読みたくなったか?」を基準とした投票を参加者全員が1人1票で行い、最多票を集めた本をチャンプ本とする。

厳密に上記の通りに行っているわけではありませんが、各エンジニアが輪読会で取り上げたい本を持ち寄り、その本の内容や、読むとどんな良いことがあるのかをプレゼンします。その後、質問があれば答えたり、感想を言い合ったりします。

全員のプレゼンが終わったら投票タイムです。1人1票で投票を行い、最も得票数が多かった本が採用されます。

集まってディスカッション

2週目以降は、事前に決めた章を全員が読んだ状態で集まります。1章だけの場合もありますし、何章かまとめての場合もあります。

まず、集まってから最初の15分程度で、各自その章を読んで学んだことや疑問に思ったことなどを書きます。 オンラインホワイトボードツールのMiroを使ってこんな感じで付箋に記入しています。

輪読会で使っているオンラインホワイトボード

その後、その日のファシリテーターの進行のもと、各々が書いた内容を順に話していきます。全員が話し終わったところで特に気になったポイントについて感想を述べたり、質問をしたりして深掘りを重ねていきます。

このとき、本で学んだことを踏まえて運用中のシステムのここが問題だよねということを話したりもします。

上記の『Kubernetes完全ガイド』の例で言えば、この部分の設定値はこれが推奨されているけれど、現状そうなっていないよね、という話などです。また、その前に実施していた『ドメイン駆動設計 モデリング/実装ガイド』では、このAPIのパッケージ構成は本来こうあるべきだよね、という話をしたりしていました。

輪読会をしてみて

まず、当たり前ですが技術書を読むことで知識が増えました。知識が増えることで、できることが増えたり、現状の課題が見えてきたりします。この点に関しては、輪読会を行ったからというよりも、技術書を読んだからという理由が大きいです。

では、ただ読むだけでなく輪読会という形式にしたことでよかったと感じる点が以下です。

  • 詳しいメンバーの知識をシェアしてもらうきっかけになる
  • 強制的に読めるw

詳しいメンバーの知識をシェアしてもらうきっかけになる

新しく入社したエンジニアやまだ経験の浅い若手は、分からないことがたくさんあります。体系的な知識を得ようにも、社内でドキュメントが完璧に整備されているということもなかなかないでしょう。そんなとき、漠然となんとなく分からないのですが、、、と質問することは難しいですが、輪読会を通してであれば、自然と知識をシェアすることができます。自分自身、輪読会をきっかけに先輩エンジニアたちが話した内容から学んだことがたくさんあります。

強制的に読める

分厚い技術書をひとりで読み切るのは簡単ではありません。読めばありがたい教えがあり、自分のためになると分かっていても読めないのが人間というものです。毎週、輪読会という締め切りが訪れることで、強制的に技術書を読むことができます (笑)

最後に

というわけで、これを読んで気になった方は、ぜひ輪読会をしてみてください!

今回は技術書の輪読会という文脈でしたが、単にビブリオバトルをするだけでも楽しいです。

職場で実施するのが難しいという方は、プライベートで仲が良い方と技術書以外の本でやってみるのも良いと思います!

VSCodeを使った簡単なjsonダミーデータの作り方

はじめまして!Voicyのフロントエンドエンジニアのしーちゃんです。

今年の4月にVoicyに入社しました! まだ在籍期間は2ヶ月弱ですが、体感としては、4ヶ月くらい経ちました。 刺激的な人々に囲まれていて、毎日楽しく経験を積んでいます。

今回は、VSCodeを使った簡単なjsonダミーデータの作り方についてお話しします。 結論から言うと、マルチカーソルとvscode-randomを使うと非常に簡単にダミーデータを作れると言う話です。

間違いなどあればご指摘いただけると大変助かります!

はじめに

フロントエンドの実装の確認をしたいとき、ダミーデータが必要になることがあります。 私は以下の状況になったことがあります。

「フロントエンド、バックエンドで同時に開発を進めた。フロントエンドはできたけど、バックエンドが未実装。」

「フロントエンド単体でテストをしたい!」

そのような実際のデータを使えないときに、ダミーデータを作成しますよね。 VSCodeとその拡張機能を使えば、早ければ1分で様々なダミーデータが作れます。

作りたいダミーデータ

複数のユーザー情報のダミーデータを作成します。

[
  {
    "name": "Randall Armstrong",
    "birthDay": "30/10/2022 16:19:03",
    "country": "Pakistan",
    "mail": "zumofi@roleg.tf"
  },
...
]

使う機能

VSCode標準機能

直線上にマルチカーソルする

  1. Shift + option + ドラッグ

qiita.com

ショートカットキーで同じ文字列、数値などの範囲を全て選択してマルチカーソルにする

  1. 文字列を選択する
  2. command + Shift + Lを押下
拡張機能

vscode-random

文字列や、数値、日付などをランダムに入力できます。

  1. 入力したい位置にカーソルを合わせる
  2. コマンドパレットからrandomと検索する
  3. randomで入力したい文字列や数値、メールアドレスなどのパターンを選択する
  4. 指定したrandomな値が入力される

作り方

手順

  1. 作りたいデータの数だけ改行する
  2. マルチカーソルで複数行にカーソルを合わせる(Shift + option + ドラッグで複数行選択する)

  3. コマンドパレットからrandom: Nameを入力し、適当なデータを入力する

以下入力中の画像イメージです。

マルチカーソルでの入力

おわりに

今回はVSCodeを使った簡単なjsonダミーデータの作り方を紹介しました。 フロントエンドの開発において、ダミーデータは必ず使うと思います。

私はマルチカーソルの存在を知ってからVSCodeを好きになりました。 慣れれば、手早く大量のダミーデータが作成できるようになるので、ぜひ使ってみてください〜!

パーソナリティの復帰をSlackで把握できるようにした話

こんにちは! 株式会社Voicyでデータアナリストをしている翔斗です。

本日は「Voicyのパーソナリティが復帰してきた際にスラックで通知を入れるようにした」という話です。

背景

Slackを利用している多くの会社(もしくは個人)では、何かしら自動で通知されるよう設定してるところは多いと思います。 Voicyも類にたがわず、画像のようにいくつかの行動の際にSlackに通知を行っています。

放送を初めて公開した際・プレミアムリスナーを開始した際・リスナーがコメントした際etc

しかし、現在通知していた条件ではパーソナリティが開始した時は把握できるのですが、放送が減っていたり、久しぶりに復帰したりした時には目視でしか気付くことができない状態でした。

やりたいこと

Voicyに戻ってきてくれたPがいた際にその存在を社員に知らせる

Voicy にはパーソナリティサクセスというパーソナリティをサポートする部署があります。そこでは、パーソナリティが放送を始めたタイミングで「サポート終わり」という状態ではなく継続的にパーソナリティがどんな状態かを確認しています。 ただ、どうしても日々発信をしている人に目が行きがちで、やめてしまった人が戻ってきた事に気づかないことも多々あります。

そのため、一定周期離脱したパーソナリティが戻ってきてくれたことを通知で知らせようと考えました。また、日頃続けてくれているパーソナリティが急にやめた際などにも気づけるようにしました。

前提知識

今までの通知はアプリ上で行動があった際などに直接Slackへ送られるものでしたが、今回行いたいのは、複数条件(変更可能性があるもの)の通知になります。 そのため、BQで通知対象になるパーソナリティの情報を入れたテーブルを毎日作成し、BQ上で定期的にSlackへ通知するようにしました。

過去にこちらでも記載しましたが、Voicyのデータ分析基盤はBigqueryになっています。 収録・再生アプリの行動ログやWebのデータ他スプレッドシートなどもデータレイクとしてBigqueryに集約しています。

行ったこと

  • テーブルの作成
  • cloud functionの設定
  • Pub/subの設定
  • cloud schedulerの設定
  • テーブルの定期実行

まずテーブルを作成します。

次にcloud functionを設定します。 トリガーをHTTPにしpython3.9で下記コードを入力します。(この時HTTPはcloudIAMの承認を必須にしてください)

from google.cloud import bigquery

def main(request):
    client = bigquery.Client()
    table_id = "テーブル名"
    # 射影するクエリ文を作成
    query = "クエリ"
    query_job = client.query(query=query)
    #スラック通知
    slack = slackweb.Slack(url="通知を送りたいSlackのチャンネル")
    try:
        for df in query_job:
            message = "メッセージ内容" 
            slack.notify(text=message)
    except Exception as e:
                print(e)
                pass
    return message 

requirements.txtには下記を入力します。

bigquery
slackweb

cloud functionの設定が終わったらPub/subの設定です。 配信タイプをpushにし、先ほど作成したHTTPをエンドポイントURLに入力します。 そして、外部から叩かれないように認証を有効にし、サービスアカウントを設定しサブスクリプションを作成します。

Pub/subの設定を済ませcloud schedulerを設定すればスラックへの通知は完了です。

今回は毎日9時に先ほど設定したpub/subを呼び出しています。

最後にテーブルの定期実行処理を済ませます。 そうすることで画像のように毎日9時過ぎに久しぶりに戻ってきてくれたパーソナリティが社員に知らされるようになりました。

感想

Voicyでは毎月何十人がチャンネルを開始しますが、全員が継続できるわけではありません。 声の発信が合わなかった人・忙しくてやめてしまう人・話すネタがなくなってしまった人、etc... さまざまな理由で放送が止まってしまう人がいます。今回Slackへの通知をして可視化したことで、想定以上に一度離脱しても戻ってきていることがわかりました。

戻ってきた人が可視化されたのをきっかけにパーソナリティサクセスと連携をとり、

なぜ戻って発信をしようと思ったのか?

どんなところが改善されると離脱せずに発信し続けられるのか?

など実際に戻ってきたパーソナリティに聞くこともでき、Voicyが良いプロダクトになるためのヒントがたくさん発見できたので今後の開発に活かしていこうと思います。