La Boétie

Analytics: cookieless product analytics

Analytics is a cookieless product analytics package that a site runs in its own stack. Before consent the package reads only the visitor choice from the device. No stored record holds an IP address. Session replay and experiments start after consent. This prototype has no dashboard yet, so reports on funnels, retention and paths are read through code.

Funnels, session replay and experiments with a cookieless default

Status
Prototype
Access
By request

Analytics capabilities

Three consent states

Consent sets one of three behaviors. In the default unknown state, the package reads and writes only the visitor choice on the device and keeps ids in memory. The granted state adds a persistent visitor, session storage, replay and surveys. In the denied state the library collects nothing and erases what it wrote to the device.

Counting visitors without cookies

A cookieless visitor counts as one page load unless the site sets a secret. With a secret, the collector computes a keyed hash of the IP address and user agent under a key that rotates each UTC day, then discards the IP. Repeat visits by one visitor within one day count as one unit. This hash is pseudonymous data, so the site mentions it in its privacy policy.

Funnels, retention, paths and heatmaps

The query helpers cover funnels, retention, paths, source cohorts and heatmaps. Funnels have ordered steps with any events allowed between them. Each report returns data to your code, so a developer reads it through a query or builds an admin page on a read only database user.

Session replay with masked inputs

Session replay starts after consent. The collector rejects chunks collected without consent. The recorder masks every input, textarea, select and contenteditable element. No option turns that masking off. Chunks are stored per session for 30 days.

Experiments and feature flags

Experiments give each visitor a sticky variant, and that assignment needs granted consent. Before consent a visitor sees the baseline and no exposure is recorded. A change of weights or a new variant keeps existing assignments as they are. A flag at full rollout is on for all visitors, while a partial rollout stays off until consent.

On this page

What cookieless analytics means

Cookieless analytics measures how people use a website without storing an identifier on their device. Classic analytics tools write a cookie, which ties visits together and usually requires consent first. A large share of visitors refuses or ignores the banner, so the numbers go missing.

Cookieless tools count visits with no device storage, and that keeps a basic measurement available before any consent choice. The trade is real: you lose the ability to follow one person across several days.

Analytics takes a two state approach. Before consent it runs cookieless. Once a visitor accepts, it switches to full product analytics with a stable visitor, funnels across visits and session replay.

How the two consent states work

StateWhenWhat runs
cookielessBefore any choice, or after a refusalPage and interaction counts with no device storage
grantedAfter the visitor acceptsPersistent visitor, session storage, a durable event queue, click ids, replay, surveys and person properties

You can choose a stricter mode. With whenUnknown: 'off', nothing is collected before a choice. The package can also read the choice from your consent platform, so visitors see one banner.

How cookieless visitors get counted

Without storage, the collector cannot tell whether two page loads came from one person. The collector offers two options.

SettingHow a visitor is countedEffect
No secret setEach page load is one unitThe strictest option, and a hard navigation looks like a new visitor
Daily counting onA short lived anonymous countOne visitor stays one unit for a day, and days cannot be linked

No IP address is stored. Your privacy policy should still describe this measurement.

What the client captures

Each module turns on or off by itself. Replay and surveys stay off until a project enables them.

ModuleWhat you get
pageviewsPage views with landing page and first touch source
clicksClicks with a label and a selector
formsStarts, submits and abandons
scrollDepth, engagedTimeHow far and how long people read
rageClicks, deadClicksFrustration signals: repeated clicks and clicks that do nothing
jsErrorsGrouped JavaScript errors
webVitalsReal user performance measures
trafficSourceWhere the session came from
heatmapsAggregated clicks and scroll depth

Clicks store a label and a selector in place of the full element tree, which keeps stored data small.

Web analytics, product analytics or session replay

Three families of tools answer different questions, and vendors often blur them.

FamilyMain questionTypical output
Web analyticsHow many people came, and from where?Visits, sources, top pages
Product analyticsWhat do people do, and where do they stop?Funnels, retention, paths
Session replayWhat happened in this one visit?A video like recording
ExperimentationWhich version works better?Variants and lift
Server logsWhat did the server receive?Requests, including bots

Analytics covers the first four in one package from one event stream. Separate tools each keep their own copy of your visitors, and their numbers rarely match. Logs remain useful for bots and errors, since AI crawlers run no JavaScript.

Common measures

