Intégrez Zenovay analytics dans n'importe quel framework JavaScript ou application vanilla JavaScript en utilisant notre API de suivi flexible.
Installation universelle du script
Balise de script basique
Fonctionne avec n'importe quel framework :
<script
defer
data-tracking-code="YOUR_TRACKING_CODE"
src="https://api.zenovay.com/z.js"
></script>
Attributs du script
| Attribut | Description |
|---|---|
data-tracking-code | Requis. Votre code de suivi du site web |
defer | Recommandé. Charge le script sans bloquer le rendu de la page |
Configuration standard
<script
defer
data-tracking-code="YOUR_TRACKING_CODE"
src="https://api.zenovay.com/z.js"
></script>
JavaScript vanilla
Utilisation basique
// Suivre un événement
window.zenovay('track', 'button_click', {
button_id: 'signup',
location: 'hero'
});
// Suivre une page (si le suivi automatique est désactivé)
window.zenovay('page');
// Identifier un utilisateur
window.zenovay('identify', 'user-123', {
email: '[email protected]',
plan: 'pro'
});
// Suivre une conversion
window.zenovay('goal', 'purchase', {
value: 99.99
});
// Suivre les revenus
window.zenovay('revenue', 149.99, 'USD', {
order_id: 'ORD-001'
});
Attendre le chargement du script
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();
}
// Utilisation
waitForZenovay((zenovay) => {
zenovay('track', 'app_ready');
});
Modèle de file d'attente d'événements
// Fonction de file (fonctionne avant le chargement du script)
window.zenovay = window.zenovay || function() {
(window.zenovay.q = window.zenovay.q || []).push(arguments);
};
// Vous pouvez maintenant appeler zenovay() immédiatement, même avant le chargement du script
window.zenovay('track', 'early_event', { source: 'inline' });
window.zenovay('page');
Intégration Svelte
Configuration dans App.svelte
<script>
import { onMount } from 'svelte';
import { page } from '$app/stores';
onMount(() => {
// Suivre la première page
if (window.zenovay) {
window.zenovay('page');
}
});
// Suivre les changements de route
$: if ($page && window.zenovay) {
window.zenovay('page');
}
</script>
Store 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();
Utilisation dans les composants Svelte
<script>
import { analytics } from '../stores/analytics';
function handleClick() {
analytics.track('button_click', { button: 'cta' });
}
</script>
<button on:click={handleClick}>
Cliquez ici
</button>
Intégration SvelteKit
// hooks.client.js
import { page } from '$app/stores';
page.subscribe(($page) => {
if (typeof window !== 'undefined' && window.zenovay && $page) {
window.zenovay('page');
}
});
Intégration Angular
Créer le service
// 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);
}
}
}
Utilisation dans les composants
// signup.component.ts
import { Component } from '@angular/core';
import { AnalyticsService } from './analytics.service';
@Component({
selector: 'app-signup',
template: `<button (click)="handleSignup()">S'inscrire</button>`
})
export class SignupComponent {
constructor(private analytics: AnalyticsService) {}
handleSignup() {
this.analytics.track('signup_click', {
source: 'header'
});
}
}
Configuration du module
// app.module.ts
import { APP_INITIALIZER, NgModule } from '@angular/core';
import { AnalyticsService } from './analytics.service';
export function initAnalytics(analytics: AnalyticsService) {
return () => {
// Initialiser le suivi
};
}
@NgModule({
providers: [
AnalyticsService,
{
provide: APP_INITIALIZER,
useFactory: initAnalytics,
deps: [AnalyticsService],
multi: true
}
]
})
export class AppModule {}
Intégration Ember.js
Créer le service
// 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);
}
}
}
Intégration Alpine.js
<div x-data="{ analytics: $store.analytics }">
<button @click="analytics.track('click', { button: 'cta' })">
Cliquez ici
</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>
Intégration jQuery
// Initialiser l'aide de suivi
$.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);
}
}
};
// Utilisation
$(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);
Utilisation :
<analytics-tracker
data-event="cta_click"
data-prop-button="hero"
data-prop-page="home"
>
<button>Commencer</button>
</analytics-tracker>
Modèles pour Single Page Applications (SPA)
Suivi avec History API
// Suivre les changements d'historique
(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) {
// Petit délai pour s'assurer que le DOM est à jour
setTimeout(() => {
window.zenovay('page');
}, 100);
}
}
})();
Routage basé sur le hash
window.addEventListener('hashchange', function() {
if (window.zenovay) {
window.zenovay('page');
}
});
Définitions 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 {};
Modèle de bibliothèque wrapper
Créez un wrapper réutilisable :
// 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();
Testez votre intégration
Mode debug
Activez la journalisation du debug pour voir l'activité du tracker dans la console du navigateur. Il y a trois façons de l'activer :
<!-- 1. Ajoutez l'attribut data-debug à la balise script -->
<script
defer
data-tracking-code="YOUR_TRACKING_CODE"
data-debug="true"
src="https://api.zenovay.com/z.js"
></script>
2. Ajoutez ?zenovay_debug=true à n'importe quelle URL de page (pratique pour la production).
3. La journalisation du debug est active automatiquement lors de l'exécution sur localhost.
Avec le debug activé, le tracker enregistre chaque événement envoyé dans la console.
Étapes de vérification
- Ouvrez les DevTools du navigateur
- Allez à l'onglet Réseau (Network)
- Filtrez par « zenovay » ou « analytics »
- Effectuez des actions
- Vérifiez que les requêtes sont envoyées
Événement de test
// Test rapide
if (window.zenovay) {
window.zenovay('track', 'test_event', {
test: true,
timestamp: Date.now()
});
console.log('Événement de test envoyé');
} else {
console.error('Zenovay non chargé');
}
Dépannage
Le script ne charge pas
Vérifiez :
- L'URL du script est correcte
- Pas d'interférence du bloqueur de publicités
- L'ID du site web est valide
- Les requêtes réseau sont visibles
Les événements ne sont pas suivis
Vérifiez :
window.zenovayexiste- Le format des données est correct
- Il n'y a pas d'erreurs JavaScript
- Le domaine est autorisé
Problèmes de navigation en SPA
Assurez-vous que :
- Les changements de route sont détectés
trackPageviewest appelé lors de la navigation- Il n'y a pas de suivi dupliqué