はじめに
mediba Advent Calender 2024の19日目の記事になります。
今回は、Ruby on Railsの学習用に作成したECサイトにて、GA4とGTMを利用してA/Bテストを行う方法について書いていきます。
背景
2023年9月のGoogle Optimizeのサービス終了に伴い、無償で気軽にA/Bテストを実施できなくなったという方が多いのではないでしょうか。(私もその一人です。)
現に、GoogleからGA連携可能なA/Bテストツールのアナウンスがありましたが、すべて有償となっています。(2024/10/16現在)
- AB Tasty
- Optimizely
- VWO
そのため、自前でA/Bテストを行う方法を検討することにしました。
アウトプット
GTMのカスタムHTMLタグ(JavaScript)を利用し、商品一覧画面の「Add to Cart」のボタンテキストをランダムに50%の確率でオリジナルとテストパターンのどちらかに変更し表示させることができました。
また、以下のアクセスログをGA4に送信し、A/Bテストの結果をBigQueryで集計することができました。(GA4の探索レポートでも集計可能です)
- A/Bテストのパターンごとのページビューイベント
- A/Bテストのパターンごとの対象箇所のクリックイベント
集計した結果は、以下の通りです。
A/Bテスト対象のページ
A/Bテスト対象のページとして、Ruby on Railsの学習用に作成したECサイトを利用します。
なお、A/Bテストはユーザーに対して「Add to Cart」のボタンテキストをランダムに50%の確率で以下の内容に変更し表示させることとします。
- オリジナル:「Add to Cart」ボタン(既存のボタンテキスト)
- テストパターン:「カートへ追加」ボタン(ボタンテキストを変更)
補足となりますが、ECサイトの環境は以下の通りです。
- Ruby 3.2.1
- Rails 7.0.6
- Bootstrap 5.2.3
- Active Storage(AWS S3)
- Action Mailer
- Docker
- Heroku
作業手順
A/Bテストを実施するための作業手順は、次の通りです。
- GTMで必要なタグを公開する
- A/Bテストの表示を確認する
- GA4ログの疎通を確認する
- A/Bテストの結果を集計する
GTMで必要なタグを公開する
ga4ClickEvent.js
以下のスクリプトをカスタムHTMLタグで配信し、GA4のクリックイベント送信関数を定義します。
後述のab_test.jsで、テスト対象箇所のaタグのonclick属性の値に本関数をappendします。
本関数が実行された(クリックされた)タイミングでカスタムイベントトリガーが発動し、GTMのGA4イベントタグ(クリックイベントタグ)が発火する設定とします。
<script>
function ga4ClickEvent(category, action, label) {
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'event': 'ga4ClickEvent',
'event_category': category,
'event_action': action,
'event_label': label,
});
}
</script>
GA4のクリックイベントタグ
前述のga4ClickEvent
関数が実行されたら(ボタンがクリックされたら)、発火するGA4のイベントタグ(イベント名:click
)を設定します。
なお、本イベントの以下イベントパラメータには、先ほどのga4ClickEvent
関数内の
dataLayer変数の値を設定します。
- event_category
- event_action
- event_label
トリガーは、カスタムイベントトリガー(イベント名:ga4ClickEvent
)を設定します。
ab_test.js
A/Bテストを行うための以下スクリプトをGTMのカスタムHTMLタグで配信します。
簡潔にまとめると、スクリプト内では以下の処理を行なっています。
- ブラウザのCookie「pattern」の値としてランダムに0と1を振り分けて、A/Bテストを実施
- Cookie「pattern」の値が「0」の場合
- オリジナル「Add to Cart」ボタンを表示
- Cookie「pattern」の値が「1」の場合
- テストパターン「カートへ追加」ボタンを表示
- Cookie「pattern」の値が「0」の場合
クリックイベント送信関数がボタンのaタグのonclick属性の値としてappendされ、ユーザーがクリックしたタイミングで、クリックイベントがGA4に送信されます。
なお、どのパターンがクリックされたかを判別するためにga4ClickEvent
関数の第三引数に、0
(オリジナル)または1
(テストパターン)の値を設定します。
<script>
(function() {
function getCookieValue(name) {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim().split('=');
if (cookie[0] === name) {
return cookie[1];
}
}
return null;
}
function setButton(element, text, patternValue) {
element.textContent = text;
element.setAttribute('onclick', 'ga4ClickEvent("商品一覧", "クリック", "' + patternValue + '")');
}
function updateButtons() {
var elements = document.getElementsByClassName('gtm-click');
var pattern = getCookieValue("pattern");
for (var i = 0; i < elements.length; i++) {
if (!pattern) {
pattern = Math.random() > 0.5 ? '0' : '1';
document.cookie = "pattern=" + pattern + "; expires=expireDate; domain=domainName";
}
if (pattern === '0') {
setButton(elements[i], "Add to Cart", "0");
} else {
setButton(elements[i], "カートへ追加", "1");
}
}
}
document.addEventListener("DOMContentLoaded", updateButtons);
})();
</script>
GA4のページビュータグ(既存)
既存のGA4のページビュータグのイベントパラメータに、どちらのパターンが表示されたかという情報をもたせておきます。
以下のような形で、イベントパラメータ「pattern」の値に前述のab_test.jsで作成したファーストパーティーCookie「pattern」の値を設定します。
以上のGTMタグの設定を公開し、本作業は完了となります。
A/Bテストの表示確認を行う
実際にページにアクセスすると、ブラウザごとにランダムにオリジナルとテストパターンが表示されました。
GA4ログの疎通を確認する
次に、ChromeのNetworkパネルでGA4のページビュー/クリックイベントが想定通りに送信されているか確認します。
ページビューイベント
既存のページビューイベントのイベントパラメータとして、pattern
が追加されました。
値には、テストパターンが表示されたことを示す1
が入っています。オリジナルが表示された場合は値に0
が入ります。
クリックイベント
ボタンがクリックされた際に、クリックイベントの送信が確認できました。
イベントパラメータevent_label
の値として、テストパターンがクリックされたことを示す1
が入っています。オリジナルがクリックされた場合は0
が入ります。
A/Bテストの結果を集計する
以下の通り、BigQueryのGA4テーブルからA/Bテスト結果の集計をすることができました。
結果の集計に利用したSQLは、以下の通りです。
CREATE TEMPORARY FUNCTION get_ga4_value(params ANY TYPE,name STRING) AS (
(
SELECT
COALESCE(
value.string_value,
cast(value.int_value AS string),
cast(value.float_value AS string),
cast(value.double_value AS string)
)
FROM
UNNEST(params) AS x
WHERE
x.key = name
)
);
WITH raw_data AS (
SELECT
event_name,
get_ga4_value(event_params, 'pattern') AS pattern,
get_ga4_value(event_params, 'event_category') AS event_category,
get_ga4_value(event_params, 'event_action') AS event_action,
get_ga4_value(event_params, 'event_label') AS event_label,
FROM
projectId.analytics_{propertyId}.events_*
WHERE
_TABLE_SUFFIX BETWEEN "yyyymmdd" AND "yyyymmdd"
),
page_view_count AS (
SELECT
pattern,
COUNT(event_name) AS page_view_count
FROM
raw_data
WHERE
event_name = "page_view"
GROUP BY
pattern
ORDER BY
pattern ASC
),
click_count AS (
SELECT
event_label AS pattern,
COUNT(event_name) AS click_count
FROM
raw_data
WHERE
event_name = "click"
AND event_category = "商品一覧"
AND event_action = "クリック"
GROUP BY
pattern
ORDER BY
pattern ASC
)
SELECT
page_view_count.pattern,
page_view_count.page_view_count,
click_count.click_count,
ROUND((CAST(click_count.click_count AS NUMERIC) / CAST(page_view_count.page_view_count AS NUMERIC)) * 100, 2) AS click_rate
FROM
page_view_count
INNER JOIN
click_count
USING(pattern)
ORDER BY
pattern ASC
;
※イベントパラメータの値の取り出しには、ユーザー定義関数(UDF)get_ga4_value
を利用しています。
カイ二乗検定で有意差検定を行う
最後に、カイ二乗検定でオリジナルとテストパターンのCTRに差があったか判断します。
詳細は割愛しますが、以下のようにスプレッドシート上でCHISQ.TEST
という関数を利用すれば簡単に実施できるので、ぜひ試してみてください。(今回はサンプルサイズが少なすぎますね。)
参考:そのABテスト意味ないかも!カイ二乗検定で「優位性」を判断する方法をわかりやすく解説│デジマログ
おわりに
GA4とGTMを利用して、自前でA/Bテストを行う方法について解説しました。
有償版のA/Bテストツールの導入障壁が高いと感じている方は、本記事を参考にA/Bテストを実施してみてはいかがでしょうか。
どなたかの参考になれば、幸いです。