# Cabin Analytics Documentation > Cabin is privacy-first, cookie-free web analytics. No cookies, no consent banner, a 2 KB script, carbon reporting and MCP access for AI agents. # Cabin Analytics Documentation Cabin is a privacy-first, carbon-conscious web analytics service. It's lightweight, compliant with all [privacy laws](https://docs.withcabin.com/privacy.md), and the ideal cookieless alternative to Google Analytics. - No cookies, so no consent banner - No data sharing and no ad networks - A 2 KB script that won't slow your site down - Compliant with GDPR, CCPA, and more Cabin comes in three plans, Free, Plus and Scale, and every one of them includes the full dashboard, [scroll depth](https://docs.withcabin.com/scroll-depth.md), [AI/MCP access](https://docs.withcabin.com/mcp.md), [public dashboards](https://docs.withcabin.com/sharing.md#public-dashboards) and [data export](https://docs.withcabin.com/export-options.md). See [plans and limits](https://docs.withcabin.com/plans.md) for what the paid plans add. This documentation is available in [English](https://docs.withcabin.com/index.md), [Français](https://docs.withcabin.com/fr.md), [Deutsch](https://docs.withcabin.com/de.md), [Nederlands](https://docs.withcabin.com/nl.md), [Italiano](https://docs.withcabin.com/it.md) and [日本語](https://docs.withcabin.com/ja.md). ## Privacy by Design Cabin is built from the ground up using **Privacy by Design** principles. We never store unique identifiers for your visitors, and our non-relational data structure makes it impossible to identify individuals based on their location, browser, OS, or language. We don't sell or share any data with third parties or ad networks. Your visitors' data remains private and useless to advertising platforms. ## Environmental Responsibility Cabin's tracking script is 2 KB compressed, a fraction of the size of Google Analytics' loader, and that loader then pulls in far more JavaScript behind it. Keeping Cabin that small is a constraint we defend, not a happy accident: you can check the number yourself in your browser's network tab. Beyond the script, the biggest lever on a hosted service's emissions is where its servers sit, because that decides which electricity grid they draw from. Cabin's ingest servers, the ones your visitors' browsers talk to, are placed with that in mind: - **Clean grids first.** Two of the three regions Cabin runs in draw from grids that are over 95% carbon-free. The third serves Asia-Pacific, where no clean grid exists, and is the least carbon-intensive option that still keeps latency low there. - **Close to visitors.** Each region takes the traffic nearest to it, so a beacon travels a short distance and the page view is recorded quickly, which matters on a fast bounce. - **Small, efficient machines.** Ingest is light work, so each region runs on a small server rather than a large one sitting mostly idle. That's cheaper and lower in energy. The same grid-intensity methodology sits behind [your site's carbon estimates](https://docs.withcabin.com/energy-and-carbon.md), which use The Green Web Foundation's CO2.js. ## Data Collection The Cabin script sends minimal data points, with additional information inferred from the user-agent and request headers. #### Sent by the script | Data point | When | | --- | --- | | Page URL | Every page view | | Referrer | First page view of a visit only | | Screen width | Every page view | | Page load time | Every page view | | Visit counts | Every page view | | Time on page | When the visitor leaves the page | | [Scroll depth](https://docs.withcabin.com/scroll-depth.md) | When the visitor leaves the page | | [Event name](https://docs.withcabin.com/events.md) | Only when your site triggers an event | The referrer's query string is stripped before it leaves the browser, so nothing sensitive in a referring URL reaches us. #### Inferred from the request | Data point | Example | | ------------ | ------------- | | Timestamp | 1627589208201 | | Source | social | | Country | GB | | Browser | chrome | | Device | mobile | | OS | iOS | | Language | en | | Bounce | false | | utm_source | instagram | | utm_campaign | summer_sale | | utm_medium | paid_social | ## Unique Visitors Without Cookies > How does Cabin determine unique visitors without storing identifiers? Cabin counts unique visitors without identifiers, IP addresses or fingerprinting, using a property of HTTP caching that browsers already have: When a visitor interacts with Cabin, the request is cached in their browser like any standard web resource. We set a `last-modified` header in the response to the start of the current day. On subsequent requests, the browser automatically sends this header back to check if the request is still valid. Cabin then increments the `last-modified` time by one second with each visit. By calculating the difference between the `last-modified` time and the day's start, we can determine the number of visits without storing any personal data. The first request indicates a unique visit, while subsequent requests help us track metrics like [bounce rate](https://docs.withcabin.com/bounce-rate.md). You can read more about this on our blog: [How Cabin measures unique visitors without cookies](https://withcabin.com/blog/how-cabin-measures-unique-visitors-without-cookies). ## Visitor Geolocation Every web request includes an IP address. Cabin converts this address **in transit** (within server memory only) to an [ISO country code](https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes) with no further location detail. We store only the country code. The IP address is immediately discarded and never logged. For where that happens and where your data is stored, see the [privacy policy](https://withcabin.com/privacy). --- # Installing Cabin Start by adding your domain on the [Domains](https://withcabin.com/settings/domains) page. Then follow the instructions below to add Cabin to your site. The script is the same everywhere: one line, 2 KB, no configuration. Once it's live, visits show up in your dashboard within a few seconds. It's also open source. You can read exactly what runs on your visitors' browsers at [github.com/withcabin/hello.js](https://github.com/withcabin/hello.js), and the built file in that repository is byte-for-byte the one the CDN serves, so there's nothing to take on trust. ## Basic Installation Place the following code before your closing `` tag. ```html ``` ## WordPress 1. Install the [Insert Headers and Footers](https://wordpress.org/plugins/insert-headers-and-footers/#installation) plugin. 2. Go to **Settings** > **Insert Headers and Footers** menu. 3. Paste the code below into the **Footer scripts**: ```html ``` 4. Click **Save**. ## Shopify > [!NOTE] > This requires access to your Shopify theme code. 1. From your Shopify admin, go to **Online Store** > **Themes**. 2. Find the theme you want to edit and click **Actions** > **Edit code**. 3. In the Layout directory, click on `theme.liquid`. 4. Find the closing `` tag and paste the following code just before it: ```html ``` 5. Click **Save**. ## WooCommerce 1. Install and activate the [Code Snippets](https://wordpress.org/plugins/code-snippets/) plugin. 2. Go to **Snippets** > **Add New**. 3. Give your snippet a title like "Cabin Analytics". 4. Paste the following code: ```php function add_cabin_analytics() { echo ''; } add_action('wp_footer', 'add_cabin_analytics'); ``` 5. Set the snippet to run on the "Frontend" only. 6. Click **Save Changes and Activate**. Alternatively, you can follow the WordPress instructions above using the Insert Headers and Footers plugin. ## Squarespace > [!NOTE] > Only available on Squarespace's Business or Commerce plans. 1. Click **Settings**, click **Advanced** and then click **Code Injection** 2. Add the following code to the **Footer**: ```html ``` 3. Click **Save** at the top of the page. More details at [Squarespace](https://support.squarespace.com/hc/en-us/articles/205815908-Using-Code-Injection) ## Wix > [!NOTE] > Only available on a paid Wix plan. 1. Click **Settings** in your site's dashboard. 2. Click the **Tracking & Analytics** tab under **Advanced Settings**. 3. Click **+ New Tool** and select **Custom** from the dropdown. 4. Paste in the code from below: ```html ``` 5. Select the relevant domain. _Note: This option will appear only if you have multiple domains_. 6. Enter a name for your custom code. E.g. _Cabin Script_ 7. Add Code to Pages: Choose **All Pages** and **Load code once**. 8. Place Code in: Choose **Body - end**. 9. Click **Apply**. More details on [Wix](https://support.wix.com/en/article/embedding-custom-code-to-your-site) ## Next.js Create or edit the `app/layout.js` (or `app/layout.tsx`) file and import the script in your RootLayout component: ```jsx import Script from 'next/script' export default function RootLayout({ children }) { return ( ``` 4. Click **Save**. More details on [Ghost](https://ghost.org/help/post-settings/#code-injection). ## Webflow > [!NOTE] > Only available for paid Webflow accounts. 1. Go to your **Project settings** (gear icon in the left sidebar). 2. Select **Custom code** in the tabs menu. 3. Paste the tracking code below into the **Footer Code** section: ```html ``` 4. Click **Save Changes**. 5. Click **Publish** to make your changes live. More details on [Webflow custom code](https://help.webflow.com/hc/en-us/articles/33961357265299-Custom-code-in-head-and-body-tags). ## Nuxt 1. Edit your `nuxt.config.js` file 2. Add the script to `app.head`: ```js export default defineNuxtConfig({ app: { head: { script: [ { src: 'https://scripts.withcabin.com/hello.js', defer: true, async: true } ] } } }) ``` More details on [Nuxt head management](https://nuxt.com/docs/getting-started/seo-meta). ## Svelte/SvelteKit 1. Edit your `src/app.html` file 2. Add the script before the closing `` tag: ```html %sveltekit.head%
%sveltekit.body%
``` More details on [SvelteKit app.html](https://kit.svelte.dev/docs/project-structure#project-files-app-html). ## Gatsby 1. Install the Gatsby Script API: ```bash npm install gatsby-script ``` 2. Edit your layout component (typically in `src/components/layout.js`): ```jsx import React from "react" import { Script } from "gatsby" export default function Layout({ children }) { return ( <> {children} ``` 3. Make sure this partial is included in your site's main layout. Alternatively, you can add it directly to `layouts/_default/baseof.html` before the closing `` tag. More details on [Hugo Templates](https://gohugo.io/templates/introduction/). ## Astro 1. Edit your main layout file (typically in `src/layouts/Layout.astro`): ```html ``` More details on [Astro Layouts](https://docs.astro.build/en/core-concepts/layouts/). ## Framer > [!NOTE] > This requires a paid Framer plan that allows custom code insertion. 1. Open your Framer project. 2. Click on the **Settings** icon in the left sidebar. 3. Select the **General** tab. 4. Scroll down to **Custom Code**. 5. Paste the following code in the **Before `` tag** section: ```html ``` 6. Click **Save**. ## Bubble 1. Go to your Bubble app's dashboard. 2. Click on **Settings** in the left sidebar. 3. Navigate to the **SEO/metatags** tab. 4. Scroll down to **Advanced settings**. 5. Find the **Script in the body** section and paste the following code: ```html ``` 6. Click **Save**. More details on [Bubble's SEO/metatags settings](https://manual.bubble.io/core-resources/application-settings/seo-metatags#script-meta-tags-in-header). ## Carrd > [!NOTE] > This requires a Carrd Pro Standard plan or higher. 1. While editing your Carrd site, click on the **+** button (Add Element) in the top bar. 2. Select **Embed**. 3. Set **Type** to **Code**. 4. Paste the following code: ```html ``` 5. (Optional) Set **Label** to something descriptive like "Cabin Analytics". 6. For **Style**, select **Hidden** and choose **Body End** for placement. 7. Click **Add**. 8. Click **Publish** to make your changes live. More details on [Carrd Custom Code Embedding](https://carrd.co/docs/building/embedding-custom-code). ## Webnode > [!NOTE] > This requires a Webnode Premium plan (for projects created after June 26, 2023). 1. In your Webnode editor, position your mouse in a section where you want to add the code. 2. Click the **plus button** to add new content. 3. In the content bubble, click the circle for more options, then click on **HTML**. 4. Paste the following code: ```html ``` 5. Note that you will only be able to see the HTML added in the published version of your website, not directly in the editor. 6. Click **Publish** to make your changes live. More details on [Webnode HTML code insertion](https://www.webnode.com/support/add-html-code/). ## Google Tag Manager > [!WARNING] > While this method works, it's not recommended for privacy-focused analytics. Using Google Tag Manager sends data to Google servers before loading Cabin, which defeats some of Cabin's privacy benefits. Consider direct installation when possible. 1. Log in to your [Google Tag Manager](https://tagmanager.google.com/) account. 2. Select your container. 3. Click on **Tags** in the left sidebar. 4. Click **New** to create a new tag. 5. Click on **Tag Configuration** and select **Custom HTML**. 6. Paste the following code: ```html ``` 7. Click on **Triggering** and select a trigger (typically "All Pages"). 8. Name your tag (e.g., "Cabin Analytics") and click **Save**. 9. Click **Submit** to publish your changes. More details on [Google Tag Manager](https://support.google.com/tagmanager/answer/6103696). --- ## Checking it works Open your site, then open your Cabin dashboard: your own visit should appear right away. If nothing shows up, check that the script tag is in the published version of the page (view source and search for `hello.js`), and that an ad-blocker isn't blocking it. [Custom domains](https://docs.withcabin.com/bypass-ad-blockers.md) fix that for good. You can also ask an AI assistant to check it for you with [MCP](https://docs.withcabin.com/mcp.md): "is Cabin installed correctly on example.com?" If you need more help installing Cabin, please contact [hello@withcabin.com](mailto:hello@withcabin.com). --- # Energy & Carbon **Available on:** Plus and Scale Cabin measures how much data each of your pages moves, and turns that into an estimate of the carbon your site emits. It runs automatically on the pages your visitors actually load, so there's nothing to set up. ## How It Works Our carbon tracking system analyzes all files loaded on your website to calculate the total data transfer. A page analysis is triggered when: 1. The page receives visitor traffic 2. At least 3 days have passed since the previous analysis 3. The page content has been modified (detected by checking the **last-modified** header and comparing the HTML against our stored hash) This intelligent approach prevents unnecessary processing of unchanged assets, conserving both computational resources and energy. Each analysis is recorded in a historical log specific to that page. ## Visitor Load Calculation We determine how much data each visitor loads by applying a percentage based on their browsing history: | Visit Type | Asset Load | | -------------------------------------------------------------------- | ------------------- | | First visit to your website | 100% of page assets | | First visit to the specific page, but has visited your domain before | 50% | | Returning visitor to the specific page | 5% | ## CO2 Calculations Our carbon emissions calculations are powered by The Green Web Foundation's [CO2.js library](https://developers.thegreenwebfoundation.org/co2js/overview/). Digital activities have a carbon footprint, and our goal is to help you understand and reduce yours. The CO2.js library allows us to estimate the environmental impact of your website's data transfer by converting bytes into carbon emissions estimates. The calculations take into account various factors in the digital supply chain, including network infrastructure, user devices, and data centers. We automatically check your hosting provider against The Green Web Foundation database to determine if you're using a green hosting service, which can significantly reduce your website's carbon footprint. ## Why some pages show no energy data Occasionally a page shows no page size or carbon estimate. The most common reasons are: - **The site blocks automated requests.** To measure a page Cabin loads it the way a browser would. If your site (or a service in front of it, like Cloudflare) blocks automated visitors, the analysis can't complete. - **The page returned an error or doesn't exist.** A `404`, a redirect loop, or a page that requires logging in can't be measured. - **The page was too slow to respond** and the analysis timed out. **This is usually nothing to worry about.** If a page blocks automated visitors, your bot protection is doing its job, and you still get full analytics for that page (visits, referrers, events); only the energy estimate is missing. For most sites that's a perfectly reasonable trade-off and you don't need to change anything. Cabin also re-checks pages automatically as they receive traffic, so transient problems clear on their own. ### If you want energy data for a blocked page Measuring a protected page means letting Cabin's analyzer past your bot protection, which is a security trade-off rather than a free win. Weigh it against why the protection is there. Cabin's requests identify themselves with a User-Agent of `Cabin-Size/0.1 withcabin.com` and an `X-Cabin-Bot: 1` header. > [!WARNING] > These are just labels, and anyone can copy them. A firewall rule that allows traffic based on this user-agent or header will let **any** request through your bot protection. Only do this if you accept that, and keep the rule as narrow as you can. > #### Cloudflare - **Bot Fight Mode (Free)** can't be skipped with a rule: it runs outside Cloudflare's rules engine. The only lever is to **turn it off** (Security → Bots), which lowers protection across your *whole* site. Consider whether that's worth it just for carbon data. - **Super Bot Fight Mode (Pro/Business)** *does* run on the rules engine: prefer it. Add a **WAF custom rule** with the **Skip** action matching `http.user_agent contains "Cabin-Size"`, set to skip Super Bot Fight Mode only. That's far more targeted than disabling protection globally. - **AI Crawl Control (all plans)**: a separate feature from Bot Fight Mode, often on by default, and a common reason a page comes back blocked even when nothing else looks unusual. Go to Security → AI Crawl Control: Cloudflare generates its own WAF rule for this, and supports editing that rule directly to add an exception (an extra user-agent condition) rather than turning the whole thing off. Add a clause excluding `http.user_agent contains "Cabin-Size"` and every other AI crawler stays blocked. Worth keeping in mind this one exists specifically to keep AI training scrapers out, so an exception here is a more pointed trade-off than the Bot Fight Mode case above, because anyone who spoofs the same header gets past the AI-scraper block too, not just generic bot detection. #### Other firewalls and WAFs Add a narrowly-scoped allow rule for requests where the **User-Agent contains `Cabin-Size`** (or the **`X-Cabin-Bot` header is present**), keeping the spoofing caveat above in mind. Once allowed, Cabin picks the page back up on its next visit. --- # Campaigns and UTM Parameters **Available on:** every plan Cabin allows you to identify and analyze marketing campaigns from referral traffic using UTM parameters, helping you measure ROI effectively. ## What are UTM Parameters? UTM (Urchin Tracking Module) parameters are special URL parameters that help track the effectiveness of your marketing campaigns. They provide information about where your traffic is coming from and which marketing efforts are driving visitors to your site. ### Key UTM Parameters - `utm_campaign`: Identifies a specific promotional campaign (e.g., "summer_sale", "product_launch") - `utm_medium`: Indicates the marketing medium (e.g., "email", "paid_social", "cpc") - `utm_source`: Specifies the source of the traffic (e.g., "instagram", "newsletter", "google") ## Example In the following example, a 'summer_sale' campaign is tracked from a paid Instagram ad: `https://myshop.com?utm_campaign=summer_sale&utm_medium=paid_social&utm_source=instagram` Cabin digests these automatically and displays them in the Campaigns section of the dashboard. Clicking on a campaign will show the source, medium and path of the referrals from that campaign. --- # Event Tracking **Available on:** Plus and Scale Events record the things people *do* on your site, not just the pages they land on: a signup, a download, a video played. They're anonymous like the rest of Cabin, and they take one attribute or one line of JavaScript to add. ## What are Events? Events allow you to track specific user interactions that occur on your website beyond standard page views. While page analytics tell you which pages users visit, events provide deeper insights into how users engage with your content and features. Common use cases for events include: - Button clicks and link interactions - Form submissions - Video plays, pauses, and completions - File downloads - Newsletter signups - Feature usage - Custom conversion actions ## Tracking Events Cabin automatically records which page triggered each event, giving you context for user interactions. There are two ways to implement event tracking: ### 1. Using HTML Data Attributes Add the `data-cabin-event` attribute to any HTML element: ```html Download Menu ``` HTML attributes are automatically converted to `click` events when the element is clicked. ### 2. Using JavaScript For more complex interactions or custom triggers, use the JavaScript method: ```js cabin.event('Download Menu') ``` This approach gives you flexibility to trigger events based on any condition or user action. ## Examples Here are some common event tracking examples: ```html Download Annual Report
``` ## Viewing Events in the Dashboard Events are displayed in a dedicated list on your dashboard. Each event can be expanded to see which pages triggered the events. The dashboard shows click rates for both Unique Visitors and Total Visitors, allowing you to analyze both overall engagement and unique-visitor interaction patterns. ![Events](https://docs.withcabin.com/assets/events.webp){.border} --- # Referrers **Available on:** every plan Cabin captures referrer information when visitors arrive at your website, helping you understand where your traffic is coming from while respecting privacy. However, certain browser privacy features and technical limitations may prevent referrer data from being collected. ## Common Reasons for Missing Referrer Data 1. **Direct Navigation**: When visitors type your URL directly into their browser's address bar or use a bookmark, no referrer information is available. 2. **Security Downgrade**: If a visitor clicks a link from a secure website (HTTPS) to your non-secure website (HTTP), browsers typically strip the referrer information to protect user privacy. 3. **Explicit Blocking**: When visitors click links containing the `rel="noreferrer"` attribute, browsers intentionally withhold referrer information. If you notice traffic from a specific site but no referrer data, you might consider reaching out to the site owner about removing this attribute (while respecting their privacy choices). 4. **Single-page navigation**: The referrer is recorded once, on the first page of a visit. Moving between pages of your own site doesn't overwrite where the visitor originally came from. Cabin only collects the referrer information that browsers willingly provide, and never uses fingerprinting or other invasive methods to work around these privacy mechanisms. Any query string on the referring URL is stripped in the browser before it's sent, so a referrer can't leak search terms or tokens into your analytics. --- # Bounce Rate **Available on:** every plan Bounce rate represents the percentage of visitors who view only a single page on your site before leaving, without interacting with any other pages. It's calculated by dividing the number of **single-page sessions** by the **total sessions** on your site. ## How Cabin Measures Bounces Unlike traditional analytics tools, Cabin doesn't use cookies to track "sessions" (protecting your visitors' privacy). Instead, Cabin tracks how many visits a user makes to your domain within a day. A visitor is considered a "bounce" _until_ they navigate to another page on your site. This privacy-preserving approach gives you valuable insights without compromising user data. Learn more about our unique tracking methodology in our [Unique Visitors guide](https://docs.withcabin.com/index.md#unique-visitors-without-cookies). ## Reading Your Bounce Rate Data The prominent figure in the summary section displays the overall bounce rate for your selected date range. ![Bounce rate](https://docs.withcabin.com/assets/bounce-rate.webp) You can also view a chart of your bounce rate over time. ![Bounce rate chart](https://docs.withcabin.com/assets/bounce-rate-chart.webp) ## Best Practices for Interpretation **Pro tip:** For the most accurate assessment, evaluate bounce rates at the end of the day. Since visitors are counted as bounces until they navigate to another page, your dashboard may temporarily show elevated bounce rates during periods of high traffic until visitors begin exploring your site further. Cabin doesn't currently break bounce rate down by page. --- # Scroll Depth **Available on:** every plan Scroll depth shows how far down a page your visitors get. It comes from the same script that records page views, adds no extra requests, and is anonymous like everything else in Cabin. ## What is measured Each visit records the **deepest point** it reached, as a percentage of the page's content. It's sent once, when the visitor leaves the page. The percentage is measured against the page's **content**, not the whole document, so a long footer doesn't make a full read look like 75%. See [what counts as the page](#what-counts-as-the-page). ## Where to find it **On the dashboard**, the Attention row shows your site's average scroll depth. The small strip beside it is a picture of a page: solid at the top and fading downward as visitors fall away. Hover a band for the exact share who got that far. **In the page peek**, open any page from Top Pages and switch to the Attention tab for the same figures for that page, plus a bigger version of the strip as a list. ## Reading the heat map Each row is the share of visitors who reached **at least** that far down the page. The 0% row is everyone, and the rows only ever fall from there. ![Scroll depth heat map](https://docs.withcabin.com/assets/scroll-depth.webp) The drop between two rows is where people stopped. A big drop near the top means most visitors never scrolled. A 100% row not far below the rest means most who started kept going to the end. Reaching 100% means the bottom of the content was on screen, not that it was read. Someone who flicks straight to the end counts. ## What counts as the page Cabin measures depth against the content block, found in this order: 1. An element with `data-cabin-content`, if you've added one. 2. Otherwise the first `
` or `
`. 3. Otherwise the whole document, cut off at the first `