Intégrez Zenovay dans vos applications React pour un suivi complet des pages vues, événements personnalisés et un hook personnalisé pour la fonction globale window.zenovay.
Installation
Ajoutez le script de suivi de Zenovay à votre index.html :
<script
defer
data-tracking-code="YOUR_TRACKING_CODE"
src="https://api.zenovay.com/z.js"
></script>
Aucun paquet npm n'est requis. Le script suit automatiquement les pages vues et fournit la fonction globale window.zenovay pour le suivi personnalisé.
Configuration de base
Créer un hook useZenovay
Créez un hook personnalisé pour envelopper la fonction globale 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 };
}
Suivi automatique des pages
Avec React Router
Le script Zenovay suit automatiquement le chargement initial de la page. Pour les changements de route dans les SPA avec React Router, suivez les pages vues lors des changements de route :
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>
);
}
Les pages vues sont suivies automatiquement lors des changements de route.
Événements personnalisés
Hook useZenovay
import { useZenovay } from './hooks/useZenovay';
function SignupButton() {
const { trackEvent } = useZenovay();
const handleSignup = () => {
// Suivre le clic sur l'inscription
trackEvent('signup_click', {
plan: 'pro',
source: 'pricing_page'
});
// Continuer avec la logique d'inscription
performSignup();
};
return (
<button onClick={handleSignup}>
Démarrer l'essai gratuit
</button>
);
}
Fonction de suivi d'événement
const { trackEvent } = useZenovay();
// Événement simple
trackEvent('button_click');
// Avec propriétés
trackEvent('purchase', {
product_id: 'SKU-001',
value: 99.99,
currency: 'USD'
});
// Avec valeur
trackEvent('download', { file: 'guide.pdf' });
Suivi des objectifs
Suivi de l'accomplissement d'un objectif
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>Merci pour votre commande !</div>;
}
Identification des utilisateurs
Identifier les utilisateurs
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;
}
Dans le flux d'authentification
async function handleLogin(credentials) {
const user = await login(credentials);
// Identifier après la connexion
if (window.zenovay) {
window.zenovay('identify', user.id, {
email: user.email
});
}
navigate('/dashboard');
}
Suivi des revenus
Suivre les revenus
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>Commande confirmée !</h1>
<p>Commande #{order.id}</p>
</div>
);
}
Composants de suivi d'événement
Bouton suivable
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>
);
}
// Utilisation
<TrackableButton
event="cta_click"
eventData={{ location: 'hero' }}
onClick={handleSignup}
>
Commencer
</TrackableButton>
Suivi au montage
import { useZenovay } from './hooks/useZenovay';
import { useEffect } from 'react';
function TrackOnMount({ event, eventData }) {
const { trackEvent } = useZenovay();
useEffect(() => {
trackEvent(event, eventData);
}, []);
return null;
}
// Utilisation
<TrackOnMount
event="pricing_viewed"
eventData={{ referrer: document.referrer }}
/>
Support de TypeScript
Types
// 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 {};
Hook typé
// 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 };
}
Rendu côté serveur
Éviter les problèmes SSR
La fonction window.zenovay n'est disponible que dans le navigateur. Vérifiez toujours avant utilisation :
import { useEffect, useState } from 'react';
function ZenovayWrapper({ children }) {
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
}, []);
// Suivre seulement après le montage du composant (côté client)
if (!mounted) {
return children;
}
return children;
}
Tests
Simuler le hook
// 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
}));
Exemple de test
import { render, fireEvent, screen } from '@testing-library/react';
import { mockZenovay } from './test-utils';
import SignupButton from './SignupButton';
test('suit le clic d\'inscription', () => {
render(<SignupButton />);
fireEvent.click(screen.getByText('Démarrer l\'essai gratuit'));
expect(mockZenovay.trackEvent).toHaveBeenCalledWith('signup_click', expect.any(Object));
});
Modèles courants
Suivi du commerce électronique
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}>Ajouter au panier</button>
</div>
);
}
Suivi des formulaires
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}>
{/* champs du formulaire */}
</form>
);
}
Dépannage
Les événements ne sont pas suivis
Vérifiez :
- Que la balise de script se trouve dans votre index.html
- Que le code de suivi est correct
- Qu'il n'est pas bloqué par un bloqueur de publicités
- La console pour les erreurs
Pages vues manquantes
Vérifiez :
- Que le composant PageTracker est monté
- Que React Router est configuré correctement
- Que les routes sont rendues à l'intérieur du routeur
Suivi en double
Évitez :
- Plusieurs balises de script
- Suivi manuel + automatique
- StrictMode causant des effets doubles