Methodology

Every ranked or counted surface on this site, with the exact rule it follows ยท last updated 2026-08-28

Each ranking and counting surface on this site follows a printed rule, stated where the number appears. This page collects those rules in one place - what each surface measures, how it is counted, and what it cannot prove - so a skeptical reader can check the site against its own claims. If the site's behaviour and this page ever disagree, one of them is wrong - tell us and we will fix it and say so.

The ranked block: "Most opened - last 7 days"

The ranked block at the top of the homepage orders listings by counted opens of each listing's outbound link. A counted open is a qualifying request to the signed outbound link on a listing's profile, recorded on our servers at the moment of the hop. The exclusions below are a counting rule: they remove the automated and self-inflicted traffic we can recognise, and they are not proof that a person viewed the destination. A request counts only when all of the following hold:

The window is the last 7 UTC dates - today and the six before it. A listing appears in the ranked block only after it clears the printed floor: at least 3 counted opens spread over at least 2 of those UTC days. Below the floor, a catalogue listing stays in the daily rotation; a listing accepted after the catalogue was last built appears there once it is rebuilt. Ties are ordered by case-insensitive listing name, then by the listing's address on this site; given the per-listing counts - each listing's receipt publishes its own - the printed rule determines the exact order. The number is computed from the stored events at read time - there is no stored total anyone could quietly edit.

The ranked block and the daily rotation are also readable as data, with this rule and these numbers in machine-readable form, at /api/v1/arena - one of the public reads listed at /api/v1.

The daily rotation

Listings that have not cleared the ranking floor are reordered once per UTC day. Each row's place is a deterministic function of exactly two inputs: the UTC date, which the server prints on the page, and the row's own link. That means:

The rotation is pure display. Nothing about the visitor is read or recorded to produce it.

Paid placement is a separate, labelled surface: a fixed set of sponsor seats at fixed public prices, the same for everyone, printed on the offer. A sponsored seat is labelled as sponsored everywhere it appears, and sponsored links carry rel="sponsored noopener noreferrer". A seat can only be bought for a listing whose domain the buyer has proved they control.

Paid spend is never an input to any organic order. What a sponsor buys is the labelled placement and a public receipt of the clicks counted during its term - never a position in the ranked block, and never a promised quantity of clicks. Money can buy exposure; money cannot buy truth.

Every placement currently live is published in the machine-readable disclosure feed at /api/placements: which seat, for which listing, the term, and the published price. A seat given away without payment is disclosed there as complimentary - it is still a labelled placement, but calling it sold would be untrue.

The click receipt

Every published listing has a public receipt of the traffic this site sent it: /api/clicks/<listing>, and the same truth in a versioned envelope at /api/v1/clicks/<listing> (a live example). Every event is graded when it is recorded, and the grade vocabulary is closed:

The last three were added on 2026-08-28 after this site's own ledger was measured against them. One visitor took 31 distinct listings in 1.8 seconds on 2026-08-26, and another took 8 in 1.7 seconds on 2026-08-27; every other visitor that week opened one or two. Those two clients had built the entire ranked block. The old rule - one counted open per visitor, per listing, per UTC day - is exactly right for repeat visits to one listing and said nothing at all about one visitor touching every listing once. It is the failure this site exists to point at, found in our own numbers, and it is written here rather than fixed quietly. Counts recorded before that date were graded under the older rule and are not comparable with counts after it.

Deduplication is the same everywhere: at most one counted click per visitor, per listing, per UTC day. Each paid term on a receipt reports the clicks counted inside that term's own start and end - a link minted for a seat keeps working after the seat ends, and those later clicks are real, but they are not what the buyer paid for and are not attributed to the term. The versioned receipt publishes the full grade-by-origin table with explicit zeroes, so "no such traffic" and "not reported" can never be confused.

Movement receipts

When a counted, organic, signed open changes a listing's standing in the ranked block - it clears the floor rule, or it moves up past another listing - a movement receipt is written at that moment: a permanent page at /r/<number> and the same truth in a versioned envelope at /api/v1/receipts/<number>. The receipt stores what was true when it was minted - the listing's name, the position it left, the position it reached, the listings it passed, its counted opens, the exact 7-day window, and the ranking rule's version - and is never updated afterwards. A receipt is evidence of a moment, so it must not follow later renames or recomputation.

What cannot mint one is as fixed as what can:

Each receipt has its own link preview image at /og/r/<number>.png, and it is the only image on this site that carries a number. Every other card here is forbidden from carrying a position or a count, for a specific reason: once a platform has scraped a card, that copy lives on the platform's servers and cannot be corrected, and a number that cannot be corrected is not a checkable one. That rule bans numbers that decay. A receipt's numbers cannot decay - the row is written once, and the image repeats a single past instant rather than describing the present, so it is as true later as it was when it was made. The image is composed when it is asked for, from the stored row only.

Receipts are minted only for upward movement, because the receipt is the moved listing's artifact: the event that made one listing pass another mints one receipt, which names the listings that were passed. A receipt about a listing that is later taken down stops resolving, like every other surface that would otherwise keep naming it. The events behind a receipt roll into the same hourly roots as every other count, so a receipt's arithmetic can be checked against the proof layer below.

Corrections

When a counting rule is found to be wrong, the events already recorded under it have to be put right, and there is exactly one way this site is allowed to do that: a correction is a new row, never an edit. The click ledger is append-only. That is the basis of every claim made here against other people's numbers, and a site that quietly rewrote its own history to look better would have given up the argument. So the original events stay exactly as they were recorded, and each correction is a separate, dated row naming the event it corrects, the reason, and the version of the rule that produced it.

Every counted surface on this site nets corrections out - the ranked block, each listing's receipt, the profile pages and the public API all read the same rule, so a corrected event cannot survive in one number while disappearing from another. A correction that later proves wrong is reversed by appending a reversal, not by removing anything, and the reversal is visible too.

A correction is a public event: it moves published numbers, so it appears in the build log with its date, its reason and how many events it covered. A movement receipt whose causing open was later corrected keeps every number it was written with - it is a true record of what this site counted at that instant - and says on its face that the ledger behind it has since been corrected.

The first correction, 2026-08-28. The sweep rules described above were applied backwards to the events recorded before they existed, and only those rules: the same two-second burst rule and ten-listing daily rule, replayed in time order against the older events. No case was judged individually, so the result can be recomputed by anyone with the same rule and the same events. It corrected the counted opens produced by the two sweeping clients, which had been the bulk of the traffic behind the ranked block.

The proof layer: hourly roots

The click ledger is append-only, but that is a promise about our own behaviour, and this product exists because operator promises about traffic numbers are worthless. So each closed UTC hour gets a Merkle root over that hour's aggregate counts, published at /api/v1/roots. Roots are frozen lazily: a read of the roots API computes every closed hour after the last stored root, oldest first, in bounded batches - and once a root is stored, it is never updated. A root deleted from the middle is not silently recomputed; the verifier's gap check is what exposes it.

The leaf, in one sentence: one leaf per (hour, listing, grade, origin, signed-flag) combination with its event count, serialized as hour|entity_id|grade|placement_origin|signed|count. Leaves are sorted by the UTF-8 byte sequence of that string and hashed with SHA-256; pairs of digests are concatenated and hashed up the tree; an odd node is promoted unchanged; an hour with no events has the SHA-256 of the empty string as its root. The tree covers aggregate counts only - no pseudonyms, no timestamps finer than the hour, nothing about any visitor. Excluded traffic is in the tree as firmly as counted traffic, so reclassifying an event's exclusion reason after the fact moves two leaf counts and changes the root.

