# Revenue (/revenue)



Revenue turns the dashboard from traffic into business: a Revenue tile beside the other numbers, a
revenue line on the chart, and the pages and sources the money came from.

There are two ways to feed it. Start with the first, move to the second when the number matters.

## The quick way: report a sale from your site [#the-quick-way-report-a-sale-from-your-site]

One call, wherever your site knows a sale happened.

```js
window.peeko?.revenue?.({ amount: 49.99, currency: "USD", id: "order_1234" });
```

`amount` is in the ordinary unit, dollars rather than cents. `currency` is a three letter code. `id`
is your own order reference, optional, and used to avoid counting the same sale twice.

The sale is attributed to the page the call ran on, usually your thank you page, and to the source
that first brought that person to the site.

**A revenue call is not a page view.** That beacon records the sale and returns, so calling it on a
thank you page does not also count a view of that page. The tracker's own page view has already been
sent by then.

Two limits keep a mistake from becoming a wrong dashboard: a single reported sale may not exceed
100,000 in its currency, and a site may report 500 sales a day. Going past either is skipped rather
than stored, and your site settings tell you it happened.

## The accurate way: let Stripe confirm it [#the-accurate-way-let-stripe-confirm-it]

Stripe tells Peeko directly, and the sale is marked verified. Peeko never holds a Stripe API key: the
only credential is the endpoint's signing secret, which lets Peeko check that an event really came
from your account and does nothing else.

1. In your site's settings, open the **Revenue** card and copy the webhook endpoint it shows you.
2. In Stripe, add that endpoint and subscribe it to `checkout.session.completed` and
   `checkout.session.async_payment_succeeded`. The second one is not optional: a delayed payment
   method completes the session unpaid and settles later, and without it those sales never arrive.
3. Paste the signing secret, the value beginning `whsec_`, back into the card.

Only paid sessions are recorded, and every event is checked against the signature and a five minute
timestamp tolerance before anything is written. The same order arriving twice is stored once.

While a signing secret is stored, Peeko **ignores the JavaScript call** on that site, so the two
paths can never both count the same sale. Disconnecting Stripe turns the JavaScript path back on.

### Naming the page and the source of a verified sale [#naming-the-page-and-the-source-of-a-verified-sale]

Stripe's webhook knows about the payment, not about the browser that started it. To connect the two,
pass Peeko's page token into the Checkout session you create.

```js
const token = window.peeko?.token?.() ?? null;
// send `token` to your server, then set it on the Checkout session:
//   metadata: { peeko_t: token }
```

With the token, the sale carries the page and source it came from. Without it, the sale is still
recorded and shows up as **Unattributed**. The token is minted per page view and is good for 48
hours.

## Reading the numbers [#reading-the-numbers]

The Revenue tile shows the total for the range. Under it, a note says where the money came from.

* **Verified by Stripe** when the range holds verified sales.
* **Reported by your site** when it holds only self reported ones.
* Both, when a range straddles the day you connected Stripe: the tile shows the verified total, and
  the note adds the reported amount beside it.

**The two are never added together.** The usual path is to report sales from your site first and
connect Stripe later, so a single range legitimately holds both kinds of record for the same sales.
Adding them would double the money.

**Amounts in different currencies are listed, never converted.** Peeko holds no exchange rates and
will not invent one. The tile shows the currency that earned the most, and the rest are named under
it.

The Revenue tabs on the Pages and Sources cards break the same total down by page and by source.
`Direct` is a visitor with no external referrer; `Unattributed` is a sale Peeko could not tie to a
visit at all.

Three things to expect.

* **Revenue is never filtered.** It is scoped to the range and nothing else, because a sale belongs
  to a whole journey rather than to the one page a filter picked out. The dashboard says so whenever
  a filter is on.
* **Revenue carries no comparison** to the previous window.
* **Refunds are not handled.** Nothing subtracts from a recorded total today, whether the sale was
  reported or verified.

On a [share link](/share-links), revenue is off unless the link's owner turned it on, and even then
it publishes the totals and the breakdowns, never an individual order.

Over [MCP](/mcp), `get_revenue` returns all of it in one payload. Amounts there are in **minor
units**, so `499900` with currency `USD` is $4,999. On [the command line](/cli), `peeko revenue`
prints the same.
