Coruve

Reports

Reports explained

Every report the dashboard has today, the question it answers, the URL it lives at, and the plan it needs. Nothing on this page is a roadmap item.

Why the Brief and Explore can show different numbers

Same metric, same project, two honest windows — and the difference is exactly one day.

Two windows, both deliberate

The Brief measures the last 7 FULL days, ending yesterday — today is excluded on purpose, because the Brief's job is comparison, and a partial today would skew every 'vs the week before' delta. Explore's 'Last 7 days' is a rolling window: the last 6 full days plus today so far, because a live dashboard that hides today would be broken the other way. The two overlap on six of their seven days, so on a busy site they will rarely show the same visitor count — and both are correct for the question their surface answers. The Brief prints its exact date span next to every figure so the two can never be mistaken for the same window; Ask's 'last 7 days' matches Explore's. On any closed range — a specific month, a fixed pair of dates — every surface agrees exactly.

How the dashboard is organised

Seven surfaces, and most reports are a view inside one of them rather than a page of their own.

The seven surfaces

Every project opens on the Brief. The other six sit beside it in the navigation. A surface is a real route; a view is a state of that route, so the browser back button, a bookmark and a shared link all behave the way you expect.

SurfaceURLWhat it is for
Brief/project/{id}The home screen. What changed since you last looked, ranked, with the evidence and a pre-filled action under each item.
Explore/project/{id}/exploreOne instrument, eleven subjects. Where you go to ask about traffic, sources, devices, pages, speed and behaviour.
Realtime/project/{id}/realtimeWho is on the site right now, and the events landing as they land.
Outcomes/project/{id}/outcomesThe four reports about results rather than traffic: goals, funnels, retention and revenue.
Impact/project/{id}/impactThe ledger of closed cases: what Coruve caught, the drafted fix, and the verified before/after recovery. Recovery figures are estimates — direction, not accounting.
Ask/project/{id}/askA plain-language question about your own site, answered by a deterministic query with the matching report one click away.
Settings/project/{id}/settingsProject setup, watched segments and alerts, team, billing, and the history importers.
Explore and Outcomes select their subject with ?view=, and Settings with ?section=. So /project/{id}/explore?view=devices is the Devices report, and it is a link you can send to a colleague. An unrecognised value is not a 404 — it falls back to the surface's default view.

Explore — the eleven views

Each one answers a different question about the same traffic, under the same date range and the same filters.

What each view answers

The rail down the left of Explore switches subject without losing your range, your filters or your comparison. Add ?view= to the Explore URL to open one directly.

View?view=The question it answersPlan
OverviewoverviewHow much traffic, from where, to which pages — the default view.Every plan
AcquisitionacquisitionWhich channels, sources and campaigns brought people, and how each one performed.Every plan
LocationslocationsWhich countries, regions and cities visits came from. Derived from the IP at the moment of the request, which is never stored.Every plan
AI TrafficaiHow much of your traffic is people, AI assistants and ordinary crawlers, which assistants, and how each visit was identified.Every plan (quality layer Starter and up)
DevicesdevicesDesktop, mobile or tablet; which browsers and operating systems.Every plan
JourneysjourneysThe paths people actually take through the site, forwards or backwards from any page you anchor on.Every plan
FrustrationfrustrationWhere people got stuck: rage clicks, dead clicks and quick backs, by page and by source.Starter and up
SessionssessionsSession shape — how long, how many pages, which pages people entered and left on.Every plan
EventseventsThe event catalogue: every behaviour Coruve has catalogued on your site with its kind, its counts and sessions for your range, when it was last seen and how it trends. See The event catalogue below.Every plan
Site HealthhealthReal-user speed measured in your visitors' browsers — TTFB, FCP, LCP, INP, CLS — worst pages first.Every plan
MapsmapsWhere people click on a page and how far down they read, as a density grid rather than a screenshot overlay.Starter and up
Because Coruve has no picture of your page and never will — no session recording, no screenshot capture. The maps are click positions and scroll depths on a grid, which is a different and much less invasive thing than the industry word promises.

The AI Traffic view is deliberately split in two