MeasureDefinitionRead it as
Unique visitorsDistinct units in a periodDepends on your consent state, so compare like with like
SessionsGrouped activity of one visitorThe natural unit for traffic
Engaged timeTime with the page in focus and activeBetter than time on page
Scroll depthHow far people readWhether the page keeps attention
Conversion rateConversions divided by sessionsCompare per source
Rage clicksRepeated clicks on one spotSomething looks clickable or fails
Dead clicksClicks that change nothingA broken promise in the interface

Cookieless numbers and consented numbers are different populations. Visitors who accept tend to differ from those who refuse, so avoid mixing them in one funnel without saying so.

Core Web Vitals

Google publishes three measures of real user experience, and the webVitals module collects them from your visitors.

MeasureWhat it coversGood at the 75th percentile
LCP, Largest Contentful PaintLoading of the main element2.5 seconds or less
INP, Interaction to Next PaintResponse to clicks and taps200 milliseconds or less
CLS, Cumulative Layout ShiftVisual stability0.1 or less

Field data from real devices often looks worse than a test on your own laptop. Read it per page and per device.

Write a tracking plan first

Inconsistent events break reports: signup, Sign Up and user_registered can all mean one thing. Agree on names before anyone writes code.

RuleExample
Use object_action in lower casequote_requested
Use the past tenseform_submitted, never submit_form
Put variations in propertiesplan: 'pro', never quote_requested_pro
Keep personal data out of propertiesNo email, no name
Give each event one ownerThe team that reads it

A plan for a lead generation site can stay short.

EventPropertiesQuestion it answers
page_viewAutomaticWhat do people read?
calculator_startedproductDo visitors engage?
quote_requestedproduct, sourceWhich pages produce leads?
call_bookedproductDo leads go further?

Start with about ten events, and add one only when someone will read it.

Tracking where visitors come from

The trafficSource module reads the referrer and the campaign tags of each session. UTM tags are parameters you add to a link, so a report can tell one campaign from another.

https://example.com/offer?utm_source=newsletter&utm_medium=email&utm_campaign=spring
TagAnswersExample
utm_sourceWho sent the visitor?newsletter, linkedin
utm_mediumThrough what kind of channel?email, cpc, social
utm_campaignFor which campaign?spring
utm_contentWhich link or version?header_button

Keep tags in lower case and write the list down, since Email and email become two sources in a report. Leave tags off internal links, because they overwrite the true source of the session.

Paid clicks carry their own click ids. Those are stored only with consent, so an offline conversion upload depends on the visitor having accepted.

First party collection and ad blockers

A script served from an analytics vendor's domain sits on most blocklists. An endpoint on your own domain, such as /api/site-events, appears as part of your site, so fewer requests are lost. Privacy tools can still block it, and visitors keep their right to refuse. A first party endpoint improves data quality and leaves your consent duties unchanged.

Bots add noise from the other side. Many run no JavaScript and never reach the collector, while others do. Compare your analytics totals with your server logs from time to time.

Install it in a Next.js site

The package installs as a private tarball, so the site keeps it in its own repository. Three pieces connect it.

The layout wraps the app in a provider.

import { AnalyticsProvider } from '@infra/analytics/react';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        <AnalyticsProvider endpoint="/api/site-events" projectKey="my-site">
          {children}
        </AnalyticsProvider>
      </body>
    </html>
  );
}

A route on your own domain receives the events.

import { createCollector, createMongoSink, createRouteHandler } from '@infra/analytics/server';
import { getAnalyticsDb } from '../../../lib/analytics-db';

export const runtime = 'nodejs';

export const { POST } = createRouteHandler(() =>
  createCollector({
    sink: createMongoSink({ db: getAnalyticsDb, projectKey: 'my-site' }),
    projectKey: 'my-site',
    onError: (error) => console.error('[analytics]', error),
  }),
);

Any client component can then record a business event.

const analytics = useAnalytics();
analytics.track('quote_requested', { plan: 'pro' });

The endpoint sits on your domain, so requests reach your own server. That makes the setup first party, and it means the events land in a database you already run.

Session replay with masked inputs

Session replay records what a visitor did on the page so you can watch it back. Done carelessly, it records passwords and personal data.

Here, the recorder loads only with consent. Visitors without consent never download it. Every input, textarea and select is masked, along with any editable content, and no option turns that masking off. Setting maskAllText: true masks page text too, and data-analytics-mask masks one element.

