RevenueUI ドキュメント

カスタムイベントとゴール

アプリケーションから重要なコンバージョンイベントを送り、RevenueUIで計測可能なゴールにします。

カスタムイベントの仕組み

登録完了、リードフォーム送信、チェックアウト開始など、事業上重要な完了アクションに使います。トラッカーは現在ページと訪問者またはセッションIDをイベントに付け、ゴールを達成した訪問者をRevenueUIで表示できるようにします。

最後のtrack()はブラウザから呼びます。サーバーは成功を判定できますが、PHP、Python、Ruby、Node.jsのサーバーコードからはwindow.revenueUIや帰属に使うブラウザIDへアクセスできません。

  1. 訪問者がブラウザで処理を開始する。
  2. アプリケーションまたはサーバーが処理を完了する。
  3. ブラウザが成功レスポンスを受け取るか、確認済み成功ページへ戻る。
  4. ブラウザがtrack()を一度呼ぶ。
  5. RevenueUIで完全に同じイベント名のゴールを作成する。

最初のボタンクリックでは記録しないでください。OAuthのキャンセル、検証エラー、決済拒否が起こり得ます。

再利用できるブラウザヘルパー

スクリプトはdeferで読み込まれるため、準備前はrevenueui:readyを待ちます。

export function trackRevenueUI(eventName) {
  const send = () => window.revenueUI?.track(eventName);

  if (window.revenueUI?.ready) {
    send();
    return;
  }

  window.addEventListener("revenueui:ready", send, { once: true });
}

イベント名は英字で始め、小文字英字・数字・アンダースコアのみ、32文字以内です。page_viewpage_engagementは予約済みです。

signup_completed
lead_form_submitted
checkout_started
demo_booked

カスタムプロパティは利用できません。メール、顧客名、注文番号などの個人データをイベント名へ含めないでください。

JavaScriptとTypeScript

APIが成功を確認した後だけ送信します。

async function createAccount(formData) {
  const response = await fetch("/api/signup", { method: "POST", body: formData });
  if (!response.ok) throw new Error("Signup failed");
  trackRevenueUI("signup_completed");
}

TypeScriptではWindow型と許可するイベント名を定義できます。

export {};
declare global {
  interface Window {
    revenueUI?: { readonly ready: boolean; track(eventName: string): void };
  }
}

type RevenueUIEvent = "signup_completed" | "lead_form_submitted" | "checkout_started";

ReactとNext.js App Router

フォームのAPIレスポンス成功後に送信します。マウント時だけのEffectは開発モードや再訪問で重複し得るため避けてください。App Routerではwindow.revenueUIをClient Componentからだけ使い、Server Actionは成功結果を返します。

"use client";

export function SignupForm() {
  async function handleSubmit(formData: FormData) {
    const result = await createAccount(formData);
    if (result.success) trackRevenueUI("signup_completed");
  }
  return <form action={handleSubmit}>{/* fields */}</form>;
}

OAuthはサーバーでコールバックを検証し、短時間の一回限り成功シグナルを持つクライアント完了ページへリダイレクトします。OAuthボタンのクリックは完了として扱いません。

Vue、Nuxt、Angular、SvelteKit

いずれもクライアント側のハンドラーで成功レスポンスを確認してからヘルパーを呼びます。NuxtのサーバールートやSvelteKitのサーバーActionから直接トラッカーを呼ばず、成功状態をブラウザへ返してください。Angularではボタンの(click)ではなくサービスの成功コールバック、SvelteKitでは成功したフォームハンドラーまたは一回限りの成功ページを使います。

ExpressとNode.js

Expressは成功結果をブラウザJavaScriptへ返します。

app.post("/api/signup", async (request, response) => {
  const account = await createAccount(request.body);
  response.status(201).json({ created: true, accountId: account.id });
});

ブラウザ側でresponse.status === 201を確認してから送信します。サーバーだけのイベントにはRevenueUIが使うブラウザの訪問者・セッションIDが自動で付きません。

Laravel、Django、Rails

サーバー処理の成功後に一回限りのFlashまたはSession値を設定し、リダイレクト先のページで安全にJSONエンコードしてブラウザから送信します。

return redirect()->route('welcome')->with('revenueui_event', 'signup_completed');
@if (session('revenueui_event'))
  <script>
    const eventName = {{ Js::from(session('revenueui_event')) }};
    const send = () => window.revenueUI?.track(eventName);
    if (window.revenueUI?.ready) send();
    else window.addEventListener("revenueui:ready", send, { once: true });
  </script>
@endif

DjangoではSession値をpop、Railsではflashを使うと通常の再読み込みで再送されません。テンプレートへ直接文字列連結せず、各フレームワークの安全なJSONエンコードを使ってください。

重複イベントを防ぐ

同じ完了をフォームハンドラーと成功ページの両方から送らず、権威ある成功経路を1つにします。再訪問可能なクライアントルートでは、機密性のない完了トークンをSession Storageへ保存できます。

export function trackRevenueUIOnce(eventName, completionId) {
  const storageKey = `revenueui:${eventName}:${completionId}`;
  if (sessionStorage.getItem(storageKey)) return;
  const send = () => {
    window.revenueUI?.track(eventName);
    sessionStorage.setItem(storageKey, "1");
  };
  if (window.revenueUI?.ready) send();
  else window.addEventListener("revenueui:ready", send, { once: true });
}

不透明で短命な完了IDを使い、メールなどを保存キーに含めません。基礎処理のサーバー側冪等性は別途必要です。

RevenueUIでゴールを作る

  1. Webサイト詳細のゴール訪問者タブを開く。
  2. ゴールを追加を選ぶ。
  3. Completed signupなどの表示名を入力する。
  4. アプリと同じsignup_completedなどのイベント名を入力する。
  5. 保存する。

イベント名は大文字小文字を区別します。ゴール作成後に受信した完了が集計されます。

実装を確認する

成功経路と失敗経路を1回ずつテストします。成功時にイベントとゴール訪問者が表示され、成功ページの再読み込みで重複せず、無効入力やキャンセル時に送られないことを確認します。届かない場合はスクリプト、公開キー、登録オリジン、同意状態、コンテンツブロッカーを確認してください。