柔軟なトラッキングAPIを使用して、あらゆるJavaScriptフレームワークまたはバニラJavaScriptアプリケーションにZenovayアナリティクスを統合します。
ユニバーサルスクリプトのインストール
基本的なスクリプトタグ
あらゆるフレームワークで動作します:
<script
defer
data-tracking-code="YOUR_TRACKING_CODE"
src="https://api.zenovay.com/z.js"
></script>
スクリプト属性
| 属性 | 説明 |
|---|---|
data-tracking-code | 必須。ウェブサイトのトラッキングコード |
defer | 推奨。ページレンダリングをブロックせずにスクリプトを読み込む |
標準設定
<script
defer
data-tracking-code="YOUR_TRACKING_CODE"
src="https://api.zenovay.com/z.js"
></script>
バニラJavaScript
基本的な使い方
// イベントをトラック
window.zenovay('track', 'button_click', {
button_id: 'signup',
location: 'hero'
});
// ページビューをトラック(自動トラック無効の場合)
window.zenovay('page');
// ユーザーを識別
window.zenovay('identify', 'user-123', {
email: '[email protected]',
plan: 'pro'
});
// ゴールをトラック
window.zenovay('goal', 'purchase', {
value: 99.99
});
// 売上をトラック
window.zenovay('revenue', 149.99, 'JPY', {
order_id: 'ORD-001'
});
スクリプト読み込みを待つ
function waitForZenovay(callback, maxWait = 5000) {
const startTime = Date.now();
function check() {
if (window.zenovay) {
callback(window.zenovay);
} else if (Date.now() - startTime < maxWait) {
requestAnimationFrame(check);
}
}
check();
}
// 使用例
waitForZenovay((zenovay) => {
zenovay('track', 'app_ready');
});
イベントキューパターン
// キュー関数(スクリプト読み込み前でも動作)
window.zenovay = window.zenovay || function() {
(window.zenovay.q = window.zenovay.q || []).push(arguments);
};
// スクリプト読み込み前でも即座に呼び出し可能
window.zenovay('track', 'early_event', { source: 'inline' });
window.zenovay('page');
Svelte統合
App.svelteのセットアップ
<script>
import { onMount } from 'svelte';
import { page } from '$app/stores';
onMount(() => {
// 最初のページビューをトラック
if (window.zenovay) {
window.zenovay('page');
}
});
// ルート変更をトラック
$: if ($page && window.zenovay) {
window.zenovay('page');
}
</script>
Svelteストア
// stores/analytics.js
import { writable } from 'svelte/store';
function createAnalyticsStore() {
const { subscribe } = writable(null);
return {
subscribe,
track: (event, data) => {
if (typeof window !== 'undefined' && window.zenovay) {
window.zenovay('track', event, data);
}
},
identify: (userId, properties) => {
if (typeof window !== 'undefined' && window.zenovay) {
window.zenovay('identify', userId, properties);
}
},
trackGoal: (name, value) => {
if (typeof window !== 'undefined' && window.zenovay) {
window.zenovay('goal', name, { value });
}
}
};
}
export const analytics = createAnalyticsStore();
Svelteコンポーネント使用例
<script>
import { analytics } from '../stores/analytics';
function handleClick() {
analytics.track('button_click', { button: 'cta' });
}
</script>
<button on:click={handleClick}>
クリック
</button>
SvelteKit統合
// hooks.client.js
import { page } from '$app/stores';
page.subscribe(($page) => {
if (typeof window !== 'undefined' && window.zenovay && $page) {
window.zenovay('page');
}
});
Angular統合
サービスの作成
// analytics.service.ts
import { Injectable } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import { filter } from 'rxjs/operators';
declare global {
interface Window {
zenovay: {
(command: 'track', event: string, data?: Record<string, any>): void;
(command: 'page'): void;
(command: 'goal', name: string, data?: Record<string, any>): void;
(command: 'revenue', amount: number, currency: string, meta?: Record<string, any>): void;
(command: 'identify', userId: string, properties?: Record<string, any>): void;
};
}
}
@Injectable({
providedIn: 'root'
})
export class AnalyticsService {
constructor(private router: Router) {
this.setupRouteTracking();
}
private setupRouteTracking() {
this.router.events.pipe(
filter(event => event instanceof NavigationEnd)
).subscribe((event: NavigationEnd) => {
this.trackPageview(event.urlAfterRedirects);
});
}
track(event: string, data?: Record<string, any>) {
if (window.zenovay) {
(window as any).zenovay('track', event, data);
}
}
trackPageview() {
if (window.zenovay) {
(window as any).zenovay('page');
}
}
trackGoal(name: string, value?: number) {
if (window.zenovay) {
(window as any).zenovay('goal', name, { value });
}
}
identify(userId: string, properties?: Record<string, any>) {
if (window.zenovay) {
(window as any).zenovay('identify', userId, properties);
}
}
}
コンポーネント使用例
// signup.component.ts
import { Component } from '@angular/core';
import { AnalyticsService } from './analytics.service';
@Component({
selector: 'app-signup',
template: `<button (click)="handleSignup()">登録</button>`
})
export class SignupComponent {
constructor(private analytics: AnalyticsService) {}
handleSignup() {
this.analytics.track('signup_click', {
source: 'header'
});
}
}
モジュール設定
// app.module.ts
import { APP_INITIALIZER, NgModule } from '@angular/core';
import { AnalyticsService } from './analytics.service';
export function initAnalytics(analytics: AnalyticsService) {
return () => {
// トラッキング初期化
};
}
@NgModule({
providers: [
AnalyticsService,
{
provide: APP_INITIALIZER,
useFactory: initAnalytics,
deps: [AnalyticsService],
multi: true
}
]
})
export class AppModule {}
Ember.js統合
サービスの作成
// app/services/analytics.js
import Service from '@ember/service';
import { inject as service } from '@ember/service';
export default class AnalyticsService extends Service {
@service router;
constructor() {
super(...arguments);
this.setupRouteTracking();
}
setupRouteTracking() {
this.router.on('routeDidChange', () => {
this.trackPageview(this.router.currentURL);
});
}
track(event, data) {
if (window.zenovay) {
window.zenovay('track', event, data);
}
}
trackPageview() {
if (window.zenovay) {
window.zenovay('page');
}
}
identify(userId, properties) {
if (window.zenovay) {
window.zenovay('identify', userId, properties);
}
}
}
Alpine.js統合
<div x-data="{ analytics: $store.analytics }">
<button @click="analytics.track('click', { button: 'cta' })">
クリック
</button>
</div>
<script>
document.addEventListener('alpine:init', () => {
Alpine.store('analytics', {
track(event, data) {
if (window.zenovay) {
window.zenovay('track', event, data);
}
},
identify(userId, properties) {
if (window.zenovay) {
window.zenovay('identify', userId, properties);
}
}
});
});
</script>
jQuery統合
// トラッキングヘルパー初期化
$.zenovay = {
track: function(event, data) {
if (window.zenovay) {
window.zenovay('track', event, data);
}
},
identify: function(userId, properties) {
if (window.zenovay) {
window.zenovay('identify', userId, properties);
}
}
};
// 使用例
$(document).ready(function() {
$('#signup-btn').click(function() {
$.zenovay.track('signup_click', {
button: $(this).data('name')
});
});
});
Web Components
// analytics-tracker.js
class AnalyticsTracker extends HTMLElement {
connectedCallback() {
this.addEventListener('click', this.handleClick.bind(this));
}
handleClick() {
const event = this.getAttribute('data-event');
const dataAttrs = {};
for (const attr of this.attributes) {
if (attr.name.startsWith('data-prop-')) {
const key = attr.name.replace('data-prop-', '');
dataAttrs[key] = attr.value;
}
}
if (window.zenovay && event) {
window.zenovay('track', event, dataAttrs);
}
}
}
customElements.define('analytics-tracker', AnalyticsTracker);
使用例:
<analytics-tracker
data-event="cta_click"
data-prop-button="hero"
data-prop-page="home"
>
<button>スタート</button>
</analytics-tracker>
SPA(Single Page Application)パターン
History APIトラッキング
// 履歴変更をトラック
(function() {
const pushState = history.pushState;
const replaceState = history.replaceState;
history.pushState = function() {
pushState.apply(history, arguments);
trackPageChange();
};
history.replaceState = function() {
replaceState.apply(history, arguments);
trackPageChange();
};
window.addEventListener('popstate', trackPageChange);
function trackPageChange() {
if (window.zenovay) {
// DOMの更新を確認するため少し待つ
setTimeout(() => {
window.zenovay('page');
}, 100);
}
}
})();
ハッシュベースルーティング
window.addEventListener('hashchange', function() {
if (window.zenovay) {
window.zenovay('page');
}
});
TypeScript定義
// types/zenovay.d.ts
interface ZenovayEventData {
[key: string]: string | number | boolean | undefined;
}
interface ZenovayRevenueData {
order_id: string;
value: number;
currency?: string;
items?: Array<{
id: string;
name: string;
price: number;
quantity: number;
}>;
}
interface Zenovay {
(command: 'track', event: string, data?: ZenovayEventData): void;
(command: 'page'): void;
(command: 'goal', name: string, data?: { value?: number }): void;
(command: 'revenue', amount: number, currency: string, meta?: Record<string, unknown>): void;
(command: 'identify', userId: string, properties?: ZenovayEventData): void;
}
declare global {
interface Window {
zenovay?: Zenovay;
}
}
export {};
ラッパーライブラリパターン
再利用可能なラッパーを作成:
// lib/analytics.ts
class Analytics {
private queue: Array<() => void> = [];
private ready = false;
constructor() {
this.waitForScript();
}
private waitForScript() {
const check = () => {
if (window.zenovay) {
this.ready = true;
this.processQueue();
} else {
requestAnimationFrame(check);
}
};
check();
}
private processQueue() {
this.queue.forEach(fn => fn());
this.queue = [];
}
private execute(fn: () => void) {
if (this.ready) {
fn();
} else {
this.queue.push(fn);
}
}
track(event: string, data?: Record<string, any>) {
this.execute(() => (window.zenovay as any)('track', event, data));
}
pageview() {
this.execute(() => (window.zenovay as any)('page'));
}
identify(userId: string, properties?: Record<string, any>) {
this.execute(() => (window.zenovay as any)('identify', userId, properties));
}
goal(name: string, value?: number) {
this.execute(() => (window.zenovay as any)('goal', name, { value }));
}
revenue(amount: number, currency: string, meta?: Record<string, any>) {
this.execute(() => (window.zenovay as any)('revenue', amount, currency, meta));
}
}
export const analytics = new Analytics();
統合のテスト
デバッグモード
ブラウザコンソールでトラッカーアクティビティを見るためにデバッグログを有効化します。有効化する方法は3つあります:
<!-- 1. スクリプトタグにdata-debug属性を追加 -->
<script
defer
data-tracking-code="YOUR_TRACKING_CODE"
data-debug="true"
src="https://api.zenovay.com/z.js"
></script>
2. ページURLに ?zenovay_debug=true を追加(本番環境での確認に便利です)
3. localhost での実行時はデバッグログが自動的に有効になります
デバッグを有効化すると、トラッカーはコンソールに送信された各イベントをログします。
検証ステップ
- ブラウザのDevToolsを開く
- ネットワークタブに移動
- 「zenovay」または「analytics」でフィルタリング
- アクションを実行
- リクエストが送信されたことを確認
テストイベント
// クイックテスト
if (window.zenovay) {
window.zenovay('track', 'test_event', {
test: true,
timestamp: Date.now()
});
console.log('テストイベントを送信しました');
} else {
console.error('Zenovayが読み込まれていません');
}
トラブルシューティング
スクリプトが読み込まれない場合
確認事項:
- スクリプトURLが正しいか
- 広告ブロッカーによる干渉がないか
- ウェブサイトIDが有効か
- ネットワークリクエストが確認できるか
イベントがトラックされない場合
確認事項:
window.zenovayが存在するか- データ形式が正しいか
- JavaScriptエラーがないか
- ドメインが許可されているか
SPAナビゲーションの問題
確認事項:
- ルート変更が検出されているか
- ナビゲーション時に
trackPageviewが呼び出されているか - 重複トラッキングがないか