Adobe Analytics

AdobeAnalytics Datafeed: BigQueryのSIGN関数を使った小ワザ

こんにちは、エクスチュアの權泳東(権泳東/コン・ヨンドン)です。

今回もあまり需要はないけど知ってたら役に立つDatafeed + BigQuery用の小ワザです。

  1. トラフィック変数にCVを紐付ける
  2. セグメントを作る

これらはいずれもSIGN関数の使い方を覚えると簡単にSQLを書けます。

SIGN関数 | 標準 SQL 関数と演算子  |  BigQuery  |  Google Cloud

使い方を以下のケースで説明します。

 

1. トラフィック変数にCVを紐付ける

 
propなどのトラフィック変数で計測してる値をeVarみたいに最後の値にCVを紐付けたいけど、今からAA実装直したんじゃ遅い!という事が人生で何度かおきました。
私が過去にやった例だと、s.channelの値をeVarに入れ忘れ(以下略)

トラフィック変数に対するCV紐付け方法として、パーティシペーション指標を使う方法があります。
これを使えばセッションまたはレポート期間中において発生したすべてのprop値にCVが紐付きます。

しかし、propに対して「最初の値」か「最後の値」にCVを紐付けたい場合はパーティシペーションは有効ではありません。
そんな時にはササっとお手軽にSQLで抽出する方法を覚えておくと人生がラクになります(当社比)

i. propの最後の値(直近)にCVを紐付けるSQL

WITH t1 AS (
  SELECT
    CONCAT(post_visid_high, post_visid_low, CAST(visit_num AS string)) AS sid,
    hit_time_gmt,
    post_channel AS channel,
    SIGN(SUM(CASE WHEN CONCAT(',', post_event_list, ',') LIKE '%,1,%' THEN 1
        ELSE 0 END) 
        OVER(PARTITION BY CONCAT(post_visid_high, post_visid_low, CAST(visit_num AS string))
          ORDER BY hit_time_gmt DESC ROWS BETWEEN UNBOUNDED PRECEDING
          AND CURRENT ROW)) AS cvflag
  FROM exture.hit_data
  WHERE
    DATE(hit_time_gmt, 'Asia/Tokyo') >= "2019-11-01"
    AND DATE(hit_time_gmt, 'Asia/Tokyo') < "2019-12-01"
    AND post_channel IS NOT NULL
    AND exclude_hit = 0
    AND duplicate_purchase = 0
  ),

t2 AS (
  SELECT
    sid,
    hit_time_gmt,
    channel,
    ROW_NUMBER() OVER(PARTITION BY sid ORDER BY hit_time_gmt DESC) AS rownum,
    cvflag
  FROM t1
  WHERE cvflag = 1
)

SELECT
  channel,
  SUM(cvflag) AS cv_last
FROM t2
WHERE rownum = 1
GROUP BY 1
ORDER BY 2 DESC

解説:

最初のCTE t1 では、同一セッション内でコンバージョンイベントが発生したよりも前のヒットを絞り込みます。
SIGN関数を使って同一セッションのヒットに「1」というフラグを立てて行きます。

なお、OVER句において

ORDER BY hit_time_gmt DESC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW

を使う事で、CVが発生したヒットよりも前のヒットに対してパーティションを作成してます。
それらの行にSIGN関数でCVの合計数を渡すことで、CVが1件以上あれば「1」を、CVがなければ「0」を返します。

その後、CTE t2においてセッション内のヒットをDESCで降順にソートして、行番号であるrownumberカラムを生成します。

そして最後のクエリでrownumberが「1」の値(=CVより前にヒットした最後のs.channelの値)に対して、CV数が出てくるという仕組みです。

ii. propの最初の値(元の値)にCVを紐付けるSQL

WITH t1 AS (
  SELECT
    CONCAT(post_visid_high, post_visid_low, CAST(visit_num AS string)) AS sid,
    hit_time_gmt,
    post_channel AS channel,
    SIGN(SUM(CASE WHEN CONCAT(',', post_event_list, ',') LIKE '%,1,%' THEN 1
        ELSE 0 END) 
        OVER(PARTITION BY CONCAT(post_visid_high, post_visid_low, CAST(visit_num AS string))
          ORDER BY hit_time_gmt DESC ROWS BETWEEN UNBOUNDED PRECEDING
          AND CURRENT ROW)) AS cvflag
  FROM exture.hit_data
  WHERE
    DATE(hit_time_gmt, 'Asia/Tokyo') >= "2019-11-01"
    AND DATE(hit_time_gmt, 'Asia/Tokyo') < "2019-12-01"
    AND post_channel IS NOT NULL
    AND exclude_hit = 0
    AND duplicate_purchase = 0
  ),

t2 AS (
  SELECT
    sid,
    hit_time_gmt,
    channel,
    ROW_NUMBER() OVER(PARTITION BY sid ORDER BY hit_time_gmt ASC) AS rownum,
    cvflag
  FROM t1
  WHERE cvflag = 1
)

SELECT
  channel,
  SUM(cvflag) AS cv_first
FROM t2
WHERE rownum = 1
GROUP BY 1
ORDER BY 2 DESC

解説:

CTE t1 は「最後の値」と同じです。
CTE t2においてセッション内のヒットを昇順ソートしているのが違いです。
※分かりやすくするためにASCを明示的に入れてますが、なくてもOKです。

そして最後のクエリでrownumberが「1」の値(=CVより前にヒットした最初のs.channelの値)に対して、CV数が出てくるという仕組みです。

 

2. セグメントを作る

 
条件に一致したヒット・訪問・訪問者別にコンテナを作成し、該当するデータだけにフォーカスするのがAdobeAnalyticsにおける「セグメント」です。

SIGN関数を使えば、条件に一致するヒット・訪問・訪問者に対してフラグを簡単に立てられます。

例えば「弊社ブログTOPページを表示した訪問」というセグメントを定義して、セグメントに一致するトラフィックを集計するならばこう書けます。

WITH t1 AS (
  SELECT
    CONCAT(post_visid_high, post_visid_low, CAST(visit_num AS string)) AS sid,
    CONCAT(post_visid_high, post_visid_low) AS vid,
    hit_time_gmt,
    post_pagename AS pagename,
    SIGN(SUM(CASE WHEN post_pagename = 'ext:blog:index.html' THEN 1
        ELSE 0 END) 
        OVER(PARTITION BY CONCAT(post_visid_high, post_visid_low, CAST(visit_num AS string))
          ORDER BY hit_time_gmt ROWS BETWEEN UNBOUNDED PRECEDING
          AND UNBOUNDED FOLLOWING)) AS flag
  FROM exture.hit_data
  WHERE
    DATE(hit_time_gmt, 'Asia/Tokyo') >= "2019-11-01"
    AND DATE(hit_time_gmt, 'Asia/Tokyo') < "2019-12-01"
    AND post_page_event = 0
    AND exclude_hit = 0
    AND duplicate_purchase = 0
  )
  
SELECT
  pagename,
  count(1) as pv,
  count(distinct sid) as visits,
  count(distinct vid) as visitors
FROM t1
WHERE flag = 1
GROUP BY 1
ORDER BY 2 DESC

Adobeのセグメント定義をSQLで再現

解説:

CTE t1 でSIGN関数を使うのは同じですが、OVER句の中で ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING を使うのが特徴です。
これによって、条件に一致した訪問の「最初から最後まで」の行が対象になります。

そして最後に flag=1 の行だけを抽出すれば、セグメントに一致したデータを抽出出来ます。

SQL結果と完全に一致

また、「順次セグメント」のように「~より前」(BEFORE) という定義にしたい場合は

ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING

という書き方をすれば条件に一致するより前のデータだけが対象になり、逆に「~よりも後」(THEN)という定義ならば

ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW

という書き方でスコープを狭める事が出来ます。

まとめ

SIGN関数を使って「該当するセッション内のヒットにフラグを立てる」手法はAdobeAnalyticsの「セグメント」を再現する時に私は頻繁に使ってます。
このテクニックはGoogleAnalytics360 または Apps+Web PropertyのデータをBigQueryで分析する時にも使えるので、使い方を覚えておきましょう。

弊社では、Google Cloud認定データエンジニア資格とAdobe認定エキスパート資格を保持した技術者達によるデータ分析基盤構築業務を承っております。
お問い合わせはこちらからどうぞ

ピックアップ記事

  1. 最速で理解したい人のためのIT用語集

関連記事

  1. Adobe Analytics

    Adobe Analytics: RSIDを間違えてしまったデータを正しいRSに入れ直す

    こんにちは、エクスチュアの權泳東(権泳東/コン・ヨンドン)です。…

  2. Adobe Analytics

    異常値検出とは-Adobe Analyticsの指標説明

    今回は異常値検出について説明いたします。異常値検出とは過去のデータ…

  3. Google BigQuery

    Tableau : BigQueryでLOD計算が使えない場合の対処法

    こんにちは、エクスチュアの渡部です。Tableau×BigQu…

  4. Firebase Analytics

    Firebase Analyticsの新しいBigQueryスキーマを試す

    こんにちは、エクスチュアの權泳東(権泳東/コン・ヨンドン)です。…

  5. Adobe Analytics

    Adobe Analytics:IF関数を使用した計算指標

    Adobe Analyticsで1年以上前についた計算指標に関数が使え…

  6. Google BigQuery

    Google Apps Scriptを使ってスプレッドシートからBigQueryのテーブルを更新する…

    こんにちは、エクスチュアの權泳東(権泳東/コン・ヨンドン)です。…

最近の記事

  1. 【GA4/GTM】dataLayerを使ってカスタムイベント…
  2. 【GA4/GTM】dataLayerを活用しよう
  3. ジャーニーマップをデジタルマーケティングの視点で
  4. ChatGPT ProからClaude3 Proへ移行した話…
  5. その分析、やり方あってる?記述統計と推測統計の違い
  1. Google Tag Manager

    GTMでiframe内のクリックイベントを取得したい
  2. Mouseflow

    Mouseflowのフィルター機能が変わりました!
  3. コンバージョンファネル

    ファネル分析
  4. Office365

    エクセルで「テーブル」を使うメリット① 「BIツールで使いやすい」
  5. Adobe Analytics

    Adobe Analytics: Datafeedにデバイスデータがないけど慌て…
PAGE TOP