Apparence
API Cabin Analytics
Cabin propose une API en lecture seule pour accéder à vos données. Les réponses sont agrégées (exactement comme les données sont stockées et affichées dans le tableau de bord) et renvoyées au format JSON.
Avec l'offre Free, utilisez plutôt l'accès IA/MCP. Il est inclus dans toutes les offres et répond aux mêmes questions en langage courant.
Clé API
Pour utiliser l'API, vous devez créer une clé API dans la section API keys (clés API) des paramètres de votre compte.
Chaque clé est en lecture seule. Elle peut donner accès à tous vos domaines ou seulement à certains.
Les clés API ne servent pas pour l'accès IA/MCP. Les agents se connectent avec OAuth et n'ont besoin d'aucune clé.

- Sélectionnez 'New Key'
- Donnez un nom à votre clé
- Choisissez les domaines auxquels elle donne accès
- Cliquez sur 'Create'
Authentification
Pour authentifier vos requêtes, ajoutez votre clé API dans l'en-tête x-api-key.
Exemple de requête :
bash
curl -X GET "https://api.withcabin.com/v1/analytics?domain=example.com&date_from=2025-01-01&date_to=2025-02-01&scope=core&limit_lists=20" -H "x-api-key: YOUR_API_KEY"Points de terminaison
L'API est disponible à l'adresse https://api.withcabin.com/v1/{endpoint}.
/analytics
Ce point de terminaison renvoie des données agrégées sur le trafic de votre site entre deux dates, y compris les pages vues et les rebonds agrégés jour par jour.
Paramètres de requête
domain
string requiredLe nom de domaine dont vous voulez récupérer les statistiques.
date_from
string requiredLa date de début (format : YYYY-MM-DD).
date_to
string requiredLa date de fin (format : YYYY-MM-DD).
scope
string optionalPar défaut : core. Le périmètre des données. Peut contenir n'importe quelle combinaison de core,pages,referrals,events.
limit_lists
number optionalPar défaut : 50. Le nombre d'éléments renvoyés dans chaque liste. Les valeurs supérieures à 250 ne sont pas refusées, mais les réponses deviennent lourdes et lentes : considérez 250 comme le plafond en pratique.
Ce paramètre s'applique à countries, languages, browsers, operating_systems, devices, screen_sizes, pages et referrals.
Les pourcentages de la réponse restent calculés sur l'ensemble des données, quelle que soit la limite.
À propos de scope
Les scopes pages et referrals ajoutent des données pour chaque chemin de votre domaine (voir l'exemple de réponse). Ils sont un peu plus lourds, donc nous vous conseillons de vous en tenir à core si vous n'avez pas besoin de ces données supplémentaires.
Les données d'émissions liées à l'énergie ne sont disponibles qu'avec le scope pages.
La profondeur de défilement arrive aussi avec pages, à deux endroits : un objet scroll_depth sur chaque page, et un scroll_depth pour tout le site au premier niveau. Celui du site est additionné sur toutes les pages avant l'application de limit_lists, il ne correspond donc pas à la somme des pages qui vous ont été renvoyées.
events renvoie vos événements personnalisés, chacun avec la répartition des pages sur lesquelles il s'est déclenché. Il lit les mêmes données sous-jacentes que pages, donc demander pages,events ensemble ne coûte pas plus cher que demander l'un des deux.
La répartition des agents IA est renvoyée avec core, sans requête supplémentaire. Ces visites sont comptées à part de summary.page_views et ne sont jamais facturées : ai_agents ne s'ajoute donc pas à votre total de pages vues, et chaque percentage est une part du trafic des agents, pas de tout le trafic.
Exemple de réponse
json
{
query: {
domain: "example.com",
date_from: "2025-01-01",
date_to: "2025-02-01",
scope: "core,pages,referrals",
limit_lists: 10
},
/* Disponible avec scope : core */
summary: {
page_views: 1959,
unique_visitors: 1165,
bounces: 817,
bounce_rate: 0.29871244635193134
},
daily_data: [
{
timestamp: 1735689600000,
page_views: 22,
unique_visitors: 16,
bounces: 12,
bounce_rate: 0.75
},
{
timestamp: 1735776000000,
page_views: 29,
unique_visitors: 26,
bounces: 23,
bounce_rate: 0.88
},
{
timestamp: 1735862400000,
page_views: 24,
unique_visitors: 16,
bounces: 13,
bounce_rate: 0.81
}
],
screen_sizes: {
small: 38,
medium: 372,
large: 463
},
devices: {
desktop: 873,
mobile: 288,
tablet: 4,
smart_tv: 0,
console: 0,
wearable: 0
},
browsers: [
{
name: "Chrome",
value: 718
},
{
name: "WebKit",
value: 117
},
{
name: "Firefox",
value: 85
}
],
operating_systems: [
{
name: "Windows",
value: 467
},
{
name: "Mac OS",
value: 365
},
{
name: "iOS",
value: 223
}
// ...
],
countries: [
{
code: "GB",
value: 362
},
{
code: "US",
value: 263
},
{
code: "JP",
value: 41
}
// ...
],
languages: [
{
code: "en",
value: 887
},
{
code: "ja",
value: 37
},
{
code: "ru",
value: 32
}
// ...
],
traffic_sources: {
email: 0,
search: 217,
social: 151,
unknown: 789
},
ai_agents: [
{
name: "ChatGPT",
hits: 34,
percentage: 0.9444
},
{
name: "Claude",
hits: 2,
percentage: 0.0556
}
],
/* Disponible avec scope : pages */
energy: {
page_count: 22,
green_hosting: {
url: "nicmulvaney.com",
hosted_by: "Cloudflare",
hosted_by_website: "https://www.cloudflare.com",
partner: null,
green: true,
hosted_by_id: 779,
modified: "2025-03-17T20:24:22",
supporting_documents: [
{
id: 18,
title: "Blog post - The Climate and Cloudflare",
link: "https://blog.cloudflare.com/the-climate-and-cloudflare/"
},
{
id: 1264,
title: "Cloudflare 2023 Emissions Inventory",
link: "https://s3.nl-ams.scw.cloud/tgwf-web-app-live/uploads/Cloudflare_2023_Emissions_Inventory.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=SCWT1WBAW6NZ5SW5GYJ8%2F20250317%2Fnl-ams%2Fs3%2Faws4_request&X-Amz-Date=20250317T202736Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=0d3b2ffd9a885dbc41193e0e72bdee9c4ee8cf37671af3d092453578cc5a179c"
}
]
},
average_time_spent_ms: 122892,
average_co2_grams: 0.0708,
total_co2_grams: 138.65,
total_distance_km: 0.55,
total_kettles: 4,
transferred_bytes: 1145572683,
total_bytes: 22060595,
duration_total_ms: 240746383,
duration_count: 1272
},
pages: [
{
path: "/page/1",
page_views: 271671,
unique_visitors: 243070,
average_duration_seconds: 123,
total_bytes: 8.2,
co2_grams: 538,
page_views_percentage: 0.12,
scroll_depth: {
average_percentage: 46.2,
measured_visits: 1840,
reached_at_least: [
{ percent: 0, visitors_percentage: 100 },
{ percent: 10, visitors_percentage: 88.37 },
{ percent: 20, visitors_percentage: 79.08 },
{ percent: 30, visitors_percentage: 73.75 },
{ percent: 40, visitors_percentage: 69.18 },
{ percent: 50, visitors_percentage: 65 },
{ percent: 60, visitors_percentage: 57.83 },
{ percent: 70, visitors_percentage: 52.61 },
{ percent: 80, visitors_percentage: 46.63 },
{ percent: 90, visitors_percentage: 38.86 },
{ percent: 100, visitors_percentage: 22.01 }
]
}
},
{
path: "/page/2",
page_views: 167111,
unique_visitors: 150073,
average_duration_seconds: 147,
total_bytes: 4.82,
co2_grams: 222.6,
page_views_percentage: 0.08
},
{
path: "/page/3",
page_views: 106361,
unique_visitors: 93743,
average_duration_seconds: 97,
total_bytes: 4.82,
co2_grams: 133.4,
page_views_percentage: 0.05
},
// ...
],
// Pour tout le site, additionné sur toutes les pages, pas seulement celles de `pages`.
scroll_depth: {
average_percentage: 41.8,
measured_visits: 94211,
reached_at_least: [
{ percent: 0, visitors_percentage: 100 },
// ... une ligne par décile ...
{ percent: 100, visitors_percentage: 18.4 }
]
},
/* Disponible avec scope : referrals */
referrals: [
{
source: "Google",
page_views: 259,
unique_visitors: 197,
has_utm: false,
page_views_percentage: 0.39
},
{
source: "LinkedIn",
page_views: 252,
unique_visitors: 136,
has_utm: false,
page_views_percentage: 0.38
},
{
source: "com.linkedin.android",
page_views: 34,
unique_visitors: 18,
has_utm: false,
page_views_percentage: 0.05
},
// ...
],
/* Disponible avec scope : events */
events: [
{
name: "signup button (header)",
count: 14,
percentage: 0.1129,
pages: [
{
path: "/",
count: 13,
percentage: 0.9286
},
{
path: "/pricing",
count: 1,
percentage: 0.0714
}
]
},
// ...
]
}Lire scroll_depth
average_percentage est la moyenne du point le plus bas atteint, et measured_visits le nombre de visites sur lesquelles cette moyenne est calculée. C'est toujours un échantillon : la mesure est envoyée au moment où le visiteur quitte la page, et certains navigateurs n'en laissent pas le temps au script. measured_visits est donc inférieur à page_views, souvent de beaucoup.
reached_at_least est cumulatif. Chaque ligne donne la part des visites mesurées qui sont allées au moins jusque-là dans la page. percent: 0 vaut donc toujours 100, et les lignes ne font ensuite que baisser. L'écart entre deux lignes montre où les gens se sont arrêtés.
js
// « quelle part a lu au-delà de la moitié ? »
const half = page.scroll_depth.reached_at_least.find(r => r.percent === 50)
console.log(half.visitors_percentage) // 65La profondeur est mesurée par rapport au bloc de contenu de la page, pas au document entier : un long pied de page ne fait donc pas passer une lecture complète pour 75 %. Atteindre 100 % signifie que le bas du contenu s'est affiché à l'écran, pas qu'il a été lu. Consultez la page profondeur de défilement pour savoir comment le bloc de contenu est repéré et comment le baliser vous-même.
Un scroll_depth absent signifie « non mesuré », jamais zéro. Les pages plus courtes que l'écran n'ont rien à faire défiler et sont exclues, tout comme les pages dont toutes les visites sont antérieures à la fonctionnalité. Vérifiez la présence de la clé au lieu de la lire directement.
Limites selon l'offre
Votre offre détermine ce qui est renvoyé :
- Conservation.
date_fromest ramené à la période de conservation de votre offre (12 mois avec Plus, illimitée avec Scale). Si vous demandez des données plus anciennes, vous recevez les plus anciennes dont vous disposez encore, pas une erreur. - Données énergétiques. Le bloc
energyet les chiffres carbone par page nécessitent le bilan carbone, disponible avec Plus et Scale. - Événements personnalisés. Le bloc
eventsest disponible avec Plus et Scale. - Agents IA. Le bloc
ai_agentsest disponible avec Scale. - Profondeur de défilement. Disponible avec toutes les offres, Free compris.
Un bloc auquel votre offre ne donne pas droit est absent de la réponse, pas renvoyé vide. Vérifiez donc la présence de la clé avant de la lire.
Usage raisonnable
Merci de garder un rythme de requêtes raisonnable, environ 20 par minute. Les données sont agrégées chaque jour, donc interroger l'API plus souvent ne vous apprendra rien de nouveau. Si vous avez besoin d'un rythme plus élevé, contactez-nous.
