Integre el análisis de Zenovay en su aplicación React con rastreo automático de páginas, eventos personalizados y un hook personalizado para la función global window.zenovay.
Instalación
Agregue el script de rastreo de Zenovay a su index.html:
<script
defer
data-tracking-code="YOUR_TRACKING_CODE"
src="https://api.zenovay.com/z.js"
></script>
No se necesita ningún paquete npm. El script rastrea automáticamente las vistas de página y proporciona la función global window.zenovay para el rastreo personalizado.
Configuración básica
Crear un hook useZenovay
Cree un hook personalizado para envolver la función global 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 };
}
Rastreo automático de páginas
Con React Router
El script de Zenovay rastrea automáticamente la carga inicial de la página. Para los cambios de ruta en SPA con React Router, registre las vistas de página en cada cambio de ruta:
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>
);
}
Las vistas de página se registran automáticamente en los cambios de ruta.
Eventos personalizados
Hook useZenovay
import { useZenovay } from './hooks/useZenovay';
function SignupButton() {
const { trackEvent } = useZenovay();
const handleSignup = () => {
// Registrar el clic en registro
trackEvent('signup_click', {
plan: 'pro',
source: 'pricing_page'
});
// Continuar con la lógica de registro
performSignup();
};
return (
<button onClick={handleSignup}>
Comenzar prueba gratuita
</button>
);
}
Función de registro de eventos
const { trackEvent } = useZenovay();
// Evento simple
trackEvent('button_click');
// Con propiedades
trackEvent('purchase', {
product_id: 'SKU-001',
value: 99.99,
currency: 'USD'
});
// Con valor
trackEvent('download', { file: 'guide.pdf' });
Rastreo de metas
Registrar la completación de una meta
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>¡Gracias por su pedido!</div>;
}
Identificación de usuarios
Identificar usuarios
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;
}
En el flujo de autenticación
async function handleLogin(credentials) {
const user = await login(credentials);
// Identificar después del inicio de sesión
if (window.zenovay) {
window.zenovay('identify', user.id, {
email: user.email
});
}
navigate('/dashboard');
}
Rastreo de ingresos
Registrar ingresos
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>¡Pedido confirmado!</h1>
<p>Pedido #{order.id}</p>
</div>
);
}
Componentes de rastreo de eventos
Botón rastreable
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>
);
}
// Uso
<TrackableButton
event="cta_click"
eventData={{ location: 'hero' }}
onClick={handleSignup}
>
Comenzar
</TrackableButton>
Rastrear al montar
import { useZenovay } from './hooks/useZenovay';
import { useEffect } from 'react';
function TrackOnMount({ event, eventData }) {
const { trackEvent } = useZenovay();
useEffect(() => {
trackEvent(event, eventData);
}, []);
return null;
}
// Uso
<TrackOnMount
event="pricing_viewed"
eventData={{ referrer: document.referrer }}
/>
Soporte de TypeScript
Tipos
// 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 tipado
// 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 };
}
Renderizado del lado del servidor
Prevenir problemas de SSR
La función window.zenovay solo está disponible en el navegador. Siempre verifique antes de usarla:
import { useEffect, useState } from 'react';
function ZenovayWrapper({ children }) {
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
}, []);
// Solo registrar después de que el componente se monte (lado del cliente)
if (!mounted) {
return children;
}
return children;
}
Pruebas
Simular el 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
}));
Ejemplo de prueba
import { render, fireEvent, screen } from '@testing-library/react';
import { mockZenovay } from './test-utils';
import SignupButton from './SignupButton';
test('registra el clic en registro', () => {
render(<SignupButton />);
fireEvent.click(screen.getByText('Comenzar prueba gratuita'));
expect(mockZenovay.trackEvent).toHaveBeenCalledWith('signup_click', expect.any(Object));
});
Patrones comunes
Rastreo de e-commerce
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}>Agregar al carrito</button>
</div>
);
}
Rastreo de formularios
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}>
{/* campos del formulario */}
</form>
);
}
Solución de problemas
Los eventos no se registran
Verifique:
- Que la etiqueta del script esté en su index.html
- Que el código de rastreo sea correcto
- Que no esté bloqueado por un bloqueador de anuncios
- La consola para ver errores
Faltan vistas de página
Verifique:
- Que el componente PageTracker esté montado
- Que React Router esté configurado correctamente
- Que las rutas se rendericen dentro del router
Rastreo duplicado
Evite:
- Múltiples etiquetas de script
- Rastreo manual + automático
- Efectos dobles causados por StrictMode