frameworkmonthly-funnel-proof · v31099:cursor-joseph-os2026-09-01served from databaseAll documents

Monthly funnel proof — trustworthy stats for paying customers

Monthly funnel proof — what a paying customer can trust

Goal. At month-end, each paying customer gets a short report that answers one question: did the funnel we run for you send people into your business? They keep the subscription because the number is something they could argue from their own books, not because a dashboard looks busy.

This is not website analytics. Google Analytics, Clarity, and PostHog are optional working tools. They are never the number on this report.

How every site must write the underlying events, including phone and map taps, and how to count only real people: https://projects.jbnx.io/framework/tracking-doctrine (directive v64 / R13).


The trust rule

A figure is allowed on the customer report only if all four are true:

  1. It is an outcome they already recognize — a booking, signup, email captured, paid invoice, completed intake. Not “sessions,” “engagement,” or “unique visitors.”
  2. It is counted from a system they own or we operate for them — their booking table, their user table, their payment ledger, or a first-party hit log on their hostname. Not a third-party modeled conversion.
  3. The definition is printed on the page and is the same every month.
  4. The month is frozen. On the 1st we snapshot last month. Later corrections do not rewrite the PDF they already received.

If a number fails any test, it can live in an internal ops view. It does not go on the customer report.


What never goes on the report (or on /insights)

These are not customers. Counting them is how we faked a call on a page that had just gone live.

Do not verify a ship by curling /go/call. That 302s and must not increment the call number. Verify GET /insights → 200, host-scoped, and that a scripted tap does not move the number.

place=header and place=page are real UI. They are not test labels.


One funnel per product, named in English

Nothing is reported until the product has this table filled (Marketing plan P0.5 — still open for CipherDeck and NodeDough North Stars).

StagePlain name on the reportSource of truthExample
1People reached the pageFirst-party request log on their host (edge or app). Path allow-list agreed in writing. Real people only.GET /book 200s from a browser
2People started the actionSame host: form view, “start booking,” “create account” — one event, named.POST /book/start or click on #start
3People finishedTheir database row, not a thank-you pixel.Booking row status=confirmed; user created_at; payment paid
4People came back / paid againSame ledger, returning key (email/user_id/customer_id) seen in a prior month.Second booking, renewal

North Star = stage 3 (or 4 if the subscription is their subscription, not ours). Stage 1 and 2 exist only to show the pipe. The headline is finished outcomes.

Vanity that never appears as a headline: pageviews, uniques, bounce, time on site, heatmaps, recordings, “Direct traffic,” social likes.


What we claim vs what we do not

Tagged (we claim). The visitor arrived with a UTM or click-id that we put on work we did this month or still in window (utm_source/utm_campaign from the agreed scheme). The finished outcome is joined to that first-hop tag, stored on their session or lead row when they landed — not guessed at checkout.

Unattributed (we show, we do not claim). Direct, bookmarks, stripped referrers, organic they already had, “someone typed the URL.” These go in a second column so the customer sees the whole business, and so we cannot be accused of hiding it — but we do not take credit.

Modeled / estimated (we never show as fact). Google’s consent-mode estimates, sampled explorations, “likely from Instagram.” If we only have a pixel and not their booking row, that conversion is omitted.

Join rule, printed every month:

A finished outcome is tagged only when the landing request that started that person’s visit carried our tag, or their record already stored that tag from an earlier landing in the attribution window (default 30 days). Otherwise it is unattributed.

That is last-touch on our tags only. It is weaker than a full multi-touch model and stronger than a screenshot. Customers can re-count it.


The monthly pack (one page + appendix)

Delivered on the 1st for the previous calendar month, in the customer’s billing login (they already pay there) and as a file they can keep.

Page 1 — the argument

  1. Product name, month, North Star (one sentence).
  2. Finished outcomes this month vs last month vs the target we agreed.
  3. Funnel: reached → started → finished → returned. Counts and conversion rates. Same four rows every month.
  4. Split: tagged by us / unattributed. We only narrate the tagged column.
  5. What we shipped this month toward the funnel (customer-readable work lines they already have on the invoice — hours and outcomes, no vendor names).
  6. One paragraph: “How we count” (paste the join rule). One line: “This month is frozen as of <timestamp>.” One line: bots, local testers, Insights-page views, and scripted taps are excluded.

Appendix (optional, same file)

If finished outcomes are zero, the report still goes out. Empty is honest. A missing report is what kills trust.


Where the data comes from (estate)

You already have the bones. Do not add Google as the source of truth.

NeedAlready existsGap
Funnel stages + targetsmarketing.funnelsNorth Stars not set (P0.5)
Period metricsmarketing.metricsNeed month-grain snapshot table
Hit / visitFirst-party hits / events on each host + /insightsBeacon is geo only; funnel is the host log
Finished outcomesEach product’s own DB (booking, users, payments)Must be read into the report, not re-counted by a pixel
Customer deliverybill.jbnx.io work logNo monthly proof PDF/page yet
UTM on every outboundMarketing principle §2.1Not enforced on all sites

Minimum trustworthy pipe:

their site, first real request  →  store host, path, utm_*, click id, sid
their app, finished row         →  copy sid/utm onto the lead/booking/payment
1st of month                    →  freeze last month into report_snapshots
customer login                  →  render that snapshot only

Third-party tools (GA4, Clarity, PostHog) may be installed for internal debugging. If their number disagrees with the snapshot, the snapshot wins and we say so.


What we tell the customer once, then never change

That is how the report keeps the subscription: it is boring, repeatable, and checkable. A prettier chart that they cannot reconcile is how you lose them.


First products

Marketing plan already said: first campaigns CipherDeck + NodeDough; FedM8 data permanently out of this system. Same here.

Until P0.5 names a North Star per product, there is nothing honest to put on page 1. The first CEO input is still one line each: what finished action is “a customer entered the business” this quarter.