Recordings are compressed, stored per session and kept for 30 days. The collector refuses a recording unless replay is on for the project and the event was collected with consent. The recorder weighs about 35 KB gzipped.

Experiments and feature flags

An A/B test shows two versions to two groups and compares the results. Assignment needs a visitor who stays the same between page loads, so it needs granted consent.

Assignment sticks once made. Changing the weights or adding a variant moves nobody already assigned. The hook works in any component.

const variant = useVariant('pricing-page');
const enabled = useFeatureFlag('new-checkout');

Flags live in code or come from your own server. There is no separate flag service to run.

Funnels, retention and paths

Query helpers compute each report from your stored events.

const retention = await sink.queries.retention({ period: 'week' });
ReportThe question it answers
FunnelWhere do people drop out of a sequence of steps?
RetentionHow many visitors come back after their first visit?
PathsWhich routes do people take through the site?
Source cohortsWhich traffic sources bring visitors who stay?
HeatmapWhere do people click and how far do they scroll?

A worked funnel

Take a quote form with four ordered steps. Over a month, the funnel returns these counts.

StepVisitorsKept from previous step
Viewed the form10,000
Started the form3,20032%
Reached the last step1,40044%
Submitted98070%

Overall conversion is 9.8%. The largest loss sits at the first step, so start with the page above the form. Field level abandon events then show where people stop inside the form.

Read a funnel per source too. A step that works for search visitors can fail for paid social visitors, who arrive with less intent. The figures above illustrate the method and come from no client.

A worked retention table

Retention groups visitors by the week of their first visit and counts how many return.

First weekWeek 0Week 1Week 2Week 3
Cohort A100%24%15%12%
Cohort B100%28%19%16%

Read down the columns, since a newer cohort that holds better means a change worked. A curve that flattens shows a group of people who keep coming back. These figures are also illustrative.

Retention needs a stable visitor, so it counts consented visitors. Cookieless days cannot be linked.

Reading an experiment

A difference of a few conversions proves little, so let a test finish.

RuleWhy
Choose the metric before you startOtherwise you pick the winner after the fact
Fix the length in advancePeeking inflates false wins
Run full weeksBehaviour shifts between weekdays and weekends
Change one thingYou learn what caused the result
Keep a record of each testTeams repeat old mistakes

Small sites rarely reach enough conversions for a fair test. If a page gets a few conversions a week, use interviews and session replay in its place.

Moving from a hosted analytics tool

  1. Export or screenshot the reports you read, since history stays behind.
  2. Write the tracking plan.
  3. Run both tools side by side for a month.
  4. Compare totals per source, and expect a gap between them.
  5. Rebuild the reports your team reads each week through the query helpers.
  6. Remove the old tag and update your privacy policy.

Two tools will never match exactly, because they differ on bots, consent and session rules. Look for stable trends.

How to read a heatmap

A heatmap combines the clicks and scroll depth of many visitors on one page.

What you seeWhat it often meansWhat to try
Clicks on something that is not a linkVisitors expect more detailMake it a link
Few clicks on the main buttonThe offer or the wording is weakRewrite before you redesign
Most visitors stop halfwayThe page lost them thereMove key proof higher
Heavy clicks on the menuVisitors looked elsewhere for the answerAdd the answer to the page

Read phones and desktops apart, since the layouts differ. A heatmap on a page with a few dozen visits shows noise, so wait for volume.

What to do with frustration signals

Rage clicks and dead clicks turn vague complaints into a list of places to look.

  1. Sort the pages by frustration events per visit.
  2. Open a consented replay of a session on the worst page.
  3. Note what the visitor expected.
  4. Fix the cause, then compare the same measure a week later.

jsErrors groups JavaScript errors, so a bug that hits one browser appears as one line with a count. Set aside time each week to read that list, because users seldom report these errors themselves.

Surveys in the page

A short question at the right moment can explain what numbers cannot. Surveys run with consent. Ask one thing, close to the event: "What almost stopped you from signing up?" on a confirmation page gives you the wording for your next headline. Keep answers free of personal data, and read them in full, since a count of themes loses the voice of the customer.

Data retention and storage

Events default to a 13 month lifetime, and replay to 30 days. With consent, the visitor id lasts 13 months from creation, and a new visit does not extend it. You store the data in your own MongoDB.

