Tempio Docs
Metrics

Metrics

Every number on a Tempio surface comes from one table of daily counts, and every rate comes from arithmetic done at the moment you look. Nothing that can be computed is stored, and nothing that is stored is a rate.

What is stored

One row per entity per day. The grain is the workspace, the connection, the platform, the ad account, the entity level, the entity, the date and the breakdown — so a campaign's Tuesday is exactly one row, and a re-sync of Tuesday rewrites that row rather than adding a second one.

ColumnWhat it is
spendInteger minor units of the account's currency
impressionsA count
reachPeople reached, as the platform reported them for that day — or empty where the platform does not report it
clicksA count
conversionsA count, which platforms can report fractionally
conversionValueInteger minor units of the account's currency
currencyThe account's own code, stamped on the row

That is the whole of it. There is no stored CTR, no stored ROAS, no stored blended anything.

Reach is the one column that is not a plain count. Platforms report it de-duplicated: one person who saw an ad on Monday and again on Tuesday is one person across the week and two daily rows. Anything adding reach up over a range is adding daily reach, and every surface that shows it says so. Where a platform does not report reach at all the column is empty rather than zero — "did not report" and "reached nobody" are different facts and are shown differently.

What is computed

Five ratios, worked out when a page is drawn or a tool answers.

RatioHow
CTRclicks ÷ impressions
CPCspend ÷ clicks
CPM(spend ÷ impressions) × 1000
CPAspend ÷ conversions
ROASconversion value ÷ spend

The same function computes them everywhere — the dashboard tile, the campaign table, the account brief and the MCP result all divide the same way, so they cannot disagree about what CPA means.

A zero denominator gives no answer, not a zero. An account with no conversions yet has no cost per conversion; the value is null, and it renders as —. This is the rule most worth knowing about, because a zero would say something false and cheerful: that conversions were free. An agent reading a Tempio result is told the same thing — a null ratio is undefined, never nought.

Storing ratios would let them drift from the counts beneath them, which is why they are not stored. Recomputing them costs nothing next to a page's other work.

Money

Money is an integer in the ad account's own minor units, with the currency stamped beside it. Never a float, never a fraction of a cent, never a number whose denomination you have to infer.

How many minor units make a major one is the currency's business, not a universal hundred:

Currency groupMinor units per major
Yen, won, and the other zero-decimal codes1 — ¥1,500 is 1500
Most currencies100 — $15.00 is 1500
Dinars and other three-decimal codes1000 — KD 1.234 is 1234

An unfamiliar code is treated as two decimals, which is both the majority and the least damaging way to be wrong. Every form on the ads surface parses a typed amount against the currency of the account that owns the row it is editing — never against a currency the form supplied — and every draft payload is stamped with that account's code on the way in.

Several currencies at once

A dashboard covering a US account and a Japanese one has a problem no rounding solves: minor units are not comparable across currencies. ¥1,500,000 has more digits than $12,000 and is less money.

Tempio handles that in one direction only — it says so.

  • One currency in scope. Nothing is converted. The answer is exact and the figure is stated in that currency.
  • Several. The totals are converted through published rates into whichever currency carries the most spend, compared honestly rather than by digit count, and the result is labelled an estimate with the date of the oldest rate the conversion leaned on. A stale leg cannot hide behind a fresh one.
  • Several, and a rate is missing. Nothing is invented. A blended total that cannot be reached is refused rather than estimated, and a list that cannot be ranked comparably is returned in its raw order with that fact attached — a raw order across currencies is not a ranking, and every surface showing one says so.

Two windows compared against each other are pinned to the same currency, so a period-over-period change is never one currency divided by another.

Rates feed a labelled estimate and nothing else. No guardrail converts, no budget converts, and no cap is compared across currencies.

Where the numbers come from

Each sync pulls the days the platform is still willing to restate — 28 on Meta, 30 on Google, 14 on TikTok — so late conversions and platform corrections land as corrections rather than as gaps. Once a week the full ninety days are re-read. A sync that rewrites a large amount of already-stored history marks the connection restated, which is worth knowing before you conclude last month moved on its own. Connections has the sync behaviour.

Today is always partly filled in. A range ending today is reporting a day the platform has not finished counting, which is why comparisons default to complete days and why a tool result states the range it actually covers.

Reading them elsewhere

The dashboard shows the workspace blended; Campaigns shows them per campaign, ad group and ad; the account brief summarises ninety days per account. Over MCP, get_metrics and get_campaign_metrics answer the same numbers, and every result carries a report block stating the currency the answer is in — null when the scope spans currencies — the timezone the dates are in, the range, the entity level, and whether the scope is the rows returned or all of them. Read that block before comparing two results: two answers in two currencies are not two numbers you may subtract.