メインコンテンツへスキップ
無料15 minutes中級

Vue.js統合

ZenovayとVue.jsアプリケーションの統合 — Vue 3、Nuxt、Composition APIのサポート。このAPI統合ガイドでVueについて学びます。

vuenuxtjavascriptintegrationspa
最終更新日:

トラッキングスクリプトタグとグローバルの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');
  }
}

次のステップ

この記事は役に立ちましたか?