Compose a steering view, without ever seeing a person
A grid builder assembles KPIs, time series, breakdowns and tables into a view made for one need; the view is saved, shared within the space, and varies by role. Behind every widget, a single aggregate query over a closed vocabulary: no free expression, no contact field, no individual row — by construction, not by convention.
A grid builder
Twelve columns, a palette, an editor driven by the catalogue.
- A twelve-column grid, drag-and-drop and resizing; a widget palette; a widget editor that follows the catalogue — family, metrics, dimensions, filters, visualisation — with a live preview.
- Six widgets: KPI (value and variation against the previous period), time series (a single scale, never a double axis), breakdown as bars per dimension, table of the query rows, funnel of a journey’s steps, text.
- Global filters — period, comparison with the previous period — and “recent lists” widgets: latest campaigns, latest workflow runs.
- Readable names: campaign, journey, step, template, list and segment identifiers are rendered by their name, resolved on the values present in the answer only — never an inventory of the space, and never a name invented for a resource that no longer exists.
- A visualisation method rather than endless options: a fixed colour order per entity, a palette validated in light and dark, a legend from two series up, tooltips, a table view always available.
- A widget the role cannot be served displays “unavailable for your role” — never an error, never a misleading zero: a widget’s guard is derived from its query.
A closed catalogue, filtered by role
Every metric, dimension and filter belongs to a published catalogue. What is not in it cannot be asked for.
- Six families: messages (sent, delivered, hard and soft bounces, complaints, unsubscribes, opens, clicks, failures, goals reached, derived rates), journeys (outcomes per step, the third “not measurable” outcome included), contacts (headcounts per status, per list, per segment, per consent purpose, created over the period), events (per name and per day), deliverability (bounces per class, complaints, rates), workflows (runs and failures).
- Dimensions: day, week, month, campaign, journey, step, template, list, segment, variant, event name, bounce class, consent purpose, contact status, delivery route — MTA, Mailjet or Brevo.
- The catalogue returned depends on the class of the key: the console only offers what the key may ask for, and an operating role never gets a dimension that would lead back to a person.
- A query stays within bounds: one family at a time, at most two dimensions of which one of time, ten metrics, two years of period, five thousand rows; the answer is cached for sixty seconds, per space and per key class.
- The totals of a view come from a separate aggregate query, never from summing the rows — which are truncated and already masked. A total rate is the ratio of the totals, and reads “not measurable” when it is not.
What no catalogue entry can reach
- No health-classified attribute; no segment derived from a health criterion — excluded when loading, never in a query plan, and its name does not leave either.
- No nominative column — address, address fingerprint, first name, last name, external identifier, attributes — neither selected nor filtered: a test asserts it on the rendered SQL of every family.
- No free query: no SQL, no expression, no column name accepted over the network.
- Every query is bound to the space of the key that issues it; the cache carries the space and the key class.
Compliance rules live in the query
A widget cannot opt out: they live in the query, not in the display.
- Open and click rates are computed on the consenting population, never on the total sent, and read “not measurable” when that population is zero — never zero: the three-outcome rule applies to every series, not only to journeys.
- Asking for a consent-based rate returns its denominator and numerator as a matter of course, along with the regulatory note — the same constant as on the other statistics. A rate whose base is not shown does not say what it is computed on.
- Every person count goes through the space’s display threshold, whatever the class of the key; message counts are masked for operating roles.
- A rate whose numerator or denominator is masked reads “not measurable”: a division would rebuild the masked count. So does an average over a cohort below the threshold.
- Never an individual datum in a widget: the answer is made of aggregate rows, and every count carries the mark of its threshold.
Compare, aim, annotate
A curve that drops on a Tuesday always raises the same question: what happened that day?
- Period comparison, and goals with coloured thresholds, always accompanied by an icon and a label — never colour alone.
- Annotations on the series, from a closed vocabulary of four kinds: campaign sent (at its effective date), journey version published, workflow run failed — the workflow name, never the error message —, delivery route changed.
- An annotation always carries the name of a resource — never a contact, an address, a headcount — and links to the screen it concerns when there is one.
Save, share, export
A dashboard is a document of the space; the aggregates stay with the API.
- Dashboards saved per space, with an owner, private or space-wide visibility, and a default dashboard per role — which becomes the space’s home page for that role. List, create, duplicate.
- Four starter templates: campaign steering, journeys and conversion, deliverability and reputation, consents and audience. A template is copied into the space on first opening, never imposed.
- Export of a widget as CSV or PNG, and of a dashboard as PDF, in the browser, with no dependency.
- Periodic sending through a workflow — schedule, aggregate query, format, e-mail — that delivers the rows: server-side PDF is set aside, because it would require a browser inside the perimeter to compose what the user’s browser already produces.
The platform view
The operator sees counts, never contacts.
- A separate route, never a flag on the space route: a space key does not see it — not found, never forbidden.
- Three families, counts only: messages, deliverability, workflows. Never the contacts family — those are people —, never a journey outcome nor a space’s event log.
- Dimensions: day, week, month, space, delivery route, bounce class. No campaign, journey, template, list or segment name: the only name returned is that of a space.
- The platform display threshold applies to every row and every total; five hundred rows at most — a platform view is read, not exported.
- Every query writes a log entry naming the spaces actually read and the metrics requested — never a value.
- No builder on the platform side: the technical tab stays a fixed page, and there are no platform annotations.