DataDefault lifetime
Events13 months
Consented visitor id13 months from creation
Session replay30 days
Raw IPNever stored

Consent rules and your obligations

The cookieless mode was designed around the conditions the French data authority sets for audience measurement without consent: first party, for the publisher alone, statistics only, no cross site tracking and no merging with other processing. Nobody has audited or certified that design. Whether your deployment qualifies is a decision for your own counsel, and your site must still describe the measurement in its privacy policy and offer a way to refuse.

Replay, surveys and person properties fall outside that exemption and require consent.

Consent banner design

Your banner affects how much consented data you collect. Regulators in several countries ask for refusing to be as easy as accepting.

DoAvoid
Offer accept and refuse at the same levelHiding refuse behind a second screen
Name the purposes in plain wordsVague phrases such as "improve your experience"
Keep a way to change the choice laterA one time banner
Record the choiceAsking again on each page

The package reads the state you give it, so any banner works. Keep the words on your banner in line with what the code does: if replay runs after consent, the banner must say so.

Self hosted analytics or a hosted tool

QuestionSelf hosted in your stackHosted tool
Where is the data?Your databaseThe vendor's servers
Who pays for volume?You, through your own storageYou, through the vendor's pricing
Who runs it?Your teamThe vendor
DashboardsYou build or wire themIncluded
Blocked by ad blockersLess often, since the endpoint is first partyMore often, when the script loads from a vendor domain

Choose a hosted tool if your team wants ready dashboards today. Choose a self hosted package if owning the data matters more and you already run a database.

Questions to ask before choosing any analytics tool

  1. Which questions must it answer in the next quarter?
  2. Who reads the reports, and how often?
  3. Where does the data live, and for how long?
  4. What runs before consent?
  5. Can you export raw events?
  6. What happens to the cost when traffic grows tenfold?
  7. Who fixes it when the numbers look wrong?

Reporting rhythm

FrequencyWhat to readWho reads it
WeeklyTraffic, conversions, frustration signalsThe team running the site
MonthlyFunnels and sourcesMarketing and product
QuarterlyRetention and experimentsLeadership

Keep the list short, and read it on a fixed schedule.

Next step

Analytics is available on request. You receive a private package and its third party notices. Send a brief with your site, your consent setup and the funnels you need to read. It pairs with Cortex for organic growth and with Ads for paid traffic.

Frequently asked questions

What is cookieless product analytics?

Cookieless product analytics is site measurement that stores no cookie or identifier on the visitor device. Before consent, this package keeps ids in memory and reads only the visitor choice from the device. Reports on funnels, retention and paths run on those events. A visitor cannot be followed across days in this mode.

Do I need a cookie banner with cookieless analytics?

The package cannot settle that for you, because a site's own use of the data decides whether a consent exemption holds. The CNIL lists conditions such as use for the publisher alone, anonymous statistics and no cross site tracking. A site owner still has to describe the measurement in the privacy policy and offer a way to refuse. This describes code behavior and is no legal opinion.

Does session replay work without consent?

No. Replay, surveys and person properties require consent in this package. The collector accepts replay chunks only when replay is enabled and the event was collected with consent. Every form field is masked in the recorder, and one option masks all page text as well. The site database keeps recordings per session for 30 days.

How long does the package keep data?

Default event retention is 13 months against a CNIL recommended maximum of 25 months. Session replay chunks last 30 days per session. With consent, the visitor id lasts 13 months from creation, and a new visit does not extend it. These defaults apply in the MongoDB database of the site, which stays separate from its other data.

What does autocapture record?

Autocapture records views, clicks, forms, rage clicks, web vitals and errors. It does not read field values. It stores the name and the type of a field and whether it is filled. Masking covers emails and long numbers in all strings. Keys such as email or password are dropped twice, once in the browser and once on the server.

Does Analytics have a dashboard?

No. The roadmap calls the missing dashboard the largest gap of Analytics. Developers read funnel, retention, path and cohort data through the query helpers or through an admin page built on a read only database user. A team that needs ready made charts for non technical staff has to build them first.

Where does the data live?

The data lives in a MongoDB database that the site owns. A collector route inside the site writes events through an ingest user limited to that database, and reports use a separate read user. The package installs as a vendored private tarball inside the site repository, so a deploy has no outside dependency. Third party notices travel with the package.