API Données en temps réel
Accédez aux comptages de visiteurs en direct et aux données d'analyse en temps réel via des points de terminaison JSON publics. Ces points de terminaison sont conçus pour afficher des statistiques en direct sur votre site Web et ne nécessitent aucune authentification.
Vue d'ensemble
Les points de terminaison en temps réel offrent :
- Accès instantané - Aucune authentification requise
- Mises à jour en direct - Les données s'actualisent toutes les 5 à 30 secondes
- Faible latence - Servi depuis le réseau périphérique global de Cloudflare
- CORS activé - Sûr à appeler directement depuis les navigateurs
URL de base
Tous les points de terminaison en temps réel sont disponibles à :
https://api.zenovay.com/e
Comptage des visiteurs en direct
Obtenez le nombre actuel de visiteurs sur votre site Web :
/e/live/:trackingCodeObtenir le comptage des visiteurs en direct
curl -X GET 'https://api.zenovay.com/e/live/ZV_XXXXXXXXXXX'{
"liveCount": 42,
"timestamp": "2025-01-20T14:30:00Z"
}Champs de réponse :
| Champ | Type | Description |
|---|---|---|
liveCount | nombre | Visiteurs actuellement en ligne (actifs au cours des 5 dernières minutes) |
timestamp | chaîne | Timestamp ISO 8601 des données |
Analyse en temps réel
Obtenez une analyse en temps réel complète incluant les visiteurs, les vues de page et les données géographiques :
/e/realtime/:websiteIdObtenir les données d'analyse en temps réel
curl -X GET 'https://api.zenovay.com/e/realtime/ws_abc123'{
"visitors": {
"current": 42,
"today": 1234,
"change": 12.5
},
"pageViews": {
"current": 156,
"today": 4567,
"change": 8.3
},
"countries": [
{ "code": "US", "name": "United States", "count": 18 },
{ "code": "GB", "name": "United Kingdom", "count": 8 },
{ "code": "DE", "name": "Germany", "count": 6 }
],
"topPages": [
{ "path": "/", "visitors": 15 },
{ "path": "/pricing", "visitors": 8 },
{ "path": "/features", "visitors": 5 }
],
"timestamp": "2025-01-20T14:30:00Z"
}Champs de réponse :
| Champ | Type | Description |
|---|---|---|
visitors.current | nombre | Visiteurs en ligne maintenant |
visitors.today | nombre | Total des visiteurs uniques aujourd'hui |
visitors.change | nombre | Pourcentage de changement par rapport à hier |
pageViews.current | nombre | Vues de page au cours des 5 dernières minutes |
pageViews.today | nombre | Total des vues de page aujourd'hui |
countries | tableau | Pays principaux par visiteurs actuels |
topPages | tableau | Pages principales par visiteurs actuels |
Statistiques des visiteurs
Obtenez des statistiques détaillées des visiteurs incluant le taux de rebond et la durée de la session :
/e/stats/:trackingCodeObtenir les statistiques des visiteurs
curl -X GET 'https://api.zenovay.com/e/stats/ZV_XXXXXXXXXXX'{
"visitors": {
"live": 42,
"today": 1234,
"week": 8765,
"month": 34521
},
"bounceRate": 0.42,
"avgSessionDuration": 185,
"pagesPerSession": 2.9,
"newVisitorRate": 0.65,
"returningVisitorRate": 0.35,
"timestamp": "2025-01-20T14:30:00Z"
}Champs de réponse :
| Champ | Type | Description |
|---|---|---|
visitors.live | nombre | Visiteurs actuellement en ligne |
visitors.today | nombre | Visiteurs uniques aujourd'hui |
visitors.week | nombre | Visiteurs uniques cette semaine |
visitors.month | nombre | Visiteurs uniques ce mois |
bounceRate | nombre | Taux de rebond (0-1) |
avgSessionDuration | nombre | Durée moyenne de la session en secondes |
pagesPerSession | nombre | Moyenne de pages par session |
newVisitorRate | nombre | Pourcentage de nouveaux visiteurs |
returningVisitorRate | nombre | Pourcentage de visiteurs récurrents |
Statut du site Web
Vérifiez si le suivi est actif pour un site Web :
/e/:trackingCode/statusVérifier le statut du suivi
curl -X GET 'https://api.zenovay.com/e/ZV_XXXXXXXXXXX/status'{
"active": true,
"tracking_code": "ZV_XXXXXXXXXXX",
"domain": "example.com",
"last_event": "2025-01-20T14:29:55Z"
}Intégration JavaScript
Compteur de visiteurs en direct basique
Afficher le comptage des visiteurs en direct sur votre site Web :
class LiveVisitorCounter {
constructor(trackingCode, elementId) {
this.trackingCode = trackingCode;
this.element = document.getElementById(elementId);
this.intervalId = null;
}
async fetchCount() {
try {
const response = await fetch(
`https://api.zenovay.com/e/live/${this.trackingCode}`
);
const data = await response.json();
this.updateDisplay(data.liveCount);
} catch (error) {
console.error('Failed to fetch visitor count:', error);
}
}
updateDisplay(count) {
if (this.element) {
this.element.textContent = count.toLocaleString();
this.element.classList.add('updated');
setTimeout(() => this.element.classList.remove('updated'), 300);
}
}
start(intervalMs = 30000) {
this.fetchCount();
this.intervalId = setInterval(() => this.fetchCount(), intervalMs);
}
stop() {
if (this.intervalId) {
clearInterval(this.intervalId);
}
}
}
// Usage
const counter = new LiveVisitorCounter('ZV_XXXXXXXXXXX', 'visitor-count');
counter.start();Tableau de bord en temps réel
Créer un mini tableau de bord d'analyse :
async function updateDashboard(websiteId) {
try {
const response = await fetch(
`https://api.zenovay.com/e/realtime/${websiteId}`
);
const data = await response.json();
// Update visitor counts
document.getElementById('live-visitors').textContent = data.visitors.current;
document.getElementById('today-visitors').textContent = data.visitors.today.toLocaleString();
// Update pageviews
document.getElementById('live-pageviews').textContent = data.pageViews.current;
// Update top countries
const countriesList = document.getElementById('top-countries');
countriesList.innerHTML = data.countries
.slice(0, 5)
.map(c => `<li>${c.name}: ${c.count}</li>`)
.join('');
// Update top pages
const pagesList = document.getElementById('top-pages');
pagesList.innerHTML = data.topPages
.slice(0, 5)
.map(p => `<li>${p.path}: ${p.visitors}</li>`)
.join('');
} catch (error) {
console.error('Dashboard update failed:', error);
}
}
// Update every 30 seconds
setInterval(() => updateDashboard('ws_abc123'), 30000);
updateDashboard('ws_abc123');Hook React
Hook React personnalisé pour les données en temps réel :
import { useState, useEffect, useCallback } from 'react';
interface RealtimeData {
visitors: {
current: number;
today: number;
change: number;
};
pageViews: {
current: number;
today: number;
change: number;
};
countries: Array<{ code: string; name: string; count: number }>;
topPages: Array<{ path: string; visitors: number }>;
timestamp: string;
}
function useRealtimeAnalytics(websiteId: string, refreshInterval = 30000) {
const [data, setData] = useState<RealtimeData | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
const fetchData = useCallback(async () => {
try {
const response = await fetch(
`https://api.zenovay.com/e/realtime/${websiteId}`
);
if (!response.ok) throw new Error('Failed to fetch');
const json = await response.json();
setData(json);
setError(null);
} catch (err) {
setError(err instanceof Error ? err : new Error('Unknown error'));
} finally {
setLoading(false);
}
}, [websiteId]);
useEffect(() => {
fetchData();
const interval = setInterval(fetchData, refreshInterval);
return () => clearInterval(interval);
}, [fetchData, refreshInterval]);
return { data, loading, error, refetch: fetchData };
}
// Usage in component
function AnalyticsDashboard({ websiteId }: { websiteId: string }) {
const { data, loading, error } = useRealtimeAnalytics(websiteId);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
if (!data) return null;
return (
<div className="dashboard">
<div className="stat">
<span className="label">Live Visitors</span>
<span className="value">{data.visitors.current}</span>
</div>
<div className="stat">
<span className="label">Today</span>
<span className="value">{data.visitors.today.toLocaleString()}</span>
</div>
</div>
);
}Composable Vue
Composable Vue 3 pour les données en temps réel :
import { ref, onMounted, onUnmounted } from 'vue';
interface RealtimeData {
visitors: { current: number; today: number; change: number };
pageViews: { current: number; today: number; change: number };
countries: Array<{ code: string; name: string; count: number }>;
topPages: Array<{ path: string; visitors: number }>;
}
export function useRealtimeAnalytics(websiteId: string, refreshInterval = 30000) {
const data = ref<RealtimeData | null>(null);
const loading = ref(true);
const error = ref<Error | null>(null);
let intervalId: number | null = null;
async function fetchData() {
try {
const response = await fetch(
`https://api.zenovay.com/e/realtime/${websiteId}`
);
if (!response.ok) throw new Error('Failed to fetch');
data.value = await response.json();
error.value = null;
} catch (err) {
error.value = err instanceof Error ? err : new Error('Unknown error');
} finally {
loading.value = false;
}
}
onMounted(() => {
fetchData();
intervalId = window.setInterval(fetchData, refreshInterval);
});
onUnmounted(() => {
if (intervalId) clearInterval(intervalId);
});
return { data, loading, error, refetch: fetchData };
}Limites de débit
Les points de terminaison en temps réel ont les limites de débit suivantes :
| Point de terminaison | Limite de débit | Cache TTL |
|---|---|---|
/e/live/:trackingCode | 1000 req/min | 5 secondes |
/e/realtime/:websiteId | 500 req/min | 10 secondes |
/e/stats/:trackingCode | 500 req/min | 30 secondes |
/e/:trackingCode/status | 100 req/min | 60 secondes |
Les données sont mises en cache à la périphérie. Plusieurs demandes dans le TTL du cache recevront les mêmes données, ce qui les rend sûres pour interroger fréquemment depuis du code côté client.
Configuration CORS
Tous les points de terminaison en temps réel supportent CORS et peuvent être appelés directement depuis les navigateurs :
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, OPTIONS
Access-Control-Allow-Headers: Content-TypeGestion des erreurs
async function fetchWithRetry(url, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url);
if (response.status === 429) {
// Rate limited - wait and retry
const retryAfter = response.headers.get('Retry-After') || '60';
await new Promise(r => setTimeout(r, parseInt(retryAfter) * 1000));
continue;
}
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return await response.json();
} catch (error) {
if (i === maxRetries - 1) throw error;
// Exponential backoff
await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000));
}
}
}
// Usage
try {
const data = await fetchWithRetry('https://api.zenovay.com/e/live/ZV_XXXXXXXXXXX');
console.log('Live visitors:', data.liveCount);
} catch (error) {
console.error('Failed after retries:', error);
}Meilleures pratiques
- Mettre en cache localement - Stocker les données en mémoire pour éviter les demandes inutiles lors des mises à jour rapides de l'interface utilisateur
- Limiter le débit des mises à jour - Ne pas déclencher les mises à jour de l'interface utilisateur plus vite que le TTL du cache
- Gérer le mode hors ligne - Afficher les anciennes données avec un timestamp lorsque le réseau est indisponible
- Animer les changements - Les transitions fluides lorsque les comptages changent rendent l'interface utilisateur plus réactive
- Afficher les états de chargement - Afficher les chargeurs squelettes lors de la récupération initiale
Étapes suivantes
- Widgets - Widgets intégrables pré-construits
- API externe - API complète avec authentification
- Événements personnalisés - Suivre les actions utilisateur personnalisées