The human / AI / crawler breakdown, the list of assistants and the trend over time are on every plan, including Free — knowing an assistant sent you traffic is table stakes for a product partly named for it. So is the methodology split that says how each visit was identified — Verified (a cryptographic signature checked against the AI company's own published key), Inferred (the visit said so, through its user agent or referrer) and Unattributed (automated, but matched to no product). That split is not sold as an upgrade, on purpose: it is how the numbers above it were arrived at, and a product does not charge for the truthfulness of its own reporting. What Starter and up adds is the quality layer — the conversion multiplier and the per-assistant and per-channel tables.

What counts as a step in a journey

A step is either a page somebody viewed or an event your own site tracked — checkout_start is as much a step as /pricing is. Two kinds of row are deliberately not steps: Coruve's own instrumentation (the scroll and speed beacons the snippet fires, which nobody chose to do), and the clicks captured automatically on every button and link, which would otherwise turn almost every path into a list of clicks. Two views of the same page in a row count once, so a single-page app re-rendering does not invent a step.

Path rules are applied when a journey is read, in one fixed order

Dynamic paths are masked first (if you have that switched on), then any page you have excluded is dropped, then any section you have collapsed becomes a single step. Excluding before collapsing is what makes the two rules independent — the other order would let a rule folding /blog into one step hide a page you had asked to exclude by name. None of this rewrites what was stored, so a rule you add today reshapes last month's paths, and deleting it puts them back on the next load.

Journeys is on every plan; the behaviour maps are not

Journeys used to be Starter and up. It is not any more (revised 2026-08-11): where people go from one page is a question about your own site, and what a plan buys is how much of the analyst's work Coruve does with the answer — not which of your own numbers you may look at. Frustration and Maps (the click-and-scroll report) moved the other way, to Starter and up, for the same reason read in reverse: those two are Coruve examining behaviour rather than counting visits. Both are enforced server-side in the action that fetches the report and again in the CSV export route, so the gate is not something the interface can be talked out of.

The event catalogue

What Coruve worked out your site does, so you can build a goal on a button without knowing what the button is called.

It is the rows of Explore ▸ Events

The Events view is the catalogue. Each row is one behaviour with its kind, how many times it fired and in how many sessions over your range, whether those sessions also reached your goal, when it was last seen, and its trend — with the change against the previous period when comparison is on. Categories group the rows rather than filling a column. Three things feed the list: items the catalogue derived, labels you approved, and raw event names the store counted in this range but has not catalogued yet, so nothing your site sends can hide from this screen. Page views are the one exclusion — they are the whole of the rest of the product.

One picker, four places you name a behaviour

Goals, funnel steps, alert metrics and a segment's behaviour conditions all open the same catalogue picker, and the Events view itself opens it to define something narrower than a row. The point of it is that you never type an event name: you pick the button, form or event from a list Coruve built by watching the site, and what gets saved is the catalogue item's identity, not a string you had to spell correctly. A goal on a button is genuinely a goal on a button — you still name the GOAL, because that name is what appears on your reports, but you never name the event.

You cannot ask a question about a catalogue item by name. The resolver for it exists in the codebase and nothing calls it, and Ask does not mount the picker — so if you name a button in a question, Ask is not looking it up. Ask's subjects are the fixed measurements described above.

Derived nightly, with floors, and capped

The catalogue is rebuilt once a day at 03:00 UTC, staggered so projects do not all run at once, over the last 30 days. A behaviour has to earn its row: at least 5 sessions AND at least 20 events before it is derived at all. Being derived is not the same as being suggested to you — for Coruve to PROPOSE something (a goal worth creating, a name worth accepting) it needs 25 sessions or 50 events. A project carries at most 200 automatically derived items and 400 in total, so a site that fires a distinct event per row of a table does not turn the catalogue into a second copy of its database.

Automatic names are offered before they are applied

Naming reaches three kinds of item — an element, a form, and your own custom events — and nothing else. Below a confidence of 0.6 the suggested name is not used: the item keeps a plain descriptive name and the suggestion sits beside it as something you can accept or dismiss. That is the whole rule, and it is why the catalogue does not quietly rename your checkout button to something a model guessed.

What you can change, and who can change it

Rename an item, define one more precisely, hide one you do not want to see, merge two that are the same thing, or dismiss a name that was offered. All five are owner-and-admin only; every member can READ the catalogue, which is what makes the picker work for everyone. Hiding is about your own screens — see the note on annotations below for the same distinction applied to chart markers.

The per-view depth added in 7D

Seven additions, and each one lives on named views rather than everywhere — which is the part worth knowing before you go looking for it.

Where each one is

None of these is a new report. Each is a panel inside an existing view, and each is on the views where the question it answers is actually asked.

PanelWhereWhat it does
Hour-by-weekday gridExplore ▸ Overview and SessionsSeven rows by twenty-four columns: when in the week your traffic actually happens. The cells are deliberately not links — there is no hour-of-week filter in the product, so a clickable cell would promise a view that does not exist.
Session shapesExplore ▸ SessionsThe common shapes a visit takes, ranked: where it entered, where it left, and how many pages were in between as a band. It is an aggregate, never a list of sessions and never the route between the two ends — Coruve does not offer a session replay and this is what stands in its place. Rare shapes are withheld below a small-numbers floor.
Device tabsExplore ▸ MapsAll, Desktop and Mobile. There is no Tablet tab — tablets are counted in All. The Mobile tab is removed rather than greyed out when there are too few mobile sessions on that page to draw anything honest.
Diverging comparisonExplore ▸ MapsWith comparison on, the click grid switches to a diverging scale reading in percentage points: colder where a cell lost share, warmer where it gained. There is no chooser for it — turning comparison on IS the mode.
Vitals decompositionExplore ▸ Site Health, in the Explain drawerWhy a vital moved, split by page, device and country. It splits the COUNT of poor-rated loads and never the p75, because a percentile cannot be decomposed and the count under it can. The table on the view itself still shows p75s — it is the explanation that is count-only.
Segment A vs BExplore ▸ OverviewTwo saved segments on one chart. Two is the limit and the control says so; a third line stops being readable. Overview only, and setting it clears period comparison — you compare against another segment or against another period, never both at once.
First vs last touchExplore ▸ AcquisitionWhich channel started a visit and which one it converted under, WITHIN a single visit. Not across visits: the anonymous visitor identifier rebuilds every UTC day, so a touch last week and a purchase today cannot be joined. This is the attribution the identity actually supports, and the product does not offer the one it does not.

Notes on a chart

Why the line moved, written down beside the line.

What they are

A note is a dated sentence drawn on a chart: a deploy, a campaign, a content change, an incident, an experiment, a change to what is being tracked, or a plain note. Owners and admins write them; every member reads them. They can be a moment or a span of days, and a note whose exact time was never recorded is drawn as a day rather than being printed at 00:00 — a precision nobody measured.

The glyph is a letter, on purpose

Each category has a single-letter marker rather than a colour of its own. Colour alone fails in greyscale, on a printout, and for a good share of readers; a letter survives all three. The letter is the same everywhere the marker appears.

Machine markers, and what 'hidden' means

Coruve writes notes too — when an alert opened an incident, when a deploy or incident webhook fired, when a history import landed, when a case was verified, when a spike was detected, and when the system changed what it was measuring. Some of those are marked hidden, and hidden means QUIET, not absent: the charts leave them off so the timeline stays readable, the analyst reads them regardless when it explains a change, and ?markers=all on an Explore URL is the real switch that brings them back. A note the chart does not draw is still a note that shaped the explanation you were given.

They draw on three views, not eleven

Overview, Frustration and AI Traffic carry the marker layer. The other eight Explore views do not, and Overview is the only one where a note can be created or deleted. This is worth knowing before you go looking for a marker on Devices: it is not missing, it was never drawn there.

Team notes only, and the WHERE clause is the promise

Every note Coruve stores today is a team note. The read paths that leave this project — the findings engine, the read API, the emails — are each scoped to team notes in the database query itself rather than filtered afterwards, so a private note could never reach any of them by accident. Shared dashboards are stricter still: hidden machine markers are left out of a public share entirely.

Outcomes — the four views

Results rather than traffic. Same URL, selected with ?view=.

What each view answers

Outcomes opens on Goals. Every view here reads the same date range and filters as Explore, so a segment you set in one carries into the other.

View?view=The question it answersPlan
GoalsgoalsHow often each goal converted, and what each conversion is worth if you gave it a value.Every plan
FunnelsfunnelsWhere people fall out of a sequence of steps you defined.Every plan (3 funnels on Free, Infinity on Growth)
RetentionretentionWhether your IDENTIFIED users come back, by cohort. See the note below.Every plan
RevenuerevenueWhat the money did, and which sources it can honestly be credited to.Pro and up

A behaviour condition counts sessions, and says so

A saved segment can say more than “visits from Germany”: it can say “sessions that started checkout at least once and never bought”, or “sessions that landed on /pricing” — up to three such conditions, all required together. The word is sessions everywhere, and that is not a stylistic choice: Coruve keeps no durable identity for a person, so it cannot honestly say “visitors who did X”, only that there was a visit in which X happened. Such a segment covers at most 92 days at a time, because judging it means building a list of every matching session and there is a size past which that list stops fitting — you are told to narrow the range rather than handed a silently shortened one.

Customer value is grouped by the month somebody first paid

The group a customer belongs to is set by their first day with money actually taken — so a history that opens with a refund is not an acquisition, and somebody whose only record is a refund was never a customer at all. Each month after that shows what the group is worth per customer, cumulatively, in US dollars converted at the ECB day rate. Refunds land in the month they happened rather than the month of the charge they reverse, which is why the line can go down. Two limits bound what you see, and they are different numbers: the report shows the last SIX acquisition months as groups, and each group is followed for at most TWELVE months from its first payment. A customer's fourteenth month is not on the chart and is not withheld for a reason — the curve simply stops at twelve.

An unfinished month is drawn as unfinished

A month that has not ended yet is a partial sum, so the line stops solid at the last complete month and continues dotted — it is never filled in with today's running total pretending to be a whole month. A group of fewer than ten paying customers shows its counts and its total but not its average, because an average over nine people invites more confidence than it can carry.

Retention needs identify(), and says so instead of guessing

Coruve's anonymous visitor identifier is a one-way hash that contains the calendar day, so it changes at midnight UTC and a visitor who comes back tomorrow looks like a new one. That is the cookieless trade working as intended, and it means return visits are NOT measurable on anonymous traffic — not approximately, not with a model: the information does not exist. So the Retention page does not draw a grid of it. Where your site calls identify(), Coruve stores a one-way hash of the user id you passed, and that identity is durable — which is what makes real cohorts possible for the people who have an account with you. The page always prints what share of the range's sessions were identified, because a figure about your logged-in users is not a figure about your whole audience. Below a twentieth of your traffic, or fewer than twenty identified users, it shows a card explaining why instead of a grid. Cohorts under twenty users keep their counts and lose their percentages, and periods that have not finished yet are shaded rather than counted as nobody returning. First-seen is judged against the previous 90 days, or your plan's data retention if that is shorter.

What 'Visitors' counts

Visitors counts distinct daily visitor identifiers. The identifier is a one-way hash of the site, the calendar day (UTC), the browser's signature (user agent, language, timezone) and the network address, computed on our servers and never stored in reversible form; the address itself is not stored. Because the day is part of the hash, the same person is a new visitor every day, and we do not know whether anyone came back. Before 2026-08-26 the network address was not part of the hash, so visitors on very common browser set-ups were undercounted; from 2026-08-26 the counts are higher and more accurate. Sessions and everything measured per session did not change.

Revenue is Pro and up, and so are its connectors

The revenue report, the Stripe Connect integration and the Shopify integration all read one flag — revenue tracking — which turns on at Pro. One flag rather than three is deliberate: a plan where you could connect Stripe but not read the report it fills would be a setup flow that ends at an upgrade wall. The live webhooks are the exception and are not gated, so a downgrade stops the reports being readable without losing payments your store is actively reporting. How a payment is credited to a source is its own reference: see Revenue attribution.

Funnels

A sequence of steps, and the two honest readings of what 'in order' means.

Building one

Between two and ten steps, picked from the event catalogue — so a funnel is built out of the same buttons, forms and events the rest of the product knows about, and no step is a string you typed. Ten is not a product opinion: the query engine behind it takes ten conditions.

Two readings, and why both are shown

The headline number is the IN ORDER reading: the steps happened in this sequence, and other things may have happened in between. Underneath it, when the two disagree, sits the EXACT ORDER reading: the steps happened back to back with nothing in between. When they agree the card says so in one line rather than printing the same figure twice. This exists because the card once labelled its default reading 'any order' while computing the in-order one — a word about the numbers that the numbers did not support. Naming both readings, and printing the second whenever it differs, is what replaced that one wrong word.

The conversion window is clamped to 24 hours

You choose how long someone has to complete the funnel, but the figures use at most one day, and the card says so when your saved window is longer. The reason is the same one that shapes retention: the anonymous visitor identifier is rebuilt from scratch at UTC midnight, so nobody can be followed from Monday into Tuesday. A funnel offering a 7-day window would be offering a number it cannot measure. The window is resolved once and every figure on the card — including the drop-off story — uses that same resolved value.

The device breakdown, and where it goes

A funnel can be broken down by device, and the breakdown is computed under the primary reading only — one reading, so the split adds up. It is worth knowing when it appears: it is requested on the first load of the view, and changing the range or switching funnel in the browser re-runs the funnel without it, so the device clause disappears until the page is loaded afresh.

The drop-off story is deliberately ephemeral

Asking what people did instead of taking the next step produces a story on screen and writes NOTHING: no finding, no saved view, no ledger entry, and no URL that reproduces it. Reload and it is gone. The only writes in the whole feature happen when you press a button in it — create an alert, save a segment — which is the difference between a tool that answers a question and a tool that quietly accumulates state you did not ask for.

The Brief

The home screen, and the only report that decides for itself what to show you.

What it is

The Brief is a ranked feed of findings a deterministic engine computed — this metric moved against its own history, this one crossed a threshold we treat as a floor. Each card carries the numbers, the segments that moved, and pre-filled buttons (create an alert, save a segment, add a note). A sentence over the evidence may be written by a language model, and when there is no model available a template sentence renders instead and every number is unchanged.

What your plan changes about it

Three things, and none of them is access — the Brief is on every tier. First, cadence: on Free, findings appear on a weekly cutoff rather than as they land, and the Monday email follows the same clock. Second, which families of finding are computed for you at all. Third, how many fixes Coruve will follow through verification at once — one a week on Free, five open at a time on Starter, unlimited above.

Signal familyCoversPlan
TrafficVisits, sessions, sources, pagesEvery plan
GoalsGoal conversions and their movementEvery plan
ExperienceFrustration signals — rage clicks, dead clicks, quick backsStarter and up
SpeedReal-user web vitalsStarter and up
CohortRetention and returning-visitor healthStarter and up
MoneyRevenue findingsPro and up
CombinedFindings that join two or three signals into one claim — a page that got slower, is frustrating people, and is costing moneyPro and up

Ask

A question in plain language, answered from your own data.

How it answers

Your question is routed to one of a fixed set of measurements, that measurement is run as an ordinary query, and the answer card prints the rows and the numbers it found. A model writes the headline sentence over that card and chooses which measurement to run — it never invents a figure, because every number on screen came out of the query, and the sentence is checked against the answer before it is shown. The buttons under the answer open the matching report with the same range and filters already applied.

Every plan can ask; the ceiling is what scales

The limit is per project, per rolling day, and it is enforced server-side. The surface tells you how much of it you have spent.

PlanQuestions per day
Free3
Starter50
Pro300
Growth1,500
The headline model is shown the assembled answer — the numbers and row labels already on your screen — and not the question, your project id, your account, or any note you wrote. See Privacy & data handling for the full list.

Settings, alerts and watched segments

11 sections in two groups, selected with ?section=.

The sections

Settings is a surface like any other, so /project/{id}/settings?section=billing is a link you can bookmark. The rail splits in two: seven sections configure THIS PROJECT, four belong to the workspace around it. The five keys that existed before the redesign — project, saved, alerts, team, billing — are unchanged, so every link ever sent still resolves; the other six are new.

Section?section=GroupWhat is therePlan
ProjectprojectProjectThe project's name, domain and timezone, and the install check that confirms the snippet is reporting. General settings only — everything this row used to list has moved to a section of its own.Every plan
TrackingtrackingProjectTraffic exclusions — your own visits, and rules for anyone else — plus dynamic-path masking, journey path rules, and which tracker version your site is measurably running. Bot filtering lives here too, as a statement rather than a switch: known crawlers are dropped before ingest on every project and there is nothing to turn off.Every plan
Privacy & dataprivacyProjectData retention (a statement of your plan's window, not a picker), location granularity, Do Not Track and GPC, and Erase history — a permanent purge of every event before a date you choose.Every plan
NotificationsnotificationsProjectWho gets emailed, the Slack incoming webhook alerts post to for the whole project, and quiet hours — overnight notifications are held and delivered on the first check after they end, never dropped.Every plan
Data & exportexportProjectOne-time export, the scheduled export email, the GA4 and Plausible history importers, and the Stripe and Shopify revenue connections.Every plan (importers Starter and up; revenue connections Pro and up)
API keysapiProjectAPI keys — the ingest key that sends events in, and the read key that reads numbers out — and share links, which are the other way a number leaves this project.Every plan (read keys need Pro)
Danger zonedangerProjectTransfer the project to another owner, or delete it. The two changes that cannot be undone.Every plan
Watching & savedsavedWorkspaceThe ledger of segments, goals, funnels and alerts, with when each was last used. Filters and ad-hoc questions never appear here — those are scratch, and scratch does not accumulate.Every plan (3 saved segments on Free)
AlertsalertsWorkspaceAlert rules and the incidents they opened. Alerts reach you by email and by Slack, and the section below explains what an incident is.Starter and up
TeamteamWorkspaceMembers and invitations.1 member on Free, up to 25 on Growth
BillingbillingWorkspacePlan, usage against your event allowance, and invoices.Every plan
An unrecognised ?section= falls back to Project rather than erroring, the same rule Explore and Outcomes apply to ?view=.

Exporting what you are looking at

Every report exports on every plan including Free, and it exports the report AS FILTERED rather than the whole dataset — since 7D the file honours the same filter operators and the same ?segment= as the screen you were looking at, where before it silently answered the unfiltered question and totalled differently. CSV and JSON are both served by the same route (format=csv is the default; anything that is not exactly json is treated as CSV). The route re-checks the same plan gates as the report itself — the click-map and scroll-map exports refuse below Starter, the revenue export refuses below Pro — so an export cannot be used to walk around a gate.

The read API is a different door, not a different format

This page used to say that reading reports back as JSON was the read API's job. It is not: the export route serves JSON directly, to a person signed in with a browser session. What the read API adds is a KEY — a credential a script can hold, with its own rate limit, its own plan gate (Pro and up) and a stable envelope. Same numbers, two doors: the export is session-authenticated and one file at a time; the API is key-authenticated and built to be called. See the Read API reference for the endpoints.

Alerts and incidents

A line you name in advance, and the record of every time it was crossed.

A rule, and what it can say

An alert watches one metric — visitors, sessions, an event, a goal, or an item from the event catalogue — over an hour or a day, scoped to any filter or saved segment. It can carry up to three conditions combined with ALL or ANY, so 'traffic fell and the goal fell with it' is one alert rather than two. It can also carry up to four notification windows: a stretch of the week with its own threshold, or with no threshold at all, which means do not evaluate here. That is how 'weekends are different' and 'do not measure me during the nightly batch' get said without turning the alert off.

How often it is actually checked

The sweep runs every five minutes. An alert measured over an hour is evaluated on every sweep; an alert measured over a day is evaluated at most every fifteen minutes, because re-reading a whole day sixty times an hour costs a great deal and tells you nothing new. A rule does not fire the first time it crosses — it has to stay crossed for the number of checks you set — and it does not recover on the first check back either, with a small margin the other side of your threshold so a metric sitting exactly on the line does not flap.

An incident, and the numbers frozen inside it

The crossing opens an INCIDENT, and the evidence is measured once, at that moment, and stored on it. Nothing re-reads it afterwards: the email, the Slack message and the drawer in Settings all print the same figures under the words 'as measured at', with the time they were taken. That is the difference between an alert and a report — a report tells you what is true now, an incident tells you what was true when it tripped, and a number that quietly updates itself between the notification and the investigation is the reason the two disagree in every product that lets it happen. Incidents also carry a de-duplication key with a unique index behind it, so two sweeps racing each other produce one incident and one notification rather than two.

'Deviates from usual' says which usual

A threshold you type is unambiguous. A rule that watches for a deviation is not, so it names its own basis rather than leaving you to infer it: either the same weekday in recent weeks, or the trailing seven-day median. The trailing median will not speak until the project has three weeks of history behind it — under that it is a median of noise, and the alert says it is not ready instead of firing on one.

The simulator says 'would have', never 'will'

Before you save a rule you can run it against the last thirty days and see how often it would have fired. The result is labelled 'Simulated before save' and phrased in the past conditional throughout. It is a check on your threshold, not a forecast, and the product refuses to word it as one.

Delivery: email and Slack

Alerts reach you by email and by Slack. Slack is a project-level incoming webhook you paste in under Notifications, which covers every alert on the project; an individual alert can override it with its own. An alert with neither an email recipient nor a webhook is HELD rather than silently discarded, and the reason is recorded on the incident. Quiet hours hold overnight notifications and deliver them on the first check afterwards — held, never dropped.

The buttons in a notification are signed links

Acknowledge and 'mute for 7 days' are the only two actions a notification carries, and both are signed with an HMAC that expires after seven days. Following the link only ever shows a confirmation page — clicking through a link preview, a security scanner or a corporate mail proxy changes nothing, because nothing changes until the form on that page is submitted. The endpoint is rate-limited per address and fails closed: if it cannot check the limit, it refuses.

The digest re-states; it never re-measures

A digest gathers the incidents that already happened and prints each one's frozen summary. It does no arithmetic across them and no new measurement of any of them — even the subject line declines to say 'three alerts', because a count in a subject is a number the reader will check against the body.

What the incident chart can and cannot show you

The small chart in an incident is DAY-GRAIN, always, and its caption says daily. An alert measured over an hour therefore gets a coarser picture than its own rule, and reading a smooth daily line as minute-by-minute would be reading it wrong. It also draws no threshold line at all — not the frozen one and not today's — because the series follows the rule as it is configured NOW, and a rule edited after the fact would otherwise put a marker exactly where the incident never crossed. The frozen numbers above the chart are the record; the chart is context.

Exports

One report, every report, or every report every Monday morning.

Three shapes

A single report as CSV or JSON, or report=all — a zip of every report your plan includes, with a README that explains what each column means and names anything left out, empty, or failed. The zip is always a zip; a format on that request is ignored. Everything obeys the filters and the saved segment you had applied, and the same plan gates as the report on screen.

Or have it arrive on its own

Settings ▸ Data & export will send the bundle by email — weekly, monthly or daily — at 07:00 in the PROJECT's own timezone rather than yours or ours. A sweep runs every 15 minutes and sends whatever has come due — an interval rather than a fixed clock time, precisely because 07:00 means a different instant in every project.

Five rules a scheduled export keeps

Never a partial period: a weekly export covers the last COMPLETE week, so the file never contains a half-finished Monday. Never more than your plan shows on screen. Never stamped as sent when it failed — the record only moves when a run finished, so a failure is retried rather than skipped. One project's failure never stalls the run: each project is attempted on its own and a broken one is counted and stepped over. And a period with nothing in it is recorded as a quiet period, with the stamp written and no email sent — you are not emailed an empty spreadsheet, and the schedule does not spend the next run trying to catch up on a week that had no traffic.

The one hour a year the clock moves

The send time is the period's end plus 7 hours rather than a time asked of the calendar. In a timezone whose spring-forward swallows 07:00, the export arrives an hour later that day instead of the period being skipped. Late once a year beats missing.

Big bundles become a sealed link

Up to 8 MiB the bundle is attached to the email. Over it, the email carries a link instead, and that link is built to be handled carefully: it is single-use and claimed atomically, so a mail scanner that follows it cannot spend it twice; it expires after 24 hours; it is never cached and never indexed; it is rate-limited by address and fails closed; and a token that is unknown, already used, or expired all give the same answer, because telling them apart would tell someone which tokens are real. The link itself is 32 random bytes and only a hash of it is stored, so a leaked database does not hand over anybody's reports.

The ceilings

A bundle you download from the browser is capped at 16 MiB compressed and 64 MiB of CSV before compression; past that the download is refused, with the size in the message and two ways round it. An emailed bundle is bigger — 64 MiB compressed and 256 MiB of CSV — because it is assembled away from the app rather than while you wait. A single request may span at most 366 days, and the exports with no natural top-N of their own — the retention grid in particular — stop at 5,000 rows. A truncated file says it is truncated in the README rather than ending mid-table.

How often you can ask

Exports are rate-limited, per address and per project, at levels far above real use — 60 exports an hour for a project, of which 12 may be whole-plan bundles. A handful of whole-plan bundles can also be building at once across the whole app, so a very busy moment answers "try again in a moment" rather than slowing everybody's dashboard. Hitting either of these by hand means something is looping, not that you are working hard.

Shared dashboards

A read-only page at a URL you can send to somebody with no Coruve account.

What a share link is

A link to a read-only version of your own reports, at /share/ plus a long random token. Exactly 6 views can be shared — overview, acquisition, locations, devices, ai, findings — and a new link starts with Overview alone. The list is an allowlist checked when the link is created AND again every time it is read, so a view added to the product does not become shareable by accident.

Everything you can do to a live link

PAUSE it, and it resolves to a page saying it is paused rather than a 404 — the person you sent it to learns it was switched off, not that it never existed. FREEZE it to a snapshot, and it serves what it froze and reads nothing further: date parameters on a frozen link are ignored rather than refused, and the page states the date it was frozen. BRAND it with a title, an introduction and a logo. Add an EXPIRY date, or a PASSWORD. Allow it to be EMBEDDED in a page of yours. And it prints properly, which is more often what a shared dashboard is for than anyone admits.

Embedding is off until you name the sites

A new link cannot be framed anywhere. Embedding turns on by listing exact origins — one entry per site, no wildcards — and only those may frame it. A password-protected link cannot be embedded at all, since a frame has nowhere honest to ask for the password.

The logo is a URL, never an upload

You give Coruve an https address for your logo and Coruve stores the string. There is no upload path, deliberately: hosting other people's image files is a different product with a different security surface. The address is checked for being a well-formed https URL and nothing further — it is not verified as belonging to your domain, so point it at a file you control and expect it to be fetched by every reader of the page.

The badge, and which way it fails

Shared pages carry a small Coruve badge. Growth removes it, and no other plan does. If the plan cannot be read at that moment — a database hiccup while a page is rendering — the badge STAYS. That is the safe direction for us and the honest one for you: a transient error should never quietly turn a paid feature on for somebody who has not bought it.

'Opens' is not unique viewers

The number beside a link counts opens at most once every 5 minutes per link, which is a deliberate throttle rather than a measurement: it exists so a page left open on a wallboard does not write to the database every few seconds. It does not identify anybody, it does not deduplicate people, and it is never described in the product as unique viewers. Read it as evidence of life, not as an audience.

How many you get

1 on Free, 5 on Starter, unlimited on Pro and Growth. A revoked link does not count against the limit.

The plan gates in one place

Every gate that exists today, and nothing that does not.

What each tier adds

Gates are enforced in the server action, in the export route and in the background worker — never only in the interface. A gate checked where the button is, is a gate that expires the moment a job runs after a downgrade.

CapabilityFreeStarterProGrowth
Brief, Explore, Realtime, Outcomes, Ask, CSV exportYesYesYesYes
Journeys, segmentation, suggested goals & funnelsYesYesYesYes
AI traffic split, sources, trend and methodologyYesYesYesYes
Site HealthYesYesYesYes
Brief cadenceWeeklyDailyDailyDaily
Saved segments3UnlimitedUnlimitedUnlimited
Fixes tracked to a verdict1 / week5 at onceUnlimitedUnlimited
Things Coruve keeps watching05UnlimitedUnlimited
Shared dashboards15UnlimitedUnlimited
Frustration and MapsNoYesYesYes
AI traffic quality layerNoYesYesYes
AlertsNoYesYesYes
Import history from GA4 or PlausibleNoYesYesYes
Impact ledger and combined findingsNoNoYesYes
Revenue report, Stripe and ShopifyNoNoYesYes
Read APINoNoYesYes
Shared dashboards without Coruve brandingNoNoNoYes
Events per month10,000100,0001,000,0005,000,000
Projects1310Unlimited
Funnels325100Unlimited
Data retention30 days365 days730 days1,095 days
Ask questions per day3503001,500

Retention is a deletion promise, not a paywall

Your plan's retention is stamped onto every event as it arrives and enforced by the event store itself. Data past the window is deleted, not hidden — upgrading later does not bring it back. That is also why importing years of history needs Starter or above: a plan that keeps 30 days has nowhere to put them.
Reports explained | Coruve