Aspetto
API di Cabin Analytics
Cabin offre un'API in sola lettura per accedere ai tuoi dati. Le risposte con le statistiche sono aggregate (proprio come vengono salvate e mostrate nella dashboard) e sono disponibili in formato JSON.
Con il piano Free, usa invece l'accesso IA/MCP. È incluso in tutti i piani e può rispondere alle stesse domande in linguaggio naturale.
Chiave API
Per usare l'API devi creare una chiave API nella sezione API keys settings del tuo account.
Ogni chiave è in sola lettura e può valere per tutti i tuoi domini o solo per alcuni.
Le chiavi API non servono per l'accesso IA/MCP. Gli agenti accedono con OAuth e non hanno bisogno di nessuna chiave.

- Seleziona 'New Key'
- Dai un nome alla chiave
- Seleziona i domini a cui vuoi dare accesso
- Clicca su 'Create'
Autenticazione
Per autenticare le richieste, includi la tua chiave API nell'header x-api-key.
Esempio di richiesta:
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"Endpoint
L'API è disponibile all'indirizzo https://api.withcabin.com/v1/{endpoint}.
/analytics
Questo endpoint restituisce dati aggregati sul traffico del tuo sito tra due date, comprese le visualizzazioni di pagina e i rimbalzi aggregati giorno per giorno.
Parametri della query
domain
string requiredIl nome del dominio di cui vuoi ottenere le statistiche.
date_from
string requiredLa data di inizio (formato: YYYY-MM-DD).
date_to
string requiredLa data di fine (formato: YYYY-MM-DD).
scope
string optionalPredefinito: core. L'ambito dei dati. Può contenere qualsiasi combinazione di core,pages,referrals,events.
limit_lists
number optionalPredefinito: 50. Il numero di elementi da restituire in ogni elenco. I valori sopra 250 non vengono rifiutati, ma le risposte diventano pesanti e lente, quindi considera 250 come tetto pratico.
Riguarda countries, languages, browsers, operating_systems, devices, screen_sizes, pages e referrals.
Le percentuali nella risposta restano calcolate sull'intero insieme di dati, qualunque sia il limite.
Informazioni su scope
Gli scope pages e referrals aggiungono dati sui singoli percorsi del tuo dominio: vedi l'esempio di risposta. Sono un po' più pesanti, quindi ti consigliamo di usare core a meno che non ti servano i dati aggiuntivi.
I dati sulle emissioni energetiche sono disponibili solo con lo scope pages.
Anche la profondità di scorrimento arriva con pages, in due punti: un oggetto scroll_depth su ogni pagina e uno scroll_depth per l'intero sito al primo livello. Quello per l'intero sito è sommato su tutte le pagine prima che venga applicato limit_lists, quindi non corrisponde alla somma delle pagine che ricevi.
events restituisce i tuoi eventi personalizzati, ognuno con la suddivisione delle pagine in cui è stato generato. Legge gli stessi dati di base di pages, quindi chiedere pages,events insieme non costa più che chiederne uno solo.
La suddivisione degli agenti IA arriva con core, senza richieste aggiuntive. Questi hit sono contati a parte rispetto a summary.page_views e non vengono mai fatturati, quindi ai_agents non si somma al totale delle visualizzazioni di pagina, e ogni percentage è una quota del traffico degli agenti, non di tutto il traffico.
Esempio di risposta
json
{
query: {
domain: "example.com",
date_from: "2025-01-01",
date_to: "2025-02-01",
scope: "core,pages,referrals",
limit_lists: 10
},
/* Available with 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
}
],
/* Available with 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
},
// ...
],
// Per tutto il sito, sommato su tutte le pagine, non solo su quelle in `pages`.
scroll_depth: {
average_percentage: 41.8,
measured_visits: 94211,
reached_at_least: [
{ percent: 0, visitors_percentage: 100 },
// ... una riga per decile ...
{ percent: 100, visitors_percentage: 18.4 }
]
},
/* Available with 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
},
// ...
],
/* Available with 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
}
]
},
// ...
]
}Leggere scroll_depth
average_percentage è la media del punto più profondo raggiunto e measured_visits indica da quante visite è calcolata quella media. È sempre un campione: il dato viene inviato quando il visitatore lascia la pagina e alcuni browser non danno allo script il tempo di farlo, quindi measured_visits è più basso di page_views, spesso di molto.
reached_at_least è cumulativo. Ogni riga è la quota di visite misurate che è arrivata almeno fino a quel punto della pagina, quindi percent: 0 vale sempre 100 e da lì le righe possono solo scendere. Il calo tra due righe indica dove le persone si sono fermate.
js
// "che quota ha letto oltre la metà?"
const half = page.scroll_depth.reached_at_least.find(r => r.percent === 50)
console.log(half.visitors_percentage) // 65La profondità si misura rispetto al blocco dei contenuti della pagina, non all'intero documento, così un footer lungo non fa sembrare una lettura completa un 75%. Raggiungere il 100% significa che la fine dei contenuti è apparsa sullo schermo, non che sia stata letta. Vedi profondità di scorrimento per sapere come viene individuato il blocco dei contenuti e come contrassegnarlo tu stesso.
Se scroll_depth manca significa "non misurato", mai zero. Le pagine più corte dello schermo non hanno niente da scorrere e vengono escluse, così come le pagine le cui visite sono tutte precedenti alla funzione. Controlla che la chiave esista invece di leggerla direttamente.
Limiti del piano
Il tuo piano determina cosa ricevi:
- Conservazione.
date_fromviene limitato al periodo di conservazione del tuo piano (12 mesi con Plus, senza limiti con Scale), quindi se chiedi dati più vecchi ricevi i dati più vecchi che hai ancora, non un errore. - Dati sull'energia. Il blocco
energye i dati di CO₂ per pagina richiedono i report sulla CO₂, disponibili con Plus e Scale. - Eventi personalizzati. Il blocco
eventsè disponibile con Plus e Scale. - Agenti IA. Il blocco
ai_agentsè disponibile con Scale. - Profondità di scorrimento. Con tutti i piani, Free compreso.
Un blocco a cui non hai diritto viene omesso dalla risposta, non restituito vuoto, quindi controlla che la chiave esista prima di leggerla.
Uso corretto
Mantieni le richieste a un ritmo ragionevole, circa 20 al minuto. I dati vengono aggregati ogni giorno, quindi interrogare l'API più spesso non ti mostrerà niente di nuovo. Se ti serve un ritmo più alto, scrivici.
