自動ページトラッキング、カスタムイベント、グローバルのwindow.zenovay関数用カスタムフックを使用して、ZenovayアナリティクスをReactアプリケーションに統合します。
インストール
index.htmlにZenovayトラッキングスクリプトを追加します:
<script
defer
data-tracking-code="YOUR_TRACKING_CODE"
src="https://api.zenovay.com/z.js"
></script>
npmパッケージは不要です。スクリプトは自動的にページビューを追跡し、カスタムトラッキング用のグローバルwindow.zenovay関数を提供します。
基本セットアップ
useZenovayフックの作成
グローバルのwindow.zenovay関数をラップするカスタムフックを作成します:
// hooks/useZenovay.js
export function useZenovay() {
const trackEvent = (name, properties) => {
if (window.zenovay) {
window.zenovay('track', name, properties);
}
};
const trackGoal = (name, properties) => {
if (window.zenovay) {
window.zenovay('goal', name, properties);
}
};
const trackPageview = () => {
if (window.zenovay) {
window.zenovay('page');
}
};
const trackRevenue = (amount, currency, meta) => {
if (window.zenovay) {
window.zenovay('revenue', amount, currency, meta);
}
};
const identify = (userId, properties) => {
if (window.zenovay) {
window.zenovay('identify', userId, properties);
}
};
return { trackEvent, trackGoal, trackPageview, trackRevenue, identify };
}
自動ページトラッキング
React Routerとの使用
Zenovayスクリプトは最初のページ読み込みを自動的にトラックします。React RouterでのSPAルート変更には、ルート変更時にページビューをトラックします:
import { BrowserRouter, useLocation } from 'react-router-dom';
import { useEffect } from 'react';
function PageTracker() {
const location = useLocation();
useEffect(() => {
if (window.zenovay) {
window.zenovay('page');
}
}, [location.pathname]);
return null;
}
function App() {
return (
<BrowserRouter>
<PageTracker />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/pricing" element={<Pricing />} />
</Routes>
</BrowserRouter>
);
}
ページビューはルート変更時に自動的にトラックされます。
カスタムイベント
useZenovayフック
import { useZenovay } from './hooks/useZenovay';
function SignupButton() {
const { trackEvent } = useZenovay();
const handleSignup = () => {
// サインアップクリックをトラック
trackEvent('signup_click', {
plan: 'pro',
source: 'pricing_page'
});
// サインアップロジックを続行
performSignup();
};
return (
<button onClick={handleSignup}>
無料トライアルを開始
</button>
);
}
トラッキング関数
const { trackEvent } = useZenovay();
// シンプルなイベント
trackEvent('button_click');
// プロパティ付き
trackEvent('purchase', {
product_id: 'SKU-001',
value: 99.99,
currency: 'USD'
});
// 値付き
trackEvent('download', { file: 'guide.pdf' });
ゴール追跡
ゴール完了をトラック
import { useZenovay } from './hooks/useZenovay';
import { useEffect } from 'react';
function CheckoutSuccess({ order }) {
const { trackGoal } = useZenovay();
useEffect(() => {
trackGoal('purchase', {
value: order.total,
order_id: order.id,
products: order.items
});
}, [order]);
return <div>ご注文ありがとうございます!</div>;
}
ユーザー識別
ユーザーを識別
import { useZenovay } from './hooks/useZenovay';
import { useAuth } from './auth';
import { useEffect } from 'react';
function UserIdentifier() {
const { user, isAuthenticated } = useAuth();
const { identify } = useZenovay();
useEffect(() => {
if (isAuthenticated && user) {
identify(user.id, {
email: user.email,
name: user.name,
plan: user.subscription
});
}
}, [user, isAuthenticated]);
return null;
}
認証フロー内
async function handleLogin(credentials) {
const user = await login(credentials);
// ログイン後に識別
if (window.zenovay) {
window.zenovay('identify', user.id, {
email: user.email
});
}
navigate('/dashboard');
}
売上トラッキング
売上をトラック
import { useZenovay } from './hooks/useZenovay';
import { useEffect } from 'react';
function OrderConfirmation({ order }) {
const { trackRevenue } = useZenovay();
useEffect(() => {
trackRevenue(order.total, 'USD', {
order_id: order.id,
items: order.items.map(item => ({
id: item.sku,
name: item.name,
price: item.price,
quantity: item.quantity
}))
});
}, [order]);
return (
<div>
<h1>注文が確定しました!</h1>
<p>注文番号 #{order.id}</p>
</div>
);
}
イベント追跡コンポーネント
トラック可能なボタン
import { useZenovay } from './hooks/useZenovay';
function TrackableButton({ event, eventData, children, ...props }) {
const { trackEvent } = useZenovay();
const handleClick = (e) => {
trackEvent(event, eventData);
props.onClick?.(e);
};
return (
<button {...props} onClick={handleClick}>
{children}
</button>
);
}
// 使用方法
<TrackableButton
event="cta_click"
eventData={{ location: 'hero' }}
onClick={handleSignup}
>
はじめる
</TrackableButton>
マウント時にトラック
import { useZenovay } from './hooks/useZenovay';
import { useEffect } from 'react';
function TrackOnMount({ event, eventData }) {
const { trackEvent } = useZenovay();
useEffect(() => {
trackEvent(event, eventData);
}, []);
return null;
}
// 使用方法
<TrackOnMount
event="pricing_viewed"
eventData={{ referrer: document.referrer }}
/>
TypeScriptサポート
型定義
// types/zenovay.d.ts
interface ZenovayFunction {
(command: 'track', name: string, properties?: Record<string, unknown>): void;
(command: 'identify', userId: string, traits?: Record<string, unknown>): void;
(command: 'goal', name: string, properties?: Record<string, unknown>): void;
(command: 'page'): void;
(command: 'revenue', amount: number, currency: string, meta?: Record<string, unknown>): void;
}
declare global {
interface Window {
zenovay: ZenovayFunction;
}
}
export {};
型付きフック
// hooks/useZenovay.ts
export function useZenovay() {
const trackEvent = (name: string, properties?: Record<string, unknown>) => {
if (window.zenovay) {
window.zenovay('track', name, properties);
}
};
const trackGoal = (name: string, properties?: Record<string, unknown>) => {
if (window.zenovay) {
window.zenovay('goal', name, properties);
}
};
const identify = (userId: string, properties?: Record<string, unknown>) => {
if (window.zenovay) {
window.zenovay('identify', userId, properties);
}
};
return { trackEvent, trackGoal, identify };
}
サーバーサイドレンダリング
SSR問題を回避
window.zenovay関数はブラウザでのみ利用可能です。使用前に必ず確認してください:
import { useEffect, useState } from 'react';
function ZenovayWrapper({ children }) {
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
}, []);
// コンポーネントのマウント後のみトラック(クライアント側)
if (!mounted) {
return children;
}
return children;
}
テスト
フックをモック
// test-utils.jsx
import { vi } from 'vitest';
export const mockZenovay = {
trackEvent: vi.fn(),
trackGoal: vi.fn(),
identify: vi.fn(),
trackPageview: vi.fn(),
trackRevenue: vi.fn()
};
vi.mock('./hooks/useZenovay', () => ({
useZenovay: () => mockZenovay
}));
テスト例
import { render, fireEvent, screen } from '@testing-library/react';
import { mockZenovay } from './test-utils';
import SignupButton from './SignupButton';
test('サインアップクリックをトラック', () => {
render(<SignupButton />);
fireEvent.click(screen.getByText('無料トライアルを開始'));
expect(mockZenovay.trackEvent).toHaveBeenCalledWith('signup_click', expect.any(Object));
});
一般的なパターン
Eコマーストラッキング
import { useZenovay } from './hooks/useZenovay';
import { useEffect } from 'react';
function ProductPage({ product }) {
const { trackEvent } = useZenovay();
useEffect(() => {
trackEvent('product_viewed', {
product_id: product.id,
product_name: product.name,
price: product.price,
category: product.category
});
}, [product.id]);
const handleAddToCart = () => {
trackEvent('add_to_cart', {
product_id: product.id,
price: product.price,
quantity: 1
});
};
return (
<div>
<h1>{product.name}</h1>
<button onClick={handleAddToCart}>カートに追加</button>
</div>
);
}
フォームトラッキング
import { useZenovay } from './hooks/useZenovay';
function ContactForm() {
const { trackEvent, trackGoal } = useZenovay();
const handleSubmit = async (data) => {
trackEvent('form_submitted', {
form_name: 'contact',
has_phone: !!data.phone
});
await submitForm(data);
trackGoal('contact_form');
};
return (
<form onSubmit={handleSubmit}>
{/* フォームフィールド */}
</form>
);
}
トラブルシューティング
イベントがトラックされない
確認してください:
- スクリプトタグがindex.htmlにあるか
- トラッキングコードが正しいか
- 広告ブロッカーにブロックされていないか
- コンソールにエラーがないか
ページビューが欠落している
確認してください:
- PageTrackerコンポーネントがマウントされているか
- React Routerが正しく設定されているか
- ルートがルーター内でレンダリングされているか
重複トラッキング
回避してください:
- 複数のスクリプトタグ
- 手動 + 自動トラッキング
- StrictModeによるダブルエフェクト