データ分析を元にFAQサイトを継続的に改善する

FAQサイト、サポート問い合わせをせずとも自分で疑問を解決できて便利ですよね。でも、検索した単語が一件もヒットしないと、ちょっとガッカリしてしまします。そういったガッカリを減らすために、簡単なデータ分析を使ってFAQサイトを継続的に改善する話を書いてみます。

...というのも、自分が仕事で関わっているMackerelでは最近FAQをリニューアルしたからなのでした。

MackerelのFAQではZendesk Guideを利用していますが、Zendesk Guideは便利なAPIが用意されているので、それと既存のデータ基盤を組み合わせて改善していく形です。

FAQサイト内の検索語を列挙する

まず、FAQサイト内でどういった単語が検索されているのかを列挙します。Google Tag Manager経由でFirebase Analyticsにデータを飛ばすと閲覧状況が分かりますが、そのログをBigQueryにexportしておくと調理しやすくなります。

あとは以下のようなSQL書いてあげれば、どういった検索がサイト内で行なわれているかが分かります。

SELECT
  *
FROM (
  SELECT
    (SELECT value.string_value FROM UNNEST(event_params) AS x WHERE x.key = "page_location") AS page_location,
    (SELECT value.string_value FROM UNNEST(event_params) AS x WHERE x.key = "search_term") AS search_term,
    *
  FROM
    `my-project.my_dataset.events_*`
  WHERE
    event_name = "view_search_results"
  )
WHERE
  page_location LIKE "https://support.example.com%"

これをBigQuery上でmy-project.my_dataset.zendesk_guide_search_termにviewとして定義したと仮定して、以降の話を進めます。

特定の検索語にヒットする記事を調べる

次にZendesk Guide内で検索語が何件ヒットするのかを調べましょう。Zendesk Guideはその辺がしっかりしていて、ある単語に対してヒットする記事の一覧を返してくれるAPIが存在しています。

検索された単語を全部APIに投げてるのはさすがにアレなので、検索回数が一定以上の上位N件の記事のヒット件数を取得して、BigQueryにアップロードします。

set -eu -o pipefail

COUNT_FILE=zendesk_articles_count_by_search_term.txt

bq query --max_rows 10000 --format json --use_legacy_sql=false \
  'SELECT
    search_term,
    COUNT(*) AS searches_count
  FROM
    my-project.my_dataset.zendesk_guide_search_term
  GROUP BY
    search_term
  HAVING
    searches_count >= 3
  ORDER BY
    searches_count DESC
  LIMIT
    100' | 
jq -r '.[] | .search_term' | while read -r search_term; do
  COUNT=$(curl -s "https://my_site.zendesk.com/api/v2/help_center/articles/search.json?query=${search_term}" | jq -r .count)
  sleep 1
  echo -e "${search_term}\t${COUNT}"
done > "${COUNT_FILE}"

bq load --source_format=CSV --encoding=UTF-8 --field_delimiter='\t' --replace \
  my-project.my_dataset.articles_count_by_search_term "${COUNT_FILE}" search_term:string,articles_count:integer

ヒット件数が0件の検索語を定期的にSlackに投稿する

材料が揃ったので、ヒット件数が0件の検索語を定期的にSlackに投稿します。Cloud Functionsを使うのですが、詳細は↓に書いています。

これを使うと、以下のような簡単なyamlテンプレートを書くだけで、簡単に投稿までいけます。

description: Zendesk Guide(FAQ)で検索されているが、ヒット件数が0件のものを通知する
webhook_url: https://hooks.slack.com/services/XXX/YYY/ZZZ
cron: "45 9 * * 1" # 月曜の9:45
sql: |-
  SELECT
    articles_count_by_search_term.search_term,
    MAX(articles_count_by_search_term.articles_count) AS articles_count,
    COUNT(*) AS searches_count
  FROM
    my-project.my_dataset.articles_count_by_search_term
  LEFT OUTER JOIN
    my-project.my_dataset.zendesk_guide_search_term
  ON
    articles_count_by_search_term.search_term = zendesk_guide_search_term.search_term
  GROUP BY
    articles_count_by_search_term.search_term
  HAVING articles_count = 0
  ORDER BY
    articles_count,
    searches_count DESC
template: |-
  以下の検索語がFAQでヒット件数0件でした。FAQの記事追加してみませんか?
  {%- for row in data %}
  ## 検索語: 「{{ row.search_term }}」
  - 検索回数: {{ row.searches_count }}
  {%- endfor %}

その他

Zendeskはその他、upvotesやdownvotesの数を記事毎に取得できるAPIなどもサポートされています(downvotesが多い記事は改善したほうがいい可能性が高い)。この辺りは丸っと取得してきたい & BigQueryにそのまま投下したいので、Embulkのプラグインを自前で用意しています。