トラッキングスクリプトタグとグローバルのwindow.zenovay関数を使用して、ZenovayアナリティクスをVue.jsまたはNuxtアプリケーションに統合します。
インストール
index.htmlにZenovayトラッキングスクリプトを追加します:
<!-- index.html -->
<script
defer
data-tracking-code="YOUR_TRACKING_CODE"
src="https://api.zenovay.com/z.js"
></script>
npmパッケージは不要です。スクリプトは自動的にページビューを追跡し、カスタムイベント用のグローバルwindow.zenovay関数を提供します。
Vue 3セットアップ
コンポーザブルのラッパー
Vueコンポーネントで使用するためにグローバルのwindow.zenovay関数をラップするコンポーザブルを作成します:
// composables/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 };
}
利用可能な関数
const {
trackEvent, // カスタムイベントをトラック
trackGoal, // ゴールコンバージョンをトラック
trackPageview, // 手動ページビュー
trackRevenue, // 収益をトラック
identify // ユーザーを識別
} = useZenovay();
イベントトラッキング
基本的なイベント
<script setup>
import { useZenovay } from '@/composables/useZenovay';
const { trackEvent } = useZenovay();
const handleSignup = () => {
trackEvent('signup_click', {
plan: 'pro',
source: 'pricing'
});
};
</script>
<template>
<button @click="handleSignup">
無料トライアルを始める
</button>
</template>
コンポーネントイベント
<script setup>
import { useZenovay } from '@/composables/useZenovay';
const { trackEvent } = useZenovay();
const props = defineProps(['product']);
const addToCart = () => {
trackEvent('add_to_cart', {
product_id: props.product.id,
product_name: props.product.name,
price: props.product.price
});
// カート処理を続行
emit('add', props.product);
};
</script>
<template>
<button @click="addToCart">カートに追加</button>
</template>
ゴールトラッキング
<script setup>
import { useZenovay } from '@/composables/useZenovay';
import { onMounted } from 'vue';
const props = defineProps(['order']);
const { trackGoal } = useZenovay();
onMounted(() => {
trackGoal('purchase', {
value: props.order.total,
order_id: props.order.id
});
});
</script>
ユーザー識別
<script setup>
import { useZenovay } from '@/composables/useZenovay';
import { watch } from 'vue';
import { useUserStore } from '@/stores/user';
const userStore = useUserStore();
const { identify } = useZenovay();
watch(
() => userStore.user,
(user) => {
if (user) {
identify(user.id, {
email: user.email,
name: user.name,
plan: user.subscription
});
}
},
{ immediate: true }
);
</script>
収益トラッキング
<script setup>
import { useZenovay } from '@/composables/useZenovay';
import { onMounted } from 'vue';
const props = defineProps(['order']);
const { trackRevenue } = useZenovay();
onMounted(() => {
trackRevenue(props.order.total, 'USD', {
order_id: props.order.id,
items: props.order.items.map(item => ({
id: item.sku,
name: item.name,
price: item.price,
quantity: item.quantity
}))
});
});
</script>
<template>
<div>
<h1>注文確認完了!</h1>
<p>注文 #{{ order.id }}</p>
</div>
</template>
Nuxt 3統合
nuxt.config.tsでスクリプトを追加
// nuxt.config.ts
export default defineNuxtConfig({
app: {
head: {
script: [
{
src: 'https://api.zenovay.com/z.js',
defer: true,
'data-tracking-code': 'YOUR_TRACKING_CODE'
}
]
}
}
});
環境変数
# .env
NUXT_PUBLIC_ZENOVAY_TRACKING_CODE=your-tracking-code
// nuxt.config.ts
export default defineNuxtConfig({
app: {
head: {
script: [
{
src: 'https://api.zenovay.com/z.js',
defer: true,
'data-tracking-code': process.env.NUXT_PUBLIC_ZENOVAY_TRACKING_CODE
}
]
}
}
});
Nuxtコンポーザブル
<script setup>
// 上記と同じコンポーザブルを使用
import { useZenovay } from '@/composables/useZenovay';
const { trackEvent } = useZenovay();
const handleClick = () => {
trackEvent('cta_click', { location: 'hero' });
};
</script>
Vue Router統合
自動トラッキング
Zenovayスクリプトは自動的にページビューをトラックします。SPAのルート変更には、ルーターのafterEachフックを追加します:
// router/index.js
import { createRouter, createWebHistory } from 'vue-router';
const router = createRouter({
history: createWebHistory(),
routes: [/* your routes */]
});
// ルート変更時にページビューをトラック
router.afterEach((to) => {
if (window.zenovay) {
window.zenovay('page');
}
});
export default router;
ページビューは以下で自動的にトラックされます:
- 初期読み込み
- ルート変更
- ハッシュ変更(オプション)
手動ルートトラッキング
<script setup>
import { useZenovay } from '@/composables/useZenovay';
import { useRouter } from 'vue-router';
import { watch } from 'vue';
const router = useRouter();
const { trackPageview } = useZenovay();
watch(
() => router.currentRoute.value.path,
(path) => {
trackPageview(path);
}
);
</script>
ディレクティブ
v-trackディレクティブ
<template>
<!-- クリックをトラック -->
<button v-track:click="{ event: 'signup_click', plan: 'pro' }">
サインアップ
</button>
<!-- 表示をトラック -->
<div v-track:visible="{ event: 'section_viewed', section: 'pricing' }">
料金セクション
</div>
</template>
ディレクティブを登録
// main.js
import { createApp } from 'vue';
const app = createApp(App);
// window.zenovayを使用したカスタムv-trackディレクティブ
app.directive('track', {
mounted(el, binding) {
const { event, ...properties } = binding.value;
const eventType = binding.arg || 'click';
if (eventType === 'click') {
el.addEventListener('click', () => {
if (window.zenovay) {
window.zenovay('track', event, properties);
}
});
} else if (eventType === 'visible') {
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
if (window.zenovay) {
window.zenovay('track', event, properties);
}
observer.unobserve(el);
}
});
});
observer.observe(el);
}
}
});
Options API
Options APIの使用
<script>
export default {
methods: {
handleClick() {
if (window.zenovay) {
window.zenovay('track', 'button_click', {
button: 'signup'
});
}
}
}
};
</script>
Pinia統合
アナリティクス付きストア
// stores/cart.js
import { defineStore } from 'pinia';
export const useCartStore = defineStore('cart', {
state: () => ({
items: []
}),
actions: {
addItem(product) {
this.items.push(product);
// グローバルzenovayオブジェクトを使用してトラック
if (window.zenovay) {
window.zenovay('track', 'add_to_cart', {
product_id: product.id,
price: product.price
});
}
}
}
});
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 {};
型付きの使用
<script setup lang="ts">
import { useZenovay } from '@/composables/useZenovay';
interface PurchaseEvent {
product_id: string;
price: number;
quantity: number;
}
const { trackEvent } = useZenovay();
const handlePurchase = (data: PurchaseEvent) => {
trackEvent('purchase', data);
};
</script>
テスト
コンポーザブルのモック
// tests/mocks/zenovay.js
import { vi } from 'vitest';
export const mockZenovay = {
trackEvent: vi.fn(),
trackGoal: vi.fn(),
identify: vi.fn(),
trackPageview: vi.fn()
};
vi.mock('@/composables/useZenovay', () => ({
useZenovay: () => mockZenovay
}));
テスト例
import { mount } from '@vue/test-utils';
import { mockZenovay } from './mocks/zenovay';
import SignupButton from '@/components/SignupButton.vue';
test('tracks signup click', async () => {
const wrapper = mount(SignupButton);
await wrapper.find('button').trigger('click');
expect(mockZenovay.trackEvent).toHaveBeenCalledWith(
'signup_click',
expect.any(Object)
);
});
トラブルシューティング
イベントがトラックされない
確認事項:
- スクリプトタグがindex.htmlにあるか
- トラッキングコードが有効か
- 広告ブロッカーにブロックされていないか
- コンソールにエラーがないか
ルータートラッキングが機能しない
確認事項:
- ルーターのafterEachフックが設定されているか
- ルート変更時に
window.zenovayが利用可能か
SSRの問題
Nuxt/SSRの場合:
if (process.client) {
if (window.zenovay) {
window.zenovay('track', 'client_only');
}
}