What our ads actually did
We run Meta ads for Harvv with our own pixel on the landing page. This is what the pixel caught, what we changed because of it, and what moved. Updated every hour.
One campaign, not our whole account. Every figure below is scoped to a single ad set, so nothing else we run is folded in to flatter it. We publish the results, not the targeting: you will not find the audience, the interests or the geo split here. You will find every number they produced.
What this is and is not. It is Harvv used on its own ad traffic: an observational record of one live campaign, with what the pixel found dated, what we changed in response, and the numbers on both sides. It is not a controlled experiment: there is no holdout, Meta's own optimisation keeps moving who sees the ad, and things we shipped on the same day cannot be separated afterwards. Where the page uses the word "better" it has cleared a significance test; everywhere else it is describing, not concluding.
Working back from $75 a signup
The goal is a cost, not a rate. Everything below is what that cost demands of the funnel, and where the funnel actually is. 4 sessions and $43.13 spent so far.
A signup here means an account was created. The landing page offers two other things to do, opening the booking calendar and submitting the free audit, and both are counted further down but neither is what the cost is judged on. The calendar is a click on an outbound link, so it cannot tell us a call happened. The audit does hand us a real lead, an address and a site, but a lead is not an account and neither is revenue. And $75 is a ceiling we chose, not a break-even we derived. Publishing it as though the unit economics produced it would be the same trick this page exists to avoid.
4 sessions so far, and no signup. Under 25 sessions the cost of one is not stable enough to derive a threshold from: it moved from a third of a dollar to over a dollar in two days on this campaign. The verdict and the thresholds appear at 25.
- Click-through rate0.96%8,839 impressions
- Clicks that survived the load89.4%85 link clicks
- Sessions that read past the foldno rate yet, 4 ad sessions4 ad sessions
- Sessions that opened the calendarno rate yet, 4 ad sessions4 ad sessions
- Sessions that submitted the auditno rate yet, 4 ad sessions4 ad sessions
- Sessions that reached signupno rate yet, 4 ad sessions4 ad sessions
- Sessions that ended in a signupno rate yet, 4 ad sessions4 ad sessions
Only the last stage carries a required number. A cost per signup does not dictate a click-through rate: there are many combinations of the stages above that land on the same $75, so the ones above are reported as they are rather than given a target they do not individually owe.
42 days of this campaign
Running since 2026-09-03. Nothing before that date is counted anywhere on this page.
The funnel
Our own pixel counts fewer ad-tagged sessions than Meta reports landing page views: 4 against 76. Two different meters. Meta counts a view it attributes to one of its own clicks, measured by its pixel; ours counts a session that arrived carrying this campaign's tag, measured by our pixel, after two filters described below. Where the difference goes is counted step by step in the next block, because a measurement company that cannot account for its own gap has no business telling customers about theirs.
Two populations, not one. The first three stages are Meta's meter over the people Meta showed the ad to. The last three are our pixel's meter over sessions that arrived carrying this campaign's tag, and the signups whose record carried it through. Within each half every stage is a fraction of the one above it. Across the seam it is not, which is why no rate is printed there. Nothing on this chart is a site-wide number standing in for an ad-driven one.
Where the traffic goes between Meta's count and ours
Our server saw 67 requests for the page against Meta's 76 landing page views, fewer than Meta: some of what Meta counts as a page load never reached our server as a tagged request. From there to a published session the pixel has to load, run, and send a beacon before the visitor leaves, and then survive two filters. That path is where the difference between Meta's number and ours comes from, and each step of it is counted above.
"Stayed on the page" is 5 seconds of ACTIVE time, scrolling past 25%, or reaching for a control on the page, whichever lands first. Active, not wall clock: a tab left open in the background reads as a long visit on the clock and as nothing at all on attention, and on this campaign the median visit was 31 seconds on the clock and 1.1 seconds of attention. It is not a conversion and is never counted as one. It is here because it separates "the ad bought a reader" from "the ad bought a page load", which the numbers above cannot do on their own.
The definition of this one number widened on 2026-09-10, so counts either side of that date are not the same measurement and a rise across it is not evidence of anything. It opened at 15 seconds of active time or half the page, and over the 30 days to that date it fired on 5 of 170 sessions while Meta's own record of the ad set carried no such event at all. Both doors were shut to traffic whose median attention was 1.1 seconds and whose median scroll was 1.3%. The thresholds came down and a third door was added for a visitor who taps a question or puts the cursor in the audit box, because that is intent rather than a proxy for it. It is logged in the change list below, like every other change, and the reason each one fired is recorded so a rise here can be read as attention rather than as the definition moving.
All three branches sit OUTSIDE the funnel above on purpose. Opening the calendar, submitting the audit and reaching the signup page are things a session can do and none of them requires another, so putting either in the column would make the stage under it read as a percentage of people who opened a calendar. They are drawn against the session count instead, which is the population they actually come from.
The calendar is a click, not a booked call. The link opens Google Calendar in a new tab and Google tells us nothing back, so we cannot know whether a call was booked and do not claim to. The audit submit is firmer: it hands us a URL and an email, so the lead is a real row rather than an outbound click we never hear about again. Neither is revenue, and the cost goal is judged on signups.
The numbers, and which way they are going
Each metric over every day of spend, with the most recent half of those days compared against the earlier half. A direction is only shown when both halves have enough behind them; otherwise the reason it is missing is printed in its place.
The grey line under some metrics is a third-party industry benchmark, not our measurement: where a published B2B/SaaS range sits, so a number has something to be read against. A position at the top of that range is a fact about the click, not a grade for the campaign: a cheap click that never reads the page is the most expensive thing an ad can buy, which is why the click metrics carry the share of sessions that read past the fold. Every one is sourced and dated below, and metrics with no citable benchmark deliberately show none rather than a made-up bar. Ranges move; ours are as of 2026-09.
Costs are better going down and rates are better going up, and which is which is set per metric rather than guessed from the arrow. Splitting the days in half is the comparison, not a rolling window: a window that can be slid until it looks good is not a measurement. With 42 days of spend on record, most of these will stay withheld for a while, and that is the correct output rather than a placeholder.
Are these visitors heading toward a signup? The Intent Score
One number, 0 to 100, for how much this campaign's visitors behaved like people who sign up, before any of them reached the signup page. 50 is the median visitor to harvv.com over the same 30 days; a day at 30 bought visitors who behaved like the site's bottom third.
How much this score is worth, checked on days the fit never saw. Fitted 2026-10-17 on 442 sessions with 8 that reached the signup page; 98 sessions that landed directly on the signup page were excluded, because they arrived decided and carried no behaviour to learn from. Status: insufficient.
Each dot is the mean over that day's ad sessions and the bar through it is a 95% bootstrap interval; a day with fewer than 10 scorable sessions shows its count instead of a dot. The dashed line is the site median. "Direction" is Kendall's rank correlation between the day and its score: it asks whether later days score higher than earlier ones more often than not, and it is called a direction only when p is under 0.05.
By creative
| Creative (utm_content) | Sessions scored | Intent Score | Signups predicted |
|---|---|---|---|
ask_why_v3_slack | 4 | – | 0.05 |
ask_why | 1 | – | 0.02 |
What moves it
The score is not a checklist we wrote; it is fitted, so a signal that does not predict a signup on this site gets a weight near zero, and the weights are printed. It reads only what visitors did: referrer, campaign, click ID and country are deliberately not inputs, because a score that reads the source label is one an ad could never raise by getting a better page or a better audience. Weights are on standardised inputs, so they are comparable to each other and to nothing else.
What it cannot say. These are fitted associations, not causes: sessions that hovered and clicked more went on to sign up more often, which does not mean that inducing hovers produces signups. The dated change log above, read against this line, is the closest thing this page has to a causal test, and the score is the instrument for reading it, not a substitute. It is refit every day on the last 30 days, so its weights move, and the fit date is printed each time.
Which ad these numbers came from
Everything above is scoped to one campaign tag, and a campaign tag survives a change of ad. 2 creatives have run under it. They are listed separately because pooling them would hide the change, and no rate is compared between them: at these volumes that comparison would be noise, which is the thing this page refuses to publish.
| Creative (utm_content) | Sessions | Read past the fold | Days live |
|---|---|---|---|
ask_why | 1 | 0 | 2026-09-04 |
ask_why_v3_slack | 4 | 0 | 2026-09-08 |
The landing page also changed during this window, so a creative's numbers are not a clean read on the creative alone. The dated log above says what moved and when.
Day by day
Spend and sessions are separate charts on purpose: they are different scales, and one chart with two y-axes can be made to show any relationship you like. Dashed rules on the rate charts mark the days we changed something. A day with fewer than 25 in its denominator is drawn as a gap, because a rate over a handful of events is not a rate.
What moves with what
Pearson correlation across the days above. Every figure carries the number of days behind it. Correlation is not cause, and at these sample sizes it is barely even correlation.
| Pair | Correlation | Days |
|---|---|---|
| Spend vs Ad sessions | +0.68positive95% interval +0.47 to +0.81 | n = 42 days |
| Spend vs Signups from this ad | not enough data yet | |
| Ad sessions vs Signups from this ad | not enough data yet | |
| Ad sessions vs Rage-click sessions | +1.00positive95% interval +1.00 to +1.00 | n = 42 days |
| Ad sessions vs Sessions reaching signup | not enough data yet | |
| Rage-click sessions vs Signups from this ad | not enough data yet | |
Every number, as a table
The same data behind every chart above, so nothing here is readable only as a shape.
| Date | Spend | Impr. | Clicks | LPV | Server saw | Tagged | Sessions | Intent | Read ≥50% | Calendar | Audit | Stayed | Reached signup | Signups | Rage | Dead |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2026-10-17 | $0.00 | 0 | 0 | 0 | 0 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-10-16 | $0.00 | 0 | 0 | 0 | 3 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-10-15 | $0.00 | 0 | 0 | 0 | 3 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-10-14 | $0.00 | 0 | 0 | 0 | 3 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-10-13 | $0.00 | 0 | 0 | 0 | 0 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-10-12 | $0.00 | 0 | 0 | 0 | 0 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-10-11 | $0.00 | 0 | 0 | 0 | 0 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-10-10 | $0.00 | 0 | 0 | 0 | 0 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-10-08 | $0.00 | 0 | 0 | 0 | 0 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-10-07 | $0.00 | 0 | 0 | 0 | 6 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-10-06 | $0.00 | 0 | 0 | 0 | 6 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-10-05 | $0.00 | 0 | 0 | 0 | 1 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-10-03 | $0.00 | 0 | 0 | 0 | 0 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-10-02 | $0.00 | 0 | 0 | 0 | 4 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-10-01 | $0.00 | 0 | 0 | 0 | 0 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-30 | $0.00 | 0 | 0 | 0 | 3 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-28 | $0.00 | 0 | 0 | 0 | 0 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-27 | $0.00 | 0 | 0 | 0 | 0 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-26 | $0.00 | 0 | 0 | 0 | 0 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-25 | $0.00 | 0 | 0 | 0 | 0 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-24 | $0.00 | 0 | 0 | 0 | 0 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-23 | $0.00 | 0 | 0 | 0 | 0 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-22 | $0.00 | 0 | 0 | 0 | 0 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-21 | $0.00 | 0 | 0 | 0 | 0 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-20 | $0.00 | 0 | 0 | 0 | 1 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-19 | $0.00 | 0 | 0 | 0 | 1 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-18 | $0.00 | 0 | 0 | 0 | 1 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-17 | $0.00 | 0 | 0 | 0 | 0 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-16 | $0.00 | 0 | 0 | 0 | 3 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-15 | $0.00 | 0 | 0 | 0 | 1 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-14 | $0.00 | 0 | 0 | 0 | 1 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-13 | $0.00 | 0 | 0 | 0 | 1 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-12 | $0.00 | 0 | 0 | 0 | 6 | 1 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-11 | $0.00 | 0 | 0 | 0 | 1 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-10 | $0.00 | 0 | 0 | 0 | 1 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-09 | $14.03 | 4,827 | 28 | 26 | 0 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-08 | $16.71 | 2,617 | 20 | 15 | 16 | 4 | 4 | – | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 |
| 2026-09-07 | $1.82 | 284 | 1 | 1 | 0 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-06 | $0.00 | 0 | 0 | 0 | 3 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-05 | $0.00 | 0 | 0 | 0 | 1 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-04 note | $0.00 | 0 | 0 | 0 | 1 | 1 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2026-09-03 | $10.57 | 1,111 | 36 | 34 | 0 | 0 | 0 | – | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
"Server saw" is requests for the landing page carrying this campaign's tag, counted server-side with no JavaScript involved, crawlers included. "Tagged" is every session our pixel reported with the tag, before any filter. "Sessions" is what is left after the bot classifier and the no-click gate, and is the number used everywhere else on this page. A day marked "note" had sessions removed; hover the mark for why. 2026-09-04: tagged sessions before the campaign spent anything; treated as ad-review crawlers, not visitors
What we detected, what we changed, what happened next
Bundled by the day it shipped, because that is also the unit we can measure: things released together cannot be separated afterwards. Each date carries what our own product or its gates found, what we did about it, and the result measured over the 1,000 campaign sessions either side. Today's entry is open; earlier days are folded, and a date opens with one tap.
2026-10-011 change
Detected A visitor who triple clicks to select a paragraph, a command or a code block was recorded as making a rage click, the same as three angry clicks on a button that does nothing. We reproduced it in a browser on our own pixel: one rage click for every triple click on plain text. We cannot say how many past rage clicks were text selections, because a stored rage click does not record whether the clicks selected text.
Changed From pixel version 17, a fast burst of clicks on plain text that makes or changes a text selection is not counted as rage. Rage on buttons, links and other controls still counts. The share of sessions with a rage or dead click on this page can fall from this date for that reason alone, not because the landing page got better.
0 of 1,000 sessions since this shipped, and 254 of 1,000 before it
- still measuring Scrolled at all
- still measuring Reached the signup page
- still measuring Hit a rage or dead click
No verdict until the window fills. The numbers above are shown so the wait is visible, not so anyone acts on them: a rate read early moves on noise, and checking until it looks good is how you find a winner that is not there.
2026-09-201 changeA second research pass corrected two ad rules written two days earlier
Detected We asked a second research tool the same 22 questions and compared the answers. Two rules had leaned on weak sources. One said a platform lift study needs about $30,000; the platforms' own help pages list $5,000 and 500 to 1,000 conversions, and the larger figure was an agency estimate of statistical power, not eligibility. The other quoted a median branded search return of 0.70x across 225 tests, which traces to a vendor write-up with no published table. The two reports also disagreed on how Meta changed its existing customer budget cap, which is why no rule was written on it.
Changed The lift study rule now says a study is worth asking about from about $5,000 a month per platform and is not guaranteed. The test size rule now carries arithmetic we checked ourselves: about 1,570 orders in each group to see a 10% sales change, 390 for 20%, 175 for 30%. The branded search rule no longer quotes the 0.70x figure, and it now requires the competitor report to be read before any pause is suggested. One rule was added: for Performance Max, ask for conversions split by ad event type, because views without a click are counted in the main column. We tried to pull that split through the API for one account and it came back as unknown for all 347 conversions.
0 of 1,000 sessions since this shipped, and 254 of 1,000 before it
- still measuring Scrolled at all
- still measuring Reached the signup page
- still measuring Hit a rage or dead click
No verdict until the window fills. The numbers above are shown so the wait is visible, not so anyone acts on them: a rate read early moves on noise, and checking until it looks good is how you find a winner that is not there.
2026-09-161 changePut the goal back to page loads after finding the pixel refuses our own website
Detected The ad set was moved to optimise for AuditSubmitted earlier the same day on the strength of a Conversions API receipt: HTTP 200, one event received. That receipt only proves Meta's API accepted the call. The pixel itself refuses every event from harvv.com, which Meta prints in the browser console on our own pages: the pixel is unavailable on this website due to its traffic permission settings. No request to Facebook leaves the page even when the event is fired by hand, no browser cookie is set, and the pixel reports zero events over three days while two other pixels on the same ad account report 1,459,973 and 3,431 over the same window. Landing page views kept appearing in ad reports because Meta counts those inside its own in-app browser without the pixel, which is what made the delivery look healthy. With the pixel refusing the event, the ad set was optimising for something it could never receive: 453 impressions and 2 clicks today at about twelve times the earlier cost per thousand views.
Changed Goal returned to landing page views, which this ad set can actually produce, so the budget stops buying an impossible event. The audit event itself stays shipped and keeps being sent from the server and the page. The real fix is a Meta setting a person has to make: allow harvv.com in the pixel traffic permissions, or give harvv.com its own pixel owned by the Harvv business rather than the shared QisstPay one. Case 75289 holds the evidence. The goal moves back to AuditSubmitted only after real audit submissions are visible in the pixel's own event counts, not after an API receipt.
0 of 1,000 sessions since this shipped, and 254 of 1,000 before it
- still measuring Scrolled at all
- still measuring Reached the signup page
- still measuring Hit a rage or dead click
No verdict until the window fills. The numbers above are shown so the wait is visible, not so anyone acts on them: a rate read early moves on noise, and checking until it looks good is how you find a winner that is not there.
2026-09-155 changesStopped selling a signup to agencies and started offering an audit to stores · Stopped both signup-offer arms and put the whole budget on the audit offer for four days · Counted audit submits from both shapes the pages actually emit, not just one · Added one small line at the bottom of /prompt offering a call, and gave the header signup button a stable name · Asked Meta for audit submissions instead of page loads
Detected Across 304 sessions this campaign bought, not one reached the signup page. The statistical ceiling on that rate is 1.27%, which puts the best possible cost per signup at $91 against a $75 target, so the optimistic end of the range already missed. Meanwhile the four businesses actually using the product are all stores, and the one offer that has ever produced leads asks for a URL rather than an account. Separately, the audit form had never recorded which ad sent anyone, so no previous run could be credited or blamed.
Changed Built a new concept aimed at store owners, pointing at the free audit rather than the signup, at $5 a day. Before it runs, the audit form now records the campaign, creative and click ID behind every lead, which it had been computing and discarding for four months. It is paused until reviewed. The consent banner is unchanged: privacy first stays the choice.
Detected Across the three US campaigns running since 2026-08-18 (agencies 252 clean sessions, us_agency_owners 143, homepage demo 75) 470 sessions reached the signup page zero times. Rule of three puts the 95% ceiling on that rate at 0.638%, and at the blended $0.546 per session the best possible cost per signup-page reach is $85.49 against a $75 target for a signup, which sits one step further down. The optimistic end misses before any page-to-signup loss is counted.
Changed Paused the agencies ad set (120246930493900658) and the homepage demo ad set (120247072540420658). Raised the ecom audit ad set (120247115756930658) from $5 to $20 a day and turned it on, pointed at /prompt. Four days, about $80. Both old arms were paused rather than one, because $20 plus the homepage $10 is exactly the $30 ceiling and the guard trips above it, pauses every active ad set and never unpauses. Kill rule, pre-registered: at ~$0.55 a session, $80 buys about 145 sessions. Zero audit leads by then puts the 95% floor on cost per lead at about $26 against a break-even of $2.34, ten times short, and the arm stops. Break-even is $75 times the measured lead-to-signup rate of 1 in 32 audit leads from 2026-05-27 to 2026-09-04; with one conversion the honest range on it is $0.06 to $12.
Detected /ask reports a submit as window.harvv.track('audit_submit'), which the pixel pushes as event_type cm with the name in data->>'k'. /ads-audit and /audit report the same action through window.harvv.outcome('audit_submitted'), which the pixel pushes as event_type oc with the name in data->>'n'. The counter read only the first shape, so 4 real submissions across 4 distinct sessions (2026-08-18, 08-19, 08-28, 09-01, all on /ads-audit, all is_suspect=false) were invisible to it.
Changed analysis/ad-experiment.js now matches both event types and both names. This does NOT move the published figure: all 4 carried the old vibecoder campaign tag and none carried this experiment's, so the 0.00% over the 251-session cohort was a true measured zero. The gate that missed it asserted only the event NAME; it now reads the FILTER behind audit_submit_sessions and asserts both event types, with a located-the-filter check ahead of it so it cannot pass vacuously. Case #75185.
Detected The audit offer had no second step for a visitor who wants a person rather than a prompt, and /experiment's calendar metric had no emitter on that page at all. Separately, the header Start free button was recorded under four different element labels over 30 days (a.btn:"Start free" 6 on / and 3 on /ads-audit, div.hact:"Sign inStart free" 4, a.btn:"Start free, no card" 3+2, a.cta:"Start free" 1), so any query filtering one label undercounts.
Changed /prompt now carries "Want an in-depth audit? Book 20 minutes with us." small and last, outside both the form and the result so it survives the swap, emitting book_call_click, the exact name /experiment already queries. The nav CTA has id="nav-start-free" so the label carries a stable token. Also removed a duplicate pixel script tag from /prompt: renderHead() already emits one, and this was the only page on the site with two. No data damage, because pixel.js bails on window.__harvvLoaded__, which is the point of case #75164.
Detected The ecom audit ad set was judged on audit submissions but optimised for landing page views, so Meta was paid to find people who load a page. Meta never received an audit signal to learn from: Lead only fires when an email is also given, 2 times in 30 days. Audit submissions are the more common intent signal; the vibecoder campaign produced 10 to 30 a week. The pixel stats endpoint returns no buckets for any event since 2026-09-12 20:00, so it could not confirm a new event; Meta's own receipt for a real test submission (HTTP 200, events_received 1) was used instead.
Changed Every audit submission on /prompt, /ads-audit and /audit now sends AuditSubmitted to Meta, from the server and from the page under one event id so Meta counts it once. The ecom audit ad set (120247115756930658) now optimises for AuditSubmitted instead of landing page views. This resets learning. At 10 to 30 submissions a week it will likely stay learning limited below the roughly 50 a week Meta wants, and clicks will cost more. The four day kill rule from the same day still applies.
5 changes shipped together on this date, so any movement belongs to the batch and cannot be split between them.
22 of 1,000 sessions since this shipped, and 232 of 1,000 before it
- still measuring Scrolled at all 8.6% → 9.1%
- still measuring Reached the signup page 0% → 0%
- still measuring Hit a rage or dead click 2.2% → 9.1%
No verdict until the window fills. The numbers above are shown so the wait is visible, not so anyone acts on them: a rate read early moves on noise, and checking until it looks good is how you find a winner that is not there.
2026-09-131 changePut the signup path where people had already reached, instead of adding another button
Detected Of 227 ad sessions on the landing page over 30 days, only 15 clicked anything at all. Of those 15, the consent banner drew 5 sessions, a question chip 2, our own live readout bubble 2, and the standing Start free row 1. Interaction itself is the scarce thing here, not the number of buttons. The six dead clicks over the same period landed on six different elements, one each, so they are single moments rather than a pattern, and the one mechanical explanation was checked and ruled out: the question chips already meet the 44 pixel minimum we tell customers to meet.
Changed The answer panel now ends in its own call to action, so someone who taps a question and reads the answer is offered the same thing for their own site at the moment they are interested, rather than from a row further down the page. The live readout, which by then has counted their own scroll depth and dead clicks in front of them, now offers the obvious next thought instead of nothing. Both are clicks toward signup and are counted as clicks, never as signups. The consent banner was deliberately left exactly as it is: privacy first is the choice, and it is not being traded for conversion.
37 of 1,000 sessions since this shipped, and 217 of 1,000 before it
- still measuring Scrolled at all 8.8% → 8.1%
- still measuring Reached the signup page 0% → 0%
- still measuring Hit a rage or dead click 2.3% → 5.4%
No verdict until the window fills. The numbers above are shown so the wait is visible, not so anyone acts on them: a rate read early moves on noise, and checking until it looks good is how you find a winner that is not there.
2026-09-122 changesPut one fitted number on the page: the Intent Score · Stopped asking Meta for an event this budget can never produce
Detected Every number here was a count against a threshold somebody chose (50% scroll, 5 seconds active), and none of them said whether the visitors were heading toward a signup. Two days in a row read 0 of 48 sessions past the fold; checked against the reading observer and same-day organic traffic, that was real, not a pixel fault, but nothing on the page could weigh it against the other signals.
Changed Added a 0 to 100 score fitted daily on harvv.com own signups from pre-signup behaviour only (no referrer, campaign or click ID as inputs), placed as a percentile against every visitor to the site, with a bootstrap interval per day, a Kendall trend, and the model held-out AUC and calibration printed above the score. On the first fit it ranked a future signup above a non-signup 87% of the time (interval 79 to 95) on days it had not seen; the campaign sessions scored 15 to 40 against a site median of 50.
Detected On 2026-09-08 we moved this ad set from landing page views to conversions, optimising for our own HarvvEngaged event. Meta has recorded zero of them: its own learning record for the ad set reads 0 conversions, 14 days of reporting contain no offsite conversion of any kind, and the pixel API returns 0 over 30 days. The ceiling is arithmetic rather than wiring. Our own emitter for the same condition fired on 16 sessions in 14 days across the whole site, 1 to 5 a day, so even perfect delivery is roughly 8 to 20 a week against the 50 a week Meta needs to leave the learning phase. Delivery paid for it: 219 impressions and 4 landing page views today against a 14 day average near 1,027 and 11.5. This is the fourth time in six days the same finding has been filed, which is its own defect.
Changed Moved the goal back to landing page views, which this ad set already produces at about 80 a week, comfortably past the threshold. It is one edit, so one learning reset, and the reset is the cost of the fix. Landing page views are a traffic goal, not a conversion, so quality is now judged by the Intent Score published above rather than by the goal itself. The stale HarvvEngaged event is still attached to the ad set record where it is inert, and the pixel health detector was taught to read the goal before the event so it stops filing this case against an ad set that no longer optimises for it.
2 changes shipped together on this date, so any movement belongs to the batch and cannot be split between them.
77 of 1,000 sessions since this shipped, and 177 of 1,000 before it
- still measuring Scrolled at all 6.8% → 13%
- still measuring Reached the signup page 0% → 0%
- still measuring Hit a rage or dead click 1.7% → 5.2%
No verdict until the window fills. The numbers above are shown so the wait is visible, not so anyone acts on them: a rate read early moves on noise, and checking until it looks good is how you find a winner that is not there.
2026-09-102 changesWidened "stayed on the page" after finding both its doors were shut · Nothing on the first phone screen could be tapped
Detected The signal fired at 15 seconds of active time or half the page, and over the 30 days to this date it fired on 5 of 170 ad sessions. Meta recorded none of them: its insights for this ad set carried no offsite conversion action at all, while the ad set optimised for one. Median attention on this traffic was 1.1 seconds and median scroll was 1.3%, so the scroll door could not open for anyone and the timer opened for almost nobody.
Changed Five seconds of active time, a quarter of the page, or a deliberate reach for a control: tapping a question or putting the cursor in the audit box. The third one is intent rather than a proxy for it, and it lands seconds before either timer. Counts either side of this date are not the same measurement and the page says so where the number is printed. Every emission records which of the four doors it came through, so a rise can be read as attention rather than as the definition moving.
Detected Measured live at 400px, the width the traffic actually arrives on: 164 of 173 link clicks in 30 days came from the Facebook in-app browser on mobile, and the first tappable thing in the page body sat 747px down. Above that were the nav, the headline, one sentence and a static screenshot. A third of sessions were scored as reading rather than skimming, so they were not bouncing blind, they read a first screen that offered them nothing to do and left. The page also had no hero-sub, which our better-performing landing page does have.
Changed Logged as a finding today, not yet changed. The fix is queued as its own case so its effect is not folded in with the measurement change above.
2 changes shipped together on this date, so any movement belongs to the batch and cannot be split between them.
86 of 1,000 sessions since this shipped, and 168 of 1,000 before it
- still measuring Scrolled at all 5.4% → 15.1%
- still measuring Reached the signup page 0% → 0%
- still measuring Hit a rage or dead click 1.8% → 4.7%
No verdict until the window fills. The numbers above are shown so the wait is visible, not so anyone acts on them: a rate read early moves on noise, and checking until it looks good is how you find a winner that is not there.
2026-09-085 changesTurned phones back on · Named Meta's review crawler by its network, and removed 15 of its sessions from this page · Found the browser pixel pointing at a Meta pixel ID that does not exist · Asked Meta for readers instead of page loads · United States only, home location, Wi-Fi, registered users excluded
Detected The 09-05 entry bought desktop only because 3 of 9 desktop sessions had read halfway while 2 of 123 phone sessions had. Checked against the ad creation times from the Meta API: every desktop session in this campaign that read past half arrived 2 minutes after an ad was created, from Meta's own data-center countries, in a 1050px window. Those were Meta's review crawlers, not readers. After the change the ad set delivered 284 impressions and 1 click on 09-07 and spent 18% of its budget, so the 1,000-session windows on this page could not fill.
Changed device_platforms is back to mobile and desktop. Countries stay US, GB and AU. One thing moved that we did not ask for: Meta now stores location_types as frequently_in, home and recent where it held home and recent before; we sent home and recent and it returned all three, so reach may be slightly wider than before 09-05. Nothing else in the ad set changed.
Detected Every session in this campaign that scrolled past half, touched the audit form or rage clicked, 11 of 12, arrived 2 to 3 minutes after an ad was created, in a burst of 4 to 8 from Sweden, Ireland and the United States, one of them on a 2018 Firefox. The classifier caught 1 of 16. So the 3 read-past-the-fold sessions, both rage sessions and all 6 form touches this page showed were crawler sessions. Nothing in what the browser reports separates them from people; the network they arrive from does.
Changed Meta's own network (AS32934, the query Meta's crawler documentation names) is now in the classifier's address table, so a session from it that runs our JavaScript is flagged meta_network_ip on arrival, on every site, not just this one. The 15 unflagged crawler sessions on this campaign were reclassified by hand from their arrival time and origin, because addresses are never stored. Read past the fold on this page drops from 3 to 1, rage sessions from 2 to 0, form touches from 6 to 0.
Detected The Meta pixel the ad account owns logged 1 PageView in 14 days while this page alone had about 160 sessions. The shared page head hardcoded a different pixel ID, one the account cannot see, so every browser-side event from every marketing page (PageView, the HarvvEngaged read event, the browser half of Lead) was sent to nothing. Server-side events used the right ID, which is why registrations and audit leads still appeared.
Changed The page head now reads the same pixel ID as the server. From this deploy, Meta receives a HarvvEngaged event when a visitor stays 15 seconds or scrolls past half of /ask. Separately, the QA suite's test-account signups (1,999 in 14 days) were being sent to Meta as real registrations; they are now excluded.
Detected Three campaigns, three pages and three audiences all bounced 84 to 88 percent under landing-page-view optimisation at lowest cost. The goal buys what it names: the cheapest page load, which is a one-second phone session. Changing the audience never changed the shape.
Changed The ad set now optimises for the HarvvEngaged event (15 seconds active or half the page read on /ask) instead of landing page views. Meta needs roughly 50 such events a week to finish learning; below that it still steers toward people who resemble the ones who read. Impressions and clicks will fall and the cost per session will rise; the number to watch is sessions past half, not clicks.
Detected Of 162 real sessions this campaign sent to /ask, 107 came from Canada, 38 from the United Kingdom and 26 from the United States, at roughly 50 rupees a click. Meta was buying the cheapest inventory in the country list, not the audience the brief named. Every cohort so far has been 90 percent phones with a median engaged time under two seconds.
Changed Countries narrowed to the United States with home location only (no travellers or recent-location matches). Age widened to 25 to 64. Mobile delivery restricted to Wi-Fi connections. People who already registered are excluded. Two live interests (Google Analytics, Conversion marketing) were added to the marketing-tools block; two others Meta had retired were left out. Placement stays Facebook feed only, phones and desktop. Reach is smaller and the cost per click will rise; the test is whether the sessions that arrive read the page.
5 changes shipped together on this date, so any movement belongs to the batch and cannot be split between them.
135 of 1,000 sessions since this shipped, and 119 of 1,000 before it
- still measuring Scrolled at all 7.6% → 9.6%
- still measuring Reached the signup page 0% → 0%
- still measuring Hit a rage or dead click 1.7% → 3.7%
No verdict until the window fills. The numbers above are shown so the wait is visible, not so anyone acts on them: a rate read early moves on noise, and checking until it looks good is how you find a winner that is not there.
2026-09-063 changesMade the ad say Slack, and stopped showing 22% of its own copy · Got the cookie bar off the proof, and cut the words in front of it · Fixed the form fields that were taller than the screen is wide
Detected The ad body was 563 characters. Meta shows about 125 before a "See more" that roughly 1% of readers tap, so the part a phone displayed cut mid-word inside the problem statement and never reached what the product does. The image said "aren't working", the ad headline said "Ask your client's site why", and the page H1 said the same as the headline: three phrasings of one idea. The Slack card on the image carried "62% of paid visitors" and "214 sessions" with nothing marking it as an example, on an ad whose whole promise is not publishing numbers we did not measure. And the image never showed Slack itself, only the word.
Changed Body cut to 122 characters so all of it shows above the fold. Image, ad headline and page H1 are now one sentence. The Slack card is labelled EXAMPLE, drawn with the same Slack sidebar chrome the homepage uses, and carries the Slack mark plus the four assistant logos the page shows. The creative is generated from the brand tokens by scripts/build-ad-creatives.js instead of by hand, so it cannot drift off-brand again, and create_adcreative now runs the copy validator before the API call, which is how 563 characters got through in the first place. Ad AGT_Harvv_Agencies_AskWhy_2026-09-06_ad3_slack replaces ad2; nothing else in the ad set moved.
Detected At 384x696, the most common screen in this campaign, the consent bar covered the bottom third of the first screen: exactly where the Slack example that the ad promises begins. The pixel's reading signal showed the subtitle was the only block most phone visitors ever had in view: 32 saw it and skipped, 7 skimmed, 11 read; every block below it was never in view for 30 or more sessions. 92% of phone visitors never scroll, so they saw the promise and not the proof. The most tapped thing on the page was "Accept all".
Changed Banner copy cut from 22 to 11 words and its mobile padding tightened. Subtitle cut from 31 to 15 words and the hero pulled up. Rendered at 384x696, the question and Harvv's answer are now both on the first screen. Not changed: the banner still shows, because UK visitors are in the targeting and a returning-visitor cookie needs consent there.
Detected On a real Android phone the URL field on /ask measured about 390px tall and the email field the same; on /ads-audit both were 190px. The rule was flex: 1 1 190px on the inputs, a sensible width in the desktop row, and on phones the form flips to a column, where flex-basis becomes the height. Four layout checks passed while the field we ask a paid visitor to type into was taller than their viewport is wide. /ads-audit was also rendering in the dark theme against a light-default site.
Changed flex-basis reset to auto inside the column rule on the three pages whose form flips (/ask, /ads-audit, /audit); /ads-audit rendered light. The layout gate now fails any text input taller than 80px at phone widths, and a planted copy of the bug reddened it before this shipped.
3 changes shipped together on this date, so any movement belongs to the batch and cannot be split between them.
142 of 1,000 sessions since this shipped, and 112 of 1,000 before it
- still measuring Scrolled at all 7.1% → 9.9%
- still measuring Reached the signup page 0% → 0%
- still measuring Hit a rage or dead click 0.9% → 4.2%
No verdict until the window fills. The numbers above are shown so the wait is visible, not so anyone acts on them: a rate read early moves on noise, and checking until it looks good is how you find a winner that is not there.
2026-09-054 changesStarted counting whether a visitor stayed at all · Put the thing the ad promises in the first screen · Stopped buying the cheapest country in the list · Stopped buying phones, which never read the page
Detected Across 116 ad sessions in 5 days the median ACTIVE time on the page was 1.1 seconds, and 97 of them ended under 3 seconds. The wall-clock median was 31 seconds, which is a tab left open in the background, and reading that as attention is what made the traffic look ordinary. 107 of 116 never scrolled. Nothing on the page was touched: no form, no calendar click, no audit submit.
Changed The page now fires an "engaged" signal at 15 seconds of active time or 50% scroll, whichever comes first, and /experiment counts it as a branch beside the calendar and the audit. It is not a conversion and is never drawn as one. It exists to separate an ad that bought a reader from an ad that bought a page load, which no number already on this page could do. It is also the only optimisation goal this budget can reach: Meta needs about 50 events a week to learn, and at a $75 target cost that would be $536 a day against the $10 we spend.
Detected The ad sells an answer arriving in Slack or in your AI assistant. The page opened with a headline, a question, a paragraph, two buttons and a form asking for a URL and an email, and the Slack answer panel sat below all of it. Read-depth confirms it: the only blocks any visitor ever saw were the opening paragraph and the form subtitle, both above the fold, and every deeper block was seen only by the handful of sessions that scrolled at all.
Changed The Slack answer panel moved up into the first screen, directly under the opening line, with the question chips beneath it. The buttons and the audit form moved below it. The headline now matches the ad word for word, and the opening line names Slack and the assistant instead of describing the idea abstractly. Nothing was added or removed, only reordered and reworded.
Detected The ad set was set to the United States, Canada and Australia. Meta delivered 3,299 of 3,412 impressions to Canada. The United States got 16. Asking for the cheapest possible page load, which is what the optimisation goal and the bidding strategy together ask for, gets the cheapest country, and we never tested the market we meant to.
Changed Canada is out of the ad set and the United Kingdom is in, so it is now US, GB and AU. Everything else is untouched: the same interests, the same placements, the same budget. Canada is not being re-measured because 116 sessions of it is already enough to know. This will cost more per click and buy fewer visits a day, and that is the trade being made deliberately.
Detected Meta was selling us phones almost exclusively: 55% Android smartphone, 39% iPhone, 2% tablet, across 5,983 impressions. Our own pixel says phones do not read this page. On /ask over 7 days, excluding flagged traffic: 123 mobile sessions, 92% of which never scrolled at all, median active time 1.17 seconds, 2 that reached halfway. Against that, 9 desktop sessions, 56% never scrolled, median 3.77 seconds, 3 that reached halfway. Three of nine against two of 123. Desktop is a small sample and is reported as a lead rather than a proof, but site-wide the same split holds at larger n: desktop median active time is 172 seconds against 4 to 18 on mobile. This is not the scroll blind spot; every unload event carries the scroll high-water mark, 318 of 318 on mobile, and it reports zero.
Changed The ad set now asks Meta for desktop only. Estimated reach falls from about 138,500-163,000 monthly actives to 50,800-59,800, which is still far more than a $10 a day budget can exhaust. Nothing else moved: still Facebook feed only, still US/GB/AU. This is the cheapest test available of the one difference the data actually shows, and it is one setting to undo. Read the before-and-after on this page with care. Two audience changes landed within an hour of each other today: Canada was dropped for GB earlier, and Canada had been 3,299 of 3,412 impressions. Every rate that spans 2026-09-05 therefore compares three different audiences, not one, and no verdict should be drawn across that boundary.
4 changes shipped together on this date, so any movement belongs to the batch and cannot be split between them.
163 of 1,000 sessions since this shipped, and 91 of 1,000 before it
- still measuring Scrolled at all 6.6% → 9.8%
- still measuring Reached the signup page 0% → 0%
- still measuring Hit a rage or dead click 1.1% → 3.7%
No verdict until the window fills. The numbers above are shown so the wait is visible, not so anyone acts on them: a rate read early moves on noise, and checking until it looks good is how you find a winner that is not there.
2026-09-044 changesPublished the gap between Meta landing page views and our sessions, step by step · Stopped publishing a cost per session under 25 sessions · Excluded tagged sessions on a day Meta recorded no click · Stopped calling a cheap click best in class
Detected The funnel showed 60 landing page views from Meta and 17 sessions from our pixel, with a fixed sentence underneath saying our count was the larger. It was written when that was true and never re-checked against the numbers it sat under. Nothing on the page counted what happened between the two meters.
Changed The sentence is now computed from the numbers, and a new block counts each step: our server answering the request, the pixel reporting a session, the bot classifier keeping it, and the no-click gate keeping it. Every drop between two adjacent counts is one named cause. The change log states that figures quoted inside an entry are as of that date.
Detected The goal block divided spend by 17 sessions and printed $1.25 a session, and the trend strip on the same page refused the same division as too thin. The thresholds derived from that cost had tripled in two days. Two rules for one quotient on one page.
Changed One floor, defined once in the analysis module and used by both. Under 25 sessions the goal block says what it is waiting for instead of printing a cost.
Detected The first day of the campaign read 13 impressions, 0 clicks, 0 landing page views and 7 sessions. The ad-review crawlers Meta sends at ad creation arrived on the same calendar day the campaign started spending, so the day-level spend gate let them through as visitors.
Changed A day with spend but no Meta link click did not deliver a visitor from this ad. Tagged sessions on such a day are zeroed with a note, and the raw count stays visible in the reconciliation block so the removal is not silent.
Detected The trend strip labelled a 2.55% click-through rate and a $0.34 cost per click "best in class" against published ranges, on a campaign where no session had reached the signup page. Both figures were true and the word was praise for a stage whose output had not been measured.
Changed The standings now read "top of the published range" rather than "best in class", and every upstream metric carries the share of its sessions that read past the fold, or says that share is not yet measurable. A new metric, cost per session that read past the fold, sits beside cost per session.
4 changes shipped together on this date, so any movement belongs to the batch and cannot be split between them.
189 of 1,000 sessions since this shipped, and 65 of 1,000 before it
- still measuring Scrolled at all 6.2% → 9.5%
- still measuring Reached the signup page 0% → 0%
- still measuring Hit a rage or dead click 1.5% → 3.2%
No verdict until the window fills. The numbers above are shown so the wait is visible, not so anyone acts on them: a rate read early moves on noise, and checking until it looks good is how you find a winner that is not there.
2026-09-033 changesStopped the cookie banner covering the buttons · Moved the chat button out from under the floating dock · Opened the three finding cards on mobile
Detected Measured in a real browser at phone size: the consent banner was 281px tall and covered a third of the first screen, sitting on top of both secondary buttons. Over the same 30 days its reject button was clicked more often than the page own audit button.
Changed Rebuilt it as a compact bar. It now covers 18% of the first screen instead of 33%, and its buttons meet the 44px minimum tap size we tell customers to meet.
Detected The chat button and the live tracker dock were pinned to the same corner with the same offsets. The dock renders above everything, so it covered 59% to 77% of the chat button at every scroll position. The button had zero clicks in 30 days.
Changed Moved the chat button to the opposite corner, and above the dock on phones where the two do not fit side by side. Nothing now covers it.
Detected On phones the three cards explaining what we find were collapsed, so the button inside each one was never drawn. Those buttons were not being ignored, they did not exist on screen. Phones are 68% of this page traffic.
Changed The cards now open by default. A visitor can still collapse one.
3 changes shipped together on this date, so any movement belongs to the batch and cannot be split between them.
216 of 1,000 sessions since this shipped, and 38 of 1,000 before it
- still measuring Scrolled at all 2.6% → 9.7%
- still measuring Reached the signup page 0% → 0%
- still measuring Hit a rage or dead click 2.6% → 2.8%
No verdict until the window fills. The numbers above are shown so the wait is visible, not so anyone acts on them: a rate read early moves on noise, and checking until it looks good is how you find a winner that is not there.
2026-09-023 changesStarted counting the day that is still running · Put the cost goal on the page, and the traffic needed to test it · Added a second way to convert, and started counting it
Detected This page reported today as zero spend all day while the campaign was delivering. The snapshot job was already running hourly, so cadence was never the cause: it asked Meta for date_preset last_30d, and Meta's last_Nd presets exclude the current day. No schedule could have fixed it.
Changed An explicit date range ending today. Verified against the live campaign: the preset returned 09-01 only, the range returned 09-01 and 09-02. Today's spend and impressions appear on this page from now on, so a same-day reader is no longer looking at a zero that reads like a result.
Detected The page published rates but never the number the campaign is actually judged on: what a signup costs against what we will pay for one. Without it a reader could not tell a working campaign from a failing one, and the obvious reading of zero signups was that the ads had failed.
Changed The goal is now stated at the top and worked backwards through the funnel. It also computes how much traffic is needed before zero signups means anything: about 226 sessions for the first one at the required rate, and about 677 before a continued zero is evidence rather than a quiet spell. At 31 sessions the honest verdict is that it is too early, and the page says that instead of implying failure. (Thresholds as of 2026-09-02, at $0.33 a session over 31 sessions; they move with the cost per session and the live goal block supersedes them.)
Detected The landing page had exactly one conversion, the signup, and it is the slowest thing on the funnel to fire. At the required rate and this budget, the first one was not expected for about two weeks, so there was nothing to read in between.
Changed A Book 15 minutes link now sits beside Start free on every call to action, and clicking it emits a custom event through the pixel's public API. It is counted as a branch off the funnel and labelled a click, not a booked call: the calendar is a Google link and Google reports nothing back to us. The cost goal is still judged on signups.
3 changes shipped together on this date, so any movement belongs to the batch and cannot be split between them.
245 of 1,000 sessions since this shipped, and 9 of 1,000 before it
- still measuring Scrolled at all 0% → 9%
- still measuring Reached the signup page 0% → 0%
- still measuring Hit a rage or dead click 0% → 2.9%
No verdict until the window fills. The numbers above are shown so the wait is visible, not so anyone acts on them: a rate read early moves on noise, and checking until it looks good is how you find a winner that is not there.
2026-09-017 changesFiltered for agencies with staff · Built a landing page for this ad · Made the question chips answer in one click · Moved the call to action above the fold · Fixed five tap targets under 44px · Started recording where signups come from · Stopped counting ad-review crawlers as visitors
Detected The brief was agencies with at least two people. No ad platform sells headcount targeting, so it has to be inferred.
Changed Required a second signal: tools a staffed agency buys and a solo freelancer usually does not. Reach fell from 383,000 to 135,000, so it is filtering rather than rubber-stamping.
Detected The previous agency ad pointed at a comparison page: 29.7 KB compressed against our own 25 KB budget, with a headline that promised something the ad had not.
Changed A purpose-built page at 21.6 KB whose headline is the ad headline.
Detected Clicking a question wrote it into a box and stopped, then asked for a second click to see the answer. That is a dead click, the exact thing this product detects.
Changed Selecting a question now moves the question and the answer together.
Detected On a 375px phone the only call to action sat below the answer panel, off the first screen.
Changed A button now sits under the headline, measured at 450px on an 812px screen.
Detected Our own layout check flagged logo links at 34px and a button at 26px, under the minimum Apple and Google both publish and a defect this product reports to customers.
Changed All raised past 44px, verified at five screen widths.
Detected No signup record carried a campaign tag. The capture ran only inside the app, so anyone who arrived on a marketing page and clicked through to the signup form lost it on the way.
Changed First touch is now recorded on every marketing page. There is no backfill: what was never captured cannot be recovered.
Detected Creating the ad made Meta fetch the page: 8 sessions carrying the campaign tag and a click ID before a penny was spent. Our own bot check caught 1 of the 8.
Changed Days with no spend cannot report traffic, and flagged sessions are dropped.
This shipped on the campaign's own first day, so there is no earlier traffic to compare against. It cannot be scored, now or later. Batches from here on can be.
2026-08-182 changesKept the agency angle over the trades angle · Targeted owners, not practitioners
Detected Two Dallas trades concepts ran at 1.22% and 0.91% click-through, under the 1.5% floor, while 85% and 100% of their clicks survived the page load. The hook was failing, not the page. The agency concept then ran at 1.86%.
Changed Different audience and geography, so not a clean comparison, but enough to keep the agency angle and stop rewriting landing pages.
Detected Interest targeting alone reaches everyone who works in advertising, most of whom cannot buy software.
Changed Added a business-owner signal as a required second condition rather than a broader interest list.
This shipped before the campaign started, so there is no traffic from before it to compare against. It cannot be scored against this campaign, now or later.
2026-05-232 changesStopped optimising for clicks · Dropped Instagram and Audience Network
Detected Our first campaign spent about $7 for zero signups: 174 clicks, 98.7% of them bouncing at under 10% scroll.
Changed Every campaign now optimises for landing page views, which only count when the page actually loads in a browser.
Detected Instagram sessions reported page-load times of 93 to 111ms on Pakistani mobile networks, which is physically impossible.
Changed Facebook feed only, on every campaign since.
This shipped before the campaign started, so there is no traffic from before it to compare against. It cannot be scored against this campaign, now or later.
"Better" and "worse" are only used when a two-proportion test clears 95% confidence; anything short of that reads as no detectable change, because on this much traffic a couple of points is noise. And none of this proves cause. The ad, the audience and the market all keep moving; this measures what happened after a change, not what the change did.
Any figure quoted inside an entry above is as of the date of that entry, computed on the data and the rules in force that day. The live blocks at the top of the page supersede it. Where the two disagree, that is the campaign moving or the measurement being corrected, both of which are recorded here rather than edited out.
Take the raw data
Every daily row behind this page, as CSV: spend, impressions, clicks, landing page views, sessions, signup-page reach, signups, rage clicks and dead clicks. Free, but it needs an account, because an open export of a live campaign is a scraping target rather than a reader.
Sign up to downloadAlready signed inWhy we publish this
Harvv tells people what their visitors actually did, including when the answer is unflattering. It would be strange to sell that and keep our own numbers private. If the ads do not work, this page will say so.