A/B テスト
Pro Featureダッシュボードで実験を定義し、サイトに JavaScript を 1 行埋め込むだけで、Zenovay が各訪問者に決定論的にバリアントを割り当て、バリアントごとのコンバージョン率と、対照群に対するリフトの 95% 信頼区間をレポートします。
A/B テストは Pro、Scale、Enterprise の各プランでご利用いただけます。この機能を有効にするには、プランをアップグレード してください。
仕組み
訪問者の割り当ては、トラッカー側で訪問者 ID の決定論的ハッシュを用いてローカルに計算されます。そのため、同一訪問者には常に同じバリアントが表示されます。ページ再読み込みをまたいでも、(Cookie が有効な場合は)セッションをまたいでも同じです。Cookieless モード(data-cookieless="true" でトラッカーを読み込んでいるサイトの既定)では、割り当てはウィンドウスコープとなり、タブを閉じるとリセットされます。
実験のセットアップ
- ダッシュボードで対象のウェブサイトを開き → Experiments タブ → New experiment をクリックします。
- 実験に名前を付け、必要に応じて仮説を記入し、既存のカスタムゴールから対象ゴールを選択します。
- 2 〜 N 件のバリアントを追加し、1 つを control として指定し、バリアントごとにトラフィックの分配比率を設定します。
- 下書きとして保存し、準備が整ったら Launch をクリックします。
コードの埋め込み
const variant = window.zenovay('experiment', 'checkout-cta-color', ['control', 'green', 'orange']);
if (variant === 'green') document.querySelector('.cta').style.background = '#22c55e';
if (variant === 'orange') document.querySelector('.cta').style.background = '#f97316';
クライアントサイドの実装はこれですべてです。割り当て、エクスポージャーのログ記録、コンバージョン帰属はトラッカーが自動で処理します。訪問者が後ほど対象のゴールを発火させた際(既存のゴールトラッキング呼び出し経由)、Zenovay はそのコンバージョンを、その訪問者に割り当てられていたバリアントに帰属させます。
window.zenovay('experiment', …) の呼び出しはべき等です。同じページで複数回呼び出しても同じバリアントが返り、エクスポージャーは訪問者・実験・セッションごとに最大 1 回しか記録されません。複数ページにまたがる場合も、variants 配列は常に同じ順序で渡してください。順序は決定論的ハッシュの一部です。
フレームワーク別サンプル
上記のスニペットは素の JavaScript で、どのブラウザ環境でも動作します。以下に主要スタック向けのパターンを示します。
素の HTML
Zenovay トラッカーの <script> タグより下であればどこに置いても構いません。
<button class="cta">Buy now</button>
<script>
// Wait for the tracker to load (it sets window.zenovay on init).
function applyVariant() {
if (!window.zenovay) { setTimeout(applyVariant, 50); return; }
var variant = window.zenovay('experiment', 'checkout-cta-color', ['control', 'green', 'orange']);
var cta = document.querySelector('.cta');
if (variant === 'green') cta.style.background = '#22c55e';
if (variant === 'orange') cta.style.background = '#f97316';
}
applyVariant();
</script>
React / Next.js(クライアントコンポーネント)
Next.js App Router では、コンポーネントを 'use client' でマークし、ハイドレーション後に割り当てを行うために useEffect の中から呼び出します。
'use client';
import { useEffect, useState } from 'react';
export default function CheckoutCTA() {
const [variant, setVariant] = useState('control');
useEffect(() => {
if (typeof window === 'undefined' || !window.zenovay) return;
const v = window.zenovay('experiment', 'checkout-cta-color', ['control', 'green', 'orange']);
setVariant(v);
}, []);
const bg = variant === 'green' ? '#22c55e' : variant === 'orange' ? '#f97316' : undefined;
return <button className="cta" style={{ background: bg }}>Buy now</button>;
}
初回描画でコントロールが一瞬見えるちらつきを抑えたい場合は、既定でコントロールを描画し、マウント後に useEffect でトリートメントへ切り替えます。window.zenovay('experiment', …) を最初に呼び出した時点でエクスポージャーが記録されます。
Vue / Nuxt
<script setup> のコンポーネントでは、onMounted から呼び出します。
<script setup>
import { ref, onMounted } from 'vue';
const variant = ref('control');
onMounted(() => {
if (!window.zenovay) return;
variant.value = window.zenovay('experiment', 'checkout-cta-color', ['control', 'green', 'orange']);
});
</script>
<template>
<button
class="cta"
:style="{ background: variant === 'green' ? '#22c55e' : variant === 'orange' ? '#f97316' : null }"
>
Buy now
</button>
</template>
サーバーサイドレンダリング (Next.js, Remix, Nuxt SSR)
バリアント割り当ては ウィンドウスコープ です。トラッカーはブラウザにしか存在しないため、サーバーサイドから呼び出すと undefined を返し、SSR の初回パスではコントロール側のブランチが描画されます。その後、クライアントの useEffect が再実行されたタイミングで、訪問者は短時間トリートメントを目にすることになります。
実用的なパターンは 2 つあります。
- コントロールのちらつきを許容する。 視覚的な変更(色、コピー)であれば通常問題ありません。一般的なハイドレーション速度では切り替えは気づかれません。
- トリートメントをクライアントだけで描画する。 実験ブロックを client-only バウンダリに包んで SSR は何も出力させず、ハイドレーション時に一度だけトリートメントを描画させます。ちらつきは消えますが、レイアウトシフトが発生します。
'use client';
import dynamic from 'next/dynamic';
const ExperimentalCTA = dynamic(() => import('./CheckoutCTA'), { ssr: false });
export default function Page() {
return <ExperimentalCTA />;
}
V1 ではエッジ/サーバーサイドの割り当てエンドポイントは提供していません。
Google Tag Manager (GTM)
Zenovay トラッカーのタグの後に発火するカスタム HTML タグでこの呼び出しをラップし、変数を dataLayer に push して、ほかの GTM タグから読めるようにします。
<script>
(function () {
if (!window.zenovay) return;
var variant = window.zenovay('experiment', 'checkout-cta-color', ['control', 'green', 'orange']);
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({ event: 'zenovay_experiment', experiment_id: 'checkout-cta-color', variant: variant });
})();
</script>
ほかの GTM タグ(例: CSS 書き換えタグ)はその後 zenovay_experiment イベントでトリガーし、{{ DLV - variant }} を読み取って視覚的な変更を適用できます。
有意性の計算方法
バリアントごとのコンバージョン率はサーバー側で集計されます。ダッシュボードでは、各 treatment と control の対比に対して両側 2 標本 z 検定を行い、実験内の全比較に Bonferroni 補正 を適用した結果を表示します。「winner」バッジは、以下の すべて を満たした時点で表示されます。
- Bonferroni 補正後の p 値 < 0.05
- 両方のバリアントが、設定された最小サンプルサイズ(既定: バリアントごとに 100 訪問者)に到達している
- treatment の control に対するリフトが正である
これは固定サンプルサイズの頻度主義テストです。逐次検定ではありません。実験終了前に結果をのぞき見すると Type I エラーが膨らみます。
ダッシュボードの読み方
Experiments ダッシュボードでは、バリアントごとに 1 行のサマリーを表示します。
| 列 | 表示内容 |
|---|---|
| Visitors | ローンチ以降にこのバリアントに割り当てられたユニーク訪問者数 |
| Conversions | そのうち対象ゴールを発火した訪問者数 |
| Conversion rate | バリアントごとの conversions / visitors |
| Lift vs control | control に対するコンバージョン率の相対変化 |
| p-value | Bonferroni 補正済み、control との比較(control 行は — を表示) |
| Status | running、winner、または not significant yet |
下部のチャートはバリアントごとの累積コンバージョン率を時系列でプロットします。これにより、いつ各バリアントが乖離し始めたか(もしくは依然として同水準で推移しているか)を確認できます。
推奨ワークフロー
- 1 つの実験につき変更は 1 つだけ。 CTA の色 と 見出しを同時に変えてしまうと、数値を動かしたのがどちらだったか分からなくなります。それ以外は固定しましょう。
- ローンチ前に対象ゴールを決める。 実験中に対象ゴールを追加・変更すると、それまでに集めたデータがすべて無効になります。Zenovay は警告を出し、再ローンチを要求します。
- 必要なサンプル数を見積もる。 ベースライン 2% のコンバージョン率に対して 5% のリフトを検出するには、通常バリアントあたり約 30,000 訪問者が必要です。ローンチ前にサンプルサイズ計算機を使い、トラフィックで実際に最後まで回せる実験だけを開始してください。
- 「勝者をのぞき見」しない。 頻度主義テストは、停止ルールを事前に決めた場合にのみ妥当です。ダッシュボードを毎日見て、ある treatment が p < 0.05 を超えた瞬間に止めてしまうと、Type I エラー率が大幅に膨らみます。
- 削除ではなくアーカイブ。 実験が終わったらメニューからアーカイブしてください。削除すると、下流のファネル・収益レポートが利用している過去の割り当てデータも消えてしまいます。
プランごとの上限
| プラン | 同時実行可能な実験数 | 1 実験あたりの最大バリアント数 |
|---|---|---|
| Free | — (利用不可) | — |
| Pro | 5 | 4 |
| Scale | 25 | 10 |
| Enterprise | 無制限 | 無制限 |
プライバシーとコンプライアンス
A/B テストは、Zenovay のプライバシー方針を尊重するように構築されています。
- Cookieless モード: バリアント割り当てはウィンドウスコープ(メモリ内のみ)です。新たな Cookie や localStorage エントリーは作成されません。
- バリアント割り当てデータは、無料の GDPR 第 20 条データエクスポートに含まれます。
- アカウント削除は、実験・バリアント・割り当てまでカスケードします。
- 保持期間はプラン階層に従います(Free 365 日、Pro 730 日、Scale 1,460 日)。
V1 に含まれていないもの
- Multi-armed bandit、Thompson サンプリング、ベイジアン信用区間 — 頻度主義のみ。
- 逐次 / always-valid な p 値 — 固定サンプルのみ。
- サーバー / エッジでのバリアント決定 — 割り当てはクライアントサイドです。
- ターゲティングルール(地域、デバイス、リピート訪問者のみ など) — ランダム割り当てのみです。
- 相互排他的な実験グループ。
トラブルシューティング
バリアントが常に null、または常に control を返す
頻度の高い原因から順に挙げます。
window.zenovay(...)を呼び出した時点でトラッカーがまだ読み込まれていなかった。window.zenovay関数はローダースタブによって同期的に定義されますが、実際に機能するのはトラッカーバンドルのダウンロードが終わってからです。それ以前の呼び出しはundefinedを返します。HTML の例にある小さな待機ループでラップするか、マウント後に走るフレームワークのライフサイクルフックから呼び出してください。- 実験のステータスが
runningになっていない。 トラッカーが割り当てを行うのはrunningの実験だけです。下書きや一時停止中の実験はコントロールを返します。Experiments タブを開いてステータスバッジを確認してください。 - ダッシュボードの設定と異なるバリアント配列を渡している。
window.zenovay(...)で渡すバリアントは、ダッシュボードのバリアントスラッグと完全に一致している必要があります(順序も含む)。['control', 'gren']のようなタイプミスがあると、すべての訪問者が control に振り分けられます。 - Cookieless モード + タブのクローズ。
data-cookieless="true"でトラッカーを読み込んでいるサイトでは、訪問者 ID はウィンドウスコープです。タブを閉じて開き直すと新しい訪問者として扱われ、別のバリアントに割り当てられる可能性があります。これは仕様であり、統計的にも有効です。
ローンチ後にエクスポージャーが記録されない
experiment()を呼び出すページにトラッカーが読み込まれていない。 該当ページの DevTools でwindow.zenovayが定義されているか確認してください。undefinedであれば、そのページに Zenovay トラッカーの<script>が含まれていないか、まだ実行されていません。- 実験がまだ
draftのまま。 実験の詳細画面で Launch をクリックしてください。下書きの実験はエクスポージャーを記録しません。 - アドブロッカーがリクエストを落としている。 稀ですが、ファーストパーティではないトラッキングドメインを使っている場合に起こり得ます。アドブロッカー利用者が多い場合は、ファーストパーティトラッキング(カスタムサブドメイン)に切り替えてください。
エクスポージャーは見えるのにコンバージョン帰属が 0
- ゴール ID の不一致。 実験作成時に選んだ対象ゴールは、コード(または Zenovay の自動トラッキング)が実際に発火させているゴールと同一でなければなりません。ダッシュボードでゴールスラッグを確認し、ライブフィードでゴールが発火することを確認してください。
- コンバージョンが割り当てより先に発生している。 ごく稀ですが、ページの初期ロードで CTA が即時にゴールを発火し、
experiment()の呼び出しが遅延している場合に起こり得ます。experiment()はトラッカーのスタブ直後など、できるだけ早く呼び出してください。 - 割り当てとコンバージョンが別のブラウザ/デバイス/タブで発生している。 Cookieless モードでは割り当てはタブをまたいで保持されず、コンバージョンとの紐付けも保たれません。訪問者は別々の参加者としてカウントされます。
Sample-Ratio Mismatch 警告が消えない
Sample-Ratio Mismatch (SRM) とは、設定したトラフィック分配と実際の訪問者分配の乖離のことです。50/50 の実験で 60/40 になっていれば、割り当てに何らかのバイアスが入っているサインです。
- 片方のバリアントがエラーになる。 treatment 側の JavaScript が、訪問者がコンバージョン経路に到達する前に例外を投げると、コンバージョンが帰属されにくくなります(ただしエクスポージャー数は揃うはずです)。エラートラッカーで実験ローンチと相関する増加がないか確認してください。
- ボットトラフィックが片方に偏っている。 同じ系列の訪問者 ID を共有するボット(例: ランダム性の低い IP のクローラーファーム)が、片方のバリアントに集中することがあります。Visitors タブの B2B/ボットフィルターで定量化できます。
- ローンチ後にバリアント配列を編集して再ローンチした。 クライアントの呼び出しでバリアントの順序を変えると、決定論的ハッシュが崩れます。バリアント配列を変える場合は常に新規実験として起動してください。
健全なトラフィック量で SRM が 24 時間以上続く場合は、実験を一時停止してサポートチケットを開いてください。
FAQ
Zenovay で自分のサイトに A/B テストを実装するにはどうすればよいですか?
3 ステップです。最適化したいゴールを作成し、Experiments タブで 2 つ以上のバリアントを持つ実験を定義し、バリアントを適用したいページに 1 行の JavaScript を貼り付けます。ランダム割り当て、エクスポージャーのロギング、コンバージョン帰属はすべて Zenovay トラッカーが処理します。詳細は上の「実験のセットアップ」を参照してください。
A/B バリアントのトラッキングコードはどう追加しますか?
アナリティクスを導入済みであれば、Zenovay トラッカーはすでに各ページに入っています。バリアントを描画したい場所に 1 行追加するだけです。
const variant = window.zenovay('experiment', 'your-experiment-id', ['control', 'treatment-a', 'treatment-b']);
返された値に応じてスタイル、コピー、コンポーネントを分岐させます。別途インストールする SDK はありません。
Zenovay はどのようにして訪問者に表示するバリアントを決めますか?
バリアント割り当ては、訪問者 ID の決定論的ハッシュを、設定したトラフィック分配の重みでモジュロ演算した結果です。同一の訪問者 ID は同じ実験 ID に対して常に同じバリアントへハッシュされるため、ページ遷移や(Cookie が有効な場合は)セッション間を通じて、訪問者には一貫した体験が提供されます。
バリアント割り当てが空 / null になります。なぜですか?
最も多いのは、トラッカーが読み込まれる前に window.zenovay('experiment', …) を呼び出しているケースです。関数は即時に定義されますが、実際のバリアントを返すのはバンドルの解決後です。フレームワークのライフサイクルフック(useEffect、onMounted)か小さな setTimeout ループに包んでください。全リストはトラブルシューティングのセクションを参照してください。
統計的有意性はどう確認しますか?
実験の詳細ページを開いてください。各 treatment 行には、control に対する Bonferroni 補正後の p 値が表示されます。p 値が 0.05 未満、両方のバリアントの訪問者数がそれぞれ 100 以上、treatment の control に対するリフトが正の場合に、緑色の winner バッジが付きます。
実験をいつ終了すべきですか?
停止ルールは ローンチ前 に決めておいてください。固定の訪問数バジェット(例: 「バリアントあたり 30,000 訪問者で終了」)か、固定の終了日のどちらかです。ダッシュボードの現在の状態にかかわらず、そのルールが満たされた時点で終了します。「勝者っぽいから」という理由で早く止めると、偽陽性率が大きく膨らみます。
プラン上限に達した場合(例: Pro で 5/5)どうなりますか?
既存の実験をアーカイブするまで、新しい実験を立ち上げられません。下書きの実験は上限にカウントされず、running ステータスの実験のみカウントされます。アーカイブ済みの実験は割り当てとコンバージョンの履歴を保持しており、同時実行上限の枠だけが解放されます。
実験をクローンしたり、別のコピーで再実行するにはどうすればよいですか?
元の実験を開き、メニューアイコン(⋯)から Clone を選びます。新しい実験はゴール、バリアントリスト、トラフィック分配を引き継ぐので、必要な箇所を編集して Launch してください。クローンした実験は独自の ID を持つため、訪問者は元の実験とは独立して再割り当てされます。
ローンチ後に実験を編集できますか?
完全に編集できるのは draft ステータスの実験だけです。Launch をクリックすると実験はロックされ、一時停止、アーカイブ、終了は可能ですが、バリアント、トラフィック分配、対象ゴールを変更すると実行データが無効になります。変更が必要な場合は実験を終了してクローンしてください。
コンバージョンはどうやってバリアントに紐付けられますか?
帰属は自動です。訪問者が対象ゴールを発火させると(Zenovay の自動トラッキングまたは window.zenovay('event', 'goal-slug') 経由)、Zenovay は実行中の実験に対してその訪問者に割り当てられているバリアントを参照し、コンバージョンをそこに帰属させます。手動の帰属コードは不要です。
Bonferroni 補正とは何ですか?なぜ Pro プランで使われているのですか?
複数の treatment を control と比較する場合、各比較に p < 0.05 のしきい値を単純に適用すると、偽陽性の発生確率が膨らみます(「look-elsewhere」効果)。Bonferroni 補正はしきい値を比較回数で割ります。たとえば treatment が 3 つに対して control が 1 つなら、各比較は p < 0.05 / 3 ≈ 0.017 を満たす必要があります。A/B テストをサポートする Zenovay のすべてのプランで Bonferroni を適用しており、Pro 限定機能ではありません。すべての有料ティアにおける標準のレポート手法です。
SRM とは何ですか?どのくらいで気にすべきですか?
Sample-Ratio Mismatch (SRM) とは、設定したトラフィック分配と実際の訪問者分配の乖離のことです。50/50 の実験では 50.3/49.7 程度なら問題ありませんが、十分なサンプル下で 60/40 になっていればデプロイか割り当てのバグを示すサインです。最初の約 10,000 訪問者の段階で目標から ~5 ポイントを超えてズレている場合は注意が必要です。ダッシュボードでも自動的にフラグが立ちます。
Cookieless モード + A/B テストは動作しますか?
はい。決定論的ハッシュは、トラッカーが使用するよう設定された訪問者 ID(Cookie が有効な場合は安定した Cookie ID、Cookieless モードではウィンドウスコープのインメモリ ID)を使用します。統計モデル自体は変わりません。唯一の実用上の違いは、Cookieless 環境で訪問者がタブを閉じて開き直すたびに独立に割り当てられる点です。これは正常な挙動で、実験を無効化しません。
次のステップ
- ゴール – 実験で測定するイベントを定義します
- コンバージョンファネル – 複数ステップのコンバージョン経路を追跡します
- Conversion Incidents – 実験の対象ゴールが急落した際にアラートを受け取ります