JQL: mixpanel で複雑な分析機能を使い始める – その2 プロファイルデータ –

2022.10.03

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

mixpanelのJQLでは、分析するコレクションとしてイベントデータ(Event())かプロファイルデータ(People())を選択する必要があります。

前回の記事ではイベントを扱ってみたので、今回はプロファイルデータを扱ってデータの分析をJQLで行ってみます。

やってみる

コレクションの取得

People()関数を使って取得しますが、引数を一つ与えれます。

user_selectors:[{selector: "<<Segmentation expression>>"}] の形式で、selectorオブジェクトで取得するユーザーレコードを制限できます。

※ Segmentation Expressionsについて

// allison@example.comというメールアドレスのユーザー
People({
    user_selectors:[{
      selector:'user["$email"] == "allison@example.com"'
    }]
});

// user_segmentというプロパティが定義されているユーザー
People({
    user_selectors:[{
      selector:'defined(user["user_segment"])'
    }]
});

// regionが千葉のユーザー
People({
    user_selectors:[{
      selector:'user["$region"] == "Chiba"'
    }]
});

People()で取得したユーザーは、以下のオブジェクトが返されます。

{
    "distinct_id": "<<ユーザーのdistinct_id>>",
    "last_seen":<<Set() メソッドを介して提供される最新のユーザーレコード更新のタイムスタンプ>>,
    "properties": {
       <<ユーザーのすべてのプロパティを含むオブジェクト>>
     },
    "time": <<最新のユーザー レコード更新のタイムスタンプ>>

}

※ ユーザーセレクター式のセグメンテーション式は、ユーザープロパティにのみアクセスでき、イベントプロパティにはアクセスできません

絞り込み

user_selectorsを使わずにユーザーレコードを制限することもできます。

イベントと同じく、filter()を使用できます。

user_selectorsの例をfilterで表すと、以下のようになります。

// allison@example.comというメールアドレスのユーザー
People(
).filter(function(user){
  return user.properties.$email == "allison@example.com"
});

// user_segmentというプロパティが定義されているユーザー
People(
).filter(function(user){
  return user.properties.user_segment
});

// regionが千葉のユーザー
People(
  ).filter(function(user){
    return user.properties.$region == "Chiba"
  });

イベントとの結合

イベントとプロファイルのコレクションを結合してデータを取得することも可能です。

SQLでいうjoinで、JQLでもjoin()関数が用意されています。

join(Events(), People())という形でデータを取得しますが、この状態ではfull join(完全結合) となります。

3番目の引数で結合の種類とセレクターを与えることができます。

  • type
    • full, inner, left, right
  • selectors
    • 取得するイベント/ユーザーのペアを制限する {event: "event name", selector: "<>"} オブジェクトのオプションのリスト

例) イベントとユーザーレコードの両方,イベントは米国から送信されたもの, ユーザーの年齢が30歳以上

{
      type:"inner",
      selectors:[{selector:
        'properties["country"] == "US" and user["age"] > 30'}]
}

結合された結果は以下のオブジェクトを返します。

{
  "event": {
    <<イベント オブジェクト。イベントのないユーザーの場合、このプロパティは未定義>>
  },
  "user": {
    <<イベントに一致する distinct_id を持つユーザー オブジェクト。個別の ID がないイベントの場合、または一致するユーザー レコードがない場合、このプロパティは未定義>>
  }, 
  "distinct_id": "<<イベントと一致するユーザーの両方の distinct_id>>"
}

結果から分かる通り、 distinct_idをキーとして結合しているようですね。

注意点として、Join()内のコレクションに対してmap,reduce,filter,groupByの変換を適用することはできません。

join(
    Events({
      from_date: "2022-01-01",
      to_date: "2022-10-01",
    }).filter(
      function(event) {
        return event.name == "page_open"
      }  
    ),
    People().reduce(mixpanel.reducer.avg("properties.age")),

);

はエラーとなります。

変換の関数を使う場合は、以下のように、join()の結果に対してfilter()関数などを実行して絞り込みを行えます。

今年起こったイベントの中で、1月中にサインアップしたユーザーのログインイベントを確認する

join(
      Events({
        from_date: "2022-01-01",
        to_date: "2023-01-01"
      }),
      People()
)
.filter(
  function(tuple) {
    return tuple.event.name == "login" &&
        tuple.user.properties.signup_date >= new Date("2022-01-01") &&
        tuple.user.properties.signup_date < new Date("2022-02-01");
  }
)

参考