To check an hour, read /api/v1/roots/<hour>: it returns the frozen root beside the current leaf aggregates, which is enough to recompute the root from the response alone. If a change since the freeze alters that hour's aggregate counts - an event edited into a different grade or origin, inserted, or deleted - recomputation yields a different value, and the mismatch is visible to anyone holding the published root. The tree commits to those aggregates only, not to every field of every event: a rewrite that leaves every leaf count intact is outside what a root can catch. We also maintain a standalone verifier - plain Python, standard library only - that recomputes every stored hour written under the published algorithm (a row claiming a different algorithm is reported, not judged) directly from a database export and additionally checks that every event carries a well-formed hour, that no event predates the first rooted hour, and that no hour between the first and last stored root is missing a root.

Each stored root also carries an Ed25519 signature, made with a key that is never stored in the database, over the string tl-roots-sig-v1|algo|hour|root|prev_root - where prev_root is the previous stored hour's root, or the literal genesis for the first. The public key, the message format, and each row's signature and predecessor root are printed in the API responses. A root is signed once, at the moment it is frozen, and never afterwards: there is no path anywhere in this site that signs a root already stored, so a rewritten row cannot be handed back to the key for a fresh signature. Because every signature binds its predecessor, the signed rows form a chain: rewriting a stored root, deleting the first row, or deleting a row from the middle breaks a signature that database access alone cannot re-create. Signing began at a fixed hour, printed in the API as sig_signing_began_at_hour; every root from that hour on must carry a signature, so removing signatures from recent rows fails verification rather than passing as history that predates signing. The standalone verifier checks every signature and every link against the public key, offline.

What this does not prove yet, stated plainly: the signing key lives in the worker, the worker signs whatever the freeze computes, and it remembers nothing outside the database. So an operator who deletes a run of the newest signed rows and lets the next freeze pass re-sign a rewritten tail produces a chain the verifier alone cannot fault. What the signature changes is what your own record is worth: any reader who saves one signed row holds proof, because we cannot later claim that row was never published - and since each signature binds the previous root, one saved row pins every hour up to it, not just its own. The verifier accepts such a recorded row and fails if the table no longer matches it. Closing the remaining seam without any reader's help means putting the roots somewhere we do not control, which is what the next section is.

External timestamps: every root into Bitcoin

A signature proves who wrote a root. It cannot prove when, and nothing inside a system its operator controls ever can - a log file in our own repository is a note to self. So every root is also timestamped by parties who have nothing to gain from our numbers, using OpenTimestamps: free public calendar servers that batch submissions together and commit the batch into a Bitcoin transaction. The resulting proof chains our root to a block header that thousands of unrelated machines already agree on. No account, no key and no payment is involved on our side.

What gets timestamped is not the bare root. Every hour with no events has the same root - the SHA-256 of the empty string - so a proof over the bare value could not tell one empty hour from another. The timestamped value is the SHA-256 of tl-roots-anchor-v1|algo|hour| followed by the 32 raw bytes of the root, followed by |prev_root. The proof file still begins with this hour's published root, because the three steps that build that statement - prepend, append, SHA-256 - are themselves OpenTimestamps operations, recorded ahead of the calendar's own. Open a proof and the first 32 bytes are the root you read from the API, with the hour and the predecessor root sitting right after it in readable ASCII.

A receipt is not an anchor, and we will not print it as one. A calendar answers a submission in milliseconds with a pending receipt: one server's promise that the value is queued. Only hours later does the batch reach a block. Four separate words are used and never blurred:

What "anchored" proves, exactly: that some party committed to that exact statement - this root, under this hour, chained to this predecessor - no later than that Bitcoin block. It does not prove that the root was served publicly at the time, that it was frozen when its label says, or that the events underneath it are genuine. An operator who rewrote an hour before anchoring it would anchor the rewrite just as happily; the anchor's power is against changes made after a proof exists. And the block header is corroborated, not validated: we query public explorer APIs and require them to agree, we do not run a Bitcoin node and check the work. The honest label is Bitcoin-attested, corroborated by independent public explorer APIs; not locally node-verified.

