Surevisible
Semantic layer

A session means the same thing everywhere

Every source normalises into one schema on the way in, so comparing two brands is valid by construction rather than by whoever built the spreadsheet remembering to make it so.

The problem

GA4 counts a session one way, Search Console counts a click another, and neither will tell you what happened across both. Put two brands side by side and you are comparing two definitions, not two numbers, and nothing in either tool warns you.

What we mean

A semantic layer sits between the warehouse and everything that reads it. Measures and dimensions are declared once, with the source each one comes from and the grain it is valid at. Nothing, not a chart, not the chat, not the API: can ask for a number the layer has not defined.

1

definition of a session, across every brand

How it works

Start to answer

  1. 01

    Sources land raw

    Each connector writes what its provider actually returned, unmodified, so the original is always recoverable.

  2. 02

    Normalised on the way in

    Day boundaries, channel names, URL shapes and country codes are reconciled at ingest rather than at read time.

  3. 03

    Declared as measures

    Each measure names its source, its aggregation and the dimensions it is valid against.

  4. 04

    Everything reads the layer

    Charts, chat, the API and the MCP server all go through it. There is no second path to the numbers.

Before and after

What actually changes

The monthly comparison

Before

You export two properties, notice the totals disagree, and spend an hour deciding which one to trust before you can even start the analysis.

After

Both brands are already on the same axis. The comparison is the first thing you do, not the last.

The number nobody can reproduce

Before

A figure in last quarter's deck cannot be rebuilt because nobody recorded which filters were applied.

After

Every chart is a saved query. Open it and you can see exactly what was asked.

Declared, not inferred

The schema is a contract, not a convention.

  • Every measure names its source
  • Dimensions declare the grain they are valid at
  • Invalid combinations are refused, not silently averaged

Readable by machines

The same definitions the UI uses are available over HTTP and MCP.

  • GET /api/schema returns the whole layer
  • The MCP server exposes it as get_metric_schema
  • Clients cannot invent a metric name

Honest about gaps

Where a source has not reported, the layer says so.

  • Missing days are absent, not zero
  • Revised days are re-pulled rather than trusted once
  • Partial windows are labelled as partial

Why the layer sits below the chat

The model chooses the question. The schema decides what the numbers mean. Keeping that split is what makes an AI answer auditable: the model cannot invent a metric, only select from ones that already have a definition, and the query it selected is shown alongside the answer.

What it refuses to do

It will not average a rate across brands of different sizes and present the result as a portfolio figure, and it will not join two sources at a grain where the join is not valid. Both are easy to render and neither means anything.

In short

Comparisons between brands stop being an act of faith. The definitions are applied once, at ingest, and everything downstream inherits them.

See the whole brand

Search, analytics, ads, revenue, CRM and support, pulled into one view per brand and kept current. Connect the first source in a few minutes.