Darstellung
Cabin Analytics API
Cabin bietet eine API, über die Sie lesend auf Ihre Daten zugreifen. Die Analytics-Antworten sind aggregiert (genau so, wie die Daten auch im Dashboard gespeichert und angezeigt werden) und kommen im JSON-Format.
Im Free-Tarif nutzen Sie stattdessen den KI/MCP-Zugang. Er ist in jedem Tarif enthalten und beantwortet dieselben Fragen in Alltagssprache.
API-Schlüssel
Um die API zu nutzen, erstellen Sie in Ihrem Konto unter API keys settings einen API-Schlüssel.
Jeder Schlüssel ist schreibgeschützt. Sie können ihn für alle Ihre Domains freigeben oder auf einzelne Domains beschränken.
Für den KI/MCP-Zugang werden keine API-Schlüssel verwendet. Agenten melden sich stattdessen per OAuth an und brauchen überhaupt keinen Schlüssel.

- Wählen Sie 'New Key'
- Geben Sie Ihrem Schlüssel einen Namen
- Wählen Sie die Domains aus, auf die der Schlüssel zugreifen darf
- Klicken Sie auf 'Create'
Authentifizierung
Zur Authentifizierung senden Sie Ihren API-Schlüssel im Header x-api-key jeder Anfrage mit.
Beispielanfrage:
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"Endpunkte
Die API ist unter https://api.withcabin.com/v1/{endpoint} erreichbar.
/analytics
Dieser Endpunkt liefert aggregierte Daten zum Traffic Ihrer Website zwischen zwei Daten, einschließlich aggregierter Tageswerte für Seitenaufrufe und Absprünge.
Query-Parameter
domain
string requiredDer Domainname, für den Sie Analytics-Daten abrufen möchten.
date_from
string requiredDas Startdatum der Daten (Format: YYYY-MM-DD).
date_to
string requiredDas Enddatum der Daten (Format: YYYY-MM-DD).
scope
string optionalStandard: core. Der Umfang der Daten. Kann jede Kombination aus core,pages,referrals,events enthalten.
limit_lists
number optionalStandard: 50. Die Anzahl der Einträge, die in jeder Liste zurückgegeben werden. Werte über 250 werden nicht abgelehnt, aber die Antworten werden groß und langsam. Betrachten Sie 250 daher als praktische Obergrenze.
Das betrifft countries, languages, browsers, operating_systems, devices, screen_sizes, pages und referrals.
Die Prozentwerte in der Antwort beziehen sich unabhängig vom Limit immer auf den gesamten Datensatz.
Über scope
Die Scopes pages und referrals liefern zusätzliche Daten zu einzelnen Pfaden Ihrer Domain (siehe die Beispielantwort). Diese Abfragen sind etwas aufwendiger. Wir empfehlen daher core, solange Sie die zusätzlichen Daten nicht brauchen.
Daten zu Energie und Emissionen gibt es nur mit dem Scope pages.
Auch die Scrolltiefe kommt mit pages, und zwar an zwei Stellen: als Objekt scroll_depth bei jeder Seite und als seitenweites scroll_depth auf oberster Ebene. Der seitenweite Wert wird über alle Seiten summiert, bevor limit_lists greift. Er entspricht also nicht der Summe der Seiten, die Sie erhalten haben.
events liefert Ihre eigenen Events, jeweils aufgeschlüsselt nach den Seiten, auf denen sie ausgelöst wurden. Dafür werden dieselben Rohdaten gelesen wie für pages. Eine Abfrage von pages,events kostet also nicht mehr als eine der beiden allein.
Die Aufschlüsselung nach KI-Agenten kommt ohne zusätzliche Anfrage mit core. Diese Aufrufe werden getrennt von summary.page_views gezählt und nie abgerechnet. ai_agents fließt also nicht in Ihre Gesamtzahl der Seitenaufrufe ein, und jeder percentage-Wert ist ein Anteil am Agenten-Traffic, nicht am gesamten Traffic.
Beispielantwort
json
{
query: {
domain: "example.com",
date_from: "2025-01-01",
date_to: "2025-02-01",
scope: "core,pages,referrals",
limit_lists: 10
},
/* Verfügbar mit 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
}
],
/* Verfügbar mit 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
},
// ...
],
// Seitenweit, summiert über alle Seiten, nicht nur über die in `pages`.
scroll_depth: {
average_percentage: 41.8,
measured_visits: 94211,
reached_at_least: [
{ percent: 0, visitors_percentage: 100 },
// ... eine Zeile pro Dezil ...
{ percent: 100, visitors_percentage: 18.4 }
]
},
/* Verfügbar mit 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
},
// ...
],
/* Verfügbar mit 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
}
]
},
// ...
]
}scroll_depth lesen
average_percentage ist der Mittelwert der tiefsten erreichten Stelle, und measured_visits gibt an, aus wie vielen Besuchen dieser Mittelwert stammt. Es handelt sich immer um eine Stichprobe: Der Messwert wird gesendet, wenn der Besucher die Seite verlässt, und manche Browser geben dem Skript dazu keine Gelegenheit. Deshalb ist measured_visits kleiner als page_views, oft sogar deutlich.
reached_at_least ist kumulativ. Jede Zeile zeigt den Anteil der gemessenen Besuche, die mindestens so weit nach unten gekommen sind. percent: 0 ist also immer 100, und von dort aus fallen die Werte nur noch. Der Abstand zwischen zwei Zeilen zeigt, wo Leute aufgehört haben.
js
// "Welcher Anteil hat über die Hälfte hinaus gelesen?"
const half = page.scroll_depth.reached_at_least.find(r => r.percent === 50)
console.log(half.visitors_percentage) // 65Die Tiefe wird am Inhaltsblock der Seite gemessen, nicht am gesamten Dokument. Ein langer Footer lässt einen vollständig gelesenen Artikel also nicht wie 75 % aussehen. 100 % bedeutet, dass das Ende des Inhalts auf dem Bildschirm war, nicht dass er gelesen wurde. Unter Scrolltiefe erfahren Sie, wie der Inhaltsblock ermittelt wird und wie Sie ihn selbst markieren.
Fehlt scroll_depth, heißt das „nicht gemessen“, niemals null. Seiten, die kürzer als der Bildschirm sind, bieten nichts zum Scrollen und werden ausgelassen. Dasselbe gilt für Seiten, deren Besuche alle aus der Zeit vor dieser Funktion stammen. Prüfen Sie, ob der Schlüssel vorhanden ist, bevor Sie ihn auslesen.
Tariflimits
Folgende Tariflimits bestimmen, was zurückkommt:
- Aufbewahrung.
date_fromwird auf den Aufbewahrungszeitraum Ihres Tarifs begrenzt (12 Monate bei Plus, unbegrenzt bei Scale). Fragen Sie ältere Daten an, erhalten Sie die ältesten Daten, die noch vorhanden sind, und keinen Fehler. - Energiedaten. Der Block
energyund die CO₂-Werte pro Seite setzen das CO₂-Reporting voraus, das es bei Plus und Scale gibt. - Eigene Events. Der Block
eventsist bei Plus und Scale enthalten. - KI-Agenten. Der Block
ai_agentsist bei Scale enthalten. - Scrolltiefe. In jedem Tarif, auch bei Free.
Ein Block, der in Ihrem Tarif nicht enthalten ist, fehlt in der Antwort ganz, statt leer zurückzukommen. Prüfen Sie also, ob der Schlüssel vorhanden ist, bevor Sie ihn auslesen.
Faire Nutzung
Bitte halten Sie die Anfragerate in einem vernünftigen Rahmen, etwa 20 pro Minute. Die Daten werden täglich aggregiert, häufigeres Abfragen zeigt Ihnen also nichts Neues. Wenn Sie eine höhere Rate brauchen, schreiben Sie uns.
