Methodology

Every number is a range, and here is the formula

We never show a single spend figure. Every estimate is a low to high range, a confidence label, and the public method below. Nothing is blurred on any plan.

Data sources

Whosprinting only reads publicly available advertising data. Today that means the Meta Ad Library, which publishes every active ad in the EU together with EU reach figures required by the Digital Services Act. We re-check active ads about once a day, and Free plan data is served with a 7-day delay.

  • Ad creatives are never re-hosted. Thumbnails link to the original ad in the Meta Ad Library.
  • The landing page each ad sends to is opened at most once a day: we take one screenshot of it and read the offer and price it states. We stop at that page.
  • Our crawler clicks nothing and submits nothing, so no form of yours ever receives a fake lead or a fake order from us. It identifies itself as WhosprintingBot, honours robots.txt, and waits at least a second between two pages on your site.
  • Video transcripts are generated from the public creative and stored as text only.
  • No login-gated, private or personal data is collected. Advertisers can opt out from the footer of every page.

Reach

EU reach is the number Meta publishes for each ad: unique accounts that saw the ad in the EU over its lifetime. For a creator we add up the published reach of every ad they have run, so a person who saw two of their ads is counted twice. Reach is the only input we do not estimate, so it carries no range of its own.

It is also the only reach Meta publishes. The figure exists because the Digital Services Act requires it, and that requirement covers the European Union. An advertiser delivering only in the United States, Canada or anywhere else outside it has no published reach, so we show a dash rather than a number: their spend is not waiting to be calculated, it cannot be. We would rather say so than print an estimate built on nothing.

The United Kingdom is outside it too, which surprises people. Of the ads we hold that run in the UK and nowhere else, none carries a reach figure; add a single EU country to the same campaign and 96% of them do. So a British advertiser can show years of reach from campaigns that once ran across Europe and no spend at all this month, because what they are running today is aimed at Britain.

Reach is counted over every ad an advertiser has run, not over a window: Meta publishes it for the lifetime of an ad, so there is no monthly figure to give. Spend is the last 30 days of live ads. The two cards therefore count different things, and each says which.

Spend range

Spend is impressions multiplied by the cost per thousand impressions. Impressions come from reach times frequency, and the CPM depends on the niche. Both multipliers are ranges, so the result is a range.

30-day reach = EU reach ÷ days run × min(days run, 30)
spend low = 30-day reach × 1.5 × niche CPM low ÷ 1,000
spend high = 30-day reach × 2.5 × niche CPM high ÷ 1,000
Frequency and CPM are published market assumptions for EU direct-response advertising, not figures we measure. We do not buy media, so we do not observe what anyone paid.
InputRange usedWhere it comes from
EU reachPublished per adMeta Ad Library, DSA transparency
Window30 days, or the ad's age if youngerReach is published for the ad's whole life, so we prorate it
Frequency1.5 to 2.5Impressions per reached account, direct-response EU campaigns
Niche CPM€6 to €18A band per niche inside this span, 18-niche taxonomy

An advertiser we have only just found has no niche yet, because the niche is read from the ad text after the first crawl. Until it has one, the full €6 to €18 band applies, so the range is wider and the confidence is medium at best. We would rather show you a wide honest range than a narrow flattering one. The same is true of an advertiser we could not place: their niche reads Other and they keep the full band.

Within that span a competitive niche carries a higher CPM than a broad consumer one: finance and real estate sit at the top, pets and gardening at the bottom, business and entrepreneurship at €10 to €12. That ordering is a market assumption we are stating openly, not a measurement, and it is the only thing about your niche that changes the number.

Traffic range

Funnel traffic is the number of clicks the ads running to a funnel are likely to send to its first page. It continues the spend chain rather than starting a new one: the same reach, the same frequency, the same 30-day window, with a click-through range on the end.

30-day reach = EU reach ÷ days run × min(days run, 30)
visits low = 30-day reach × 1.5 × 0.6%
visits high = 30-day reach × 2.5 × 1.4%
The click-through range is a published market assumption for EU direct-response advertising, not a figure we measure. We do not run these ads and we do not own these landing pages, so we have never observed a click. The span is wide because a video ad and a static image ad do not click through at the same rate, and we cannot know which of the two a funnel is being pushed with.

Only ads that are running count, for the same reason they are the only ones that count towards spend: the Ad Library publishes the day an ad started and never the day it stopped, so an ad that has finished has an unknown number of days inside the window and we leave it out rather than guess. A funnel with nothing running therefore shows no traffic figure at all. That is not a gap in our data, it is what the funnel is doing: nobody is sending it paid traffic this month.

A funnel can also carry published reach on some of its ads and none on others, because the disclosure covers EU delivery only. We add up the ads that publish it and no others, so such a funnel reads low rather than being scaled up by a guess about the ads we cannot see.

About one in five of the funnels with ads running is running ads Meta discloses nothing about, so no reach-based figure can ever exist for them. Rather than leave that at “no data”, we fitted a model for those funnels on the ones where the answer is known, from signals every funnel has: how many ads point at it, how many are running, how long they have been running, how big the advertiser is, and how many of its pages we have captured. Then we held a fifth of the measured funnels back, predicted them from that fit and measured how wrong it was.

It is not good enough to show you. The fit explains about a quarter of the variation on funnels it had not seen, and the median one comes out roughly six times off. For the range to be right four times in five it would have to run from a twenty-fifth of the estimate to twenty-five times it, which spans every funnel in our corpus and therefore describes none of them. So those funnels read “not measured”, and they will keep reading it until there is a signal worth fitting on. The number of ads somebody runs turns out to say very little about how much they spend on each one, and that is a fact about advertising rather than a gap we can close by trying harder.

Confidence labels

The dot next to every range tells you how tight it is. The label is decided by how much we actually observed, not by how big the number is.

LabelToleranceWhen it applies
High±20%Ad older than 14 days, reach published, niche known
Medium±40%Ad between 7 and 14 days old, or niche not yet known (full €6 to €18 CPM band)
Low±70%Ad younger than 7 days, reach not published, or fewer than 5 ads with published reach in the sample

Hover any dot in the product to see the label and this tolerance. The tooltip always links back here. See it applied on the creators leaderboard.

Signals and trends

The winner score ranks an ad from 0 to 100 on four things: how long it has been running (35), how many ad ids carry the same creative (30), how many people it reached (25), and whether that reach is still growing (10). Longevity leads because it is the one signal that cannot be bought in a day: nobody keeps paying for an ad that does not work. Those weights are our judgement, not a measurement. The line beside a score says which of the four earned the largest share of it for that ad, which is often not longevity: an ad running a fortnight in thirty two copies is being judged on the copies.

A signal we cannot see for a particular ad is removed from its total rather than counted as zero, because reach is published for EU delivery only and a US campaign should not be marked down for it. The consequence is stated here rather than hidden: a score is out of the signals available for that ad, so an ad with no published reach is capped at 80. It can rank among its peers, it cannot take the top of the leaderboard from an ad we measured fully.

Signals compare an advertiser's active ads today with 7 days ago: Offline means no active ad, Winner means an active ad has run for 30 days or more, Live means ads are running and there is no count from a week ago to compare with, Scaling means the active count grew by 15 percent or more, Cutting means it fell by 15 percent or more, and Stable means it moved by less than that either way. They are checked in that order, so an advertiser with a 30-day ad reads Winner even while scaling. The trend percentage is the same comparison: active ads today against a week ago.

Worked example

A business coach has 12 active ads that have been running 30 days, with a combined EU reach of 800,000 accounts. The band for Business and Entrepreneurship is €10 to €12.

30-day reach = 800,000 ÷ 30 × min(30, 30) = 800,000
impressions = 800,000 × 1.5 to 2.5 = 1.2M to 2.0M
spend = 1.2M × €10 ÷ 1,000 to 2.0M × €12 ÷ 1,000 = €12K to €24K

Had the same ads been running 60 days for that same 800,000 reach, only half of it would fall in the window and the range would read €6K to €12K. Reach is published for the whole life of an ad, so a long-running ad that reached a lot of people once is not a big spender now.

Reach is published for all 12 ads, every one is older than 14 days and the niche is known, so the range is labelled high confidence, ±20%. In the product it reads €12K–€24K with a green dot.

Angles

An angle is the promise an ad leads with, written as one short English sentence whatever the ad's language: "Escape your job without sacrificing security", "Lose weight without deprivation". A model reads each creative once (the same creative run 700 times is one reading) and either reuses an angle already found in that niche or writes a new one. Copy that makes no promise, such as a bare product name or a job listing, gets no angle rather than a guess.

Labels are then grouped by meaning: each label is embedded, and a label joins the most used label within 0.80 cosine similarity of it, so "Transform your body in 28 days" and "in 30 days" are one angle named by the more used of the two. That threshold was set by reading the marginal merges it allows; it is our judgement, and a merge you disagree with can be reported from the angle's panel.

The counts on an angle are counts of ads, one per ad id, started inside the chosen window, and of the distinct advertisers behind them in that same window. The trend compares the window with the one before it. Only part of the corpus has been read for angles so far (the page header says what share), so every count on that page is a count over the ads read, never over everything we hold.

What we do not know

  • Revenue. We show the price a landing page states, never how many people paid it.
  • Spend outside the EU. Meta publishes reach for the EU only, so US-only campaigns are not estimated.
  • Exact CPM paid by any single advertiser. Our niche CPM is a distribution, not a bill.
  • Anything behind a login, a paywall or a private group.
  • Anything past the landing page. We capture the page an ad sends to and stop there, and we never fill in a form, so what comes after an opt-in or a checkout stays unseen.

Questions about a specific number: hello@whosprinting.com, answered by a human in under a day.