The proofs are published as bytes, not as a status word: /api/v1/roots/<hour>/anchors returns every stored proof for an hour, plus the SHA-256 of the file it was copied from. Download one, run its operations from the root the API published, and check the block yourself - you need nothing from us but the bytes. Deliberately absent is a field saying "anchored: true": a flag written by the operator into the operator's own database, read back out of that same database, would be our word about our own honesty. The state the API returns is the calendar's word for what the proof contains, not our verdict on it.

Our own nightly job fails if a root older than 36 hours has no receipt from at least two independent calendar operators - independent by operator, not by hostname, since one party can run several calendars - or if a receipt has still not reached a block after a week. A late anchor is recorded as late permanently: a catch-up run closes the gap, it does not undo the miss. Roots frozen before external timestamping began were anchored after the fact, and their proofs establish that the value existed no later than the attesting block, not that it was fixed at the close of the hour it names. Roots from then on are anchored on the schedule above.

Destination screening

Every published listing's registrable destination domain is screened against the URLhaus active hostfile - a public list of hosts currently distributing malware. Checks run when the operator reads or forces the screening state - there is no scheduler - in batches of up to 15: never-checked listings first, then listings whose domain changed since their last check, then oldest first. A listing becomes due again once its last check is older than 24 hours; due means eligible for the next batch, not checked at that instant. A domain is flagged when it is listed itself or when any listed host sits under it; the match never runs the wider way.

Which listings are offered to search engines

Not every published listing is handed to a search engine. A listing's profile is offered for indexing, and appears in sitemap.xml, once it clears one of three bars: a person put it in the seed catalogue, or its owner proved the domain and claimed it, or it has earned at least one counted organic open. A listing that clears none of them is served with noindex,follow and left out of the sitemap.

The launch gate: how visits to this site are counted

Whether this site gets built past its trial is decided by one number: 200 qualified sessions within 7 days of the launch being published. The threshold and the window were written down before any traffic arrived. A number decided afterwards is one you can negotiate with, so this one is stated here rather than reported later.

A qualified session is a distinct (UTC day, visitor) pair that survives every exclusion below and is confirmed by a same-origin request the rendered page makes for itself. The confirmation step exists because a request arriving is not the same as a page being shown to somebody. Visitors browsing with scripting turned off, and several people sharing one network address, are undercounted rather than overcounted - the error runs against the number that decides in our favour, deliberately.

Excluded before counting, with the reason stored on the event itself: recognised automated traffic, our own operator traffic, requests that are not a page load (HEAD requests and prefetches), and test traffic. Each exclusion reason is counted and reported separately, never silently dropped.

Counting starts when the launch is published, not when the site is deployed

A domain is announced to the public certificate transparency logs the moment it is issued a TLS certificate, and there are scanners watching those logs specifically to find new domains. Some of them send an ordinary browser identification string, so a filter that matches known crawler strings sees nothing unusual and counts them as people.

That is not hypothetical here. This site was reached four times by visitors that passed every filter, on 2026-08-24 between 08:01:33 and 08:12:41 UTC, before its launch had been announced anywhere and before a single person had been told it existed. Left alone, background noise like that accumulates: given enough pre-launch days a 200-session gate drifts toward passing on its own, and the trial would be "passed" by a test nobody took.

So the count does not start at deployment. It starts at an explicit publication moment: one record, written when the first launch post goes out, holding the time it went out. Every gate query filters to events at or after that time. Anything before it is reported separately as pre-publication noise and never enters the total. Before that record exists the gate does not report a number at all - it says in plain words that nothing has been published yet, because a number shown there would look like a result.

The excluded pre-publication count stays visible rather than being quietly discarded. Hiding it would be the same failure in a politer form.


The numbers described here are also printed where they are made: each listing's profile shows its own counted opens beside the signed outbound link, and the homepage states the ranked block's rule above the block itself. Questions, corrections, or a claim you think this page overstates: use the report page - an accepted notice gets a reference number and an answer-by date, and decisions on it are made by a person.


Typefaces: Unbounded, Geist, Geist Mono, Bricolage Grotesque and Schibsted Grotesk, used under the SIL Open Font License 1.1 (license text).