Dev.to WebDev πŸ›  Dev πŸ‘ 0 πŸ“– 5 min read

I fixed every dead CTA on my blog. Revenue stayed at zero.

I fixed eight call-to-action links on a Saturday night, verified every one against the live page, and my revenue stayed exactly where it was: zero. That is not a failure story. It is what happens when you fix the ceilin

I fixed eight call-to-action links on a Saturday night, verified every one against the live page, and my revenue stayed exactly where it was: zero.

That is not a failure story. It is what happens when you fix the ceiling of a funnel that has no floor. Here are the numbers, because the numbers are the whole point.

The measurement before the fix

My dev.to account had 25 published articles and 468 total views, read from the dev.to API on 2026-11-15. Of those 25 articles, 13 linked to a paid product. The other 12 ended with something vague like "follow me for more" and no path whatsoever.

That means 217 of 468 views β€” 46% of everything this account has ever produced β€” arrived, read, and had nowhere to go. Not a bad offer. No offer.

The cheap fix: append a contextual CTA to each article that lacked one. Not a banner, not a popup. A sentence at the end that answers the next question the reader would have, plus a link.

The verification that matters more than the edit

Eight articles changed. Six of them were re-uploaded through the API, two needed a body patch. Then I did the thing that separates "I edited a file" from "it works":

curl -s -o /dev/null -w '%{http_code} %{redirect_url}' \
  "https://skills.seu.pet/buy/o-agente-que-nao-mente?ref=devto"

First attempt returned 303 with the redirect pointing back at /p/o-agente-que-nao-mente. My first read was "the buy route is broken, it's bouncing every buyer back to the product page."

It was not broken. The route has an anti-bot guard: if the User-Agent cannot plausibly be a browser, the request is redirected to the product page and no checkout session is created. That guard exists because on 24 October there were 100 Stripe sessions in four days with zero payments, clustered between 3 and 5 AM β€” link scanners, not shoppers. A curl with its default UA will always look like a scanner.

With a real browser UA:

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ... Chrome/131.0
-> 303 https://checkout.stripe.com/g/pay/cs_live_...

cs_live_ β€” a real session on the live account. Two SKUs tested, both live. The route was fine the whole time; my probe was wrong.

Rule from this: when you test a purchase path with curl, you are also testing the bot filter. Fake the browser or you will spend an hour debugging a guard that is doing its job.

The number that did not move

After the fix: 21 of 25 articles carry a paid link, and 467 of 468 views now land on an article with a purchase path. Coverage went from 54% to 99.8%.

Paid orders: still zero. Revenue: still R$ 0,00.

The reason is one line from my own store's database, measured the same morning:

Metric Value Source
Human visitors, 30 days 31 orders.db, visitante='humano'
Leads, 30 days 2 same
Paid orders, 30 days 0 Stripe API, payment_status=paid
Stripe sessions, 30 days 558 Stripe /v1/checkout/sessions
Google clicks / impressions 5 / 742 Search Console, 2026-11-15 02:48

Thirty-one humans in thirty days. At a realistic 2–3% session-to-purchase rate, 31 visitors produce between 0.6 and 0.9 orders per month. The expected value rounds to zero, and the measured value is zero. Nothing is broken; the arithmetic simply never had a chance.

The 558 Stripe sessions look like demand and are not. All 558 are open or expired, none has payment_status=paid, none has a customer e-mail, none has a client_reference_id, and the timestamps are spread uniformly across 24 hours. Human purchases cluster. Machine traffic does not.

What the dashboard told me, and what it cost me to believe it

My own OpenPanel funnel for the same 30 days reads:

27 page_view -> 26 checkout_start (96.3%) -> 0 purchase (0.0%)

A 96% view-to-checkout rate is a fantasy, and I wrote the script that emits it. checkout_start fires when the checkout endpoint is hit, and the checkout endpoint gets hit by the sitemap crawler, by my own probes, and by link scanners. A funnel step that any machine can trigger is not a funnel step, it is a counter.

The honest version of that funnel is the one Stripe returns, and Stripe says: 558 attempts, 0 payments, and the attempts were not people.

The uncomfortable conclusion

A conversion-rate problem and a traffic problem produce the same output β€” zero revenue β€” and only one of them is fixable by editing a page. I spent the first part of the week assuming it was the page, because editing a page is something I control.

It was not the page. The page converts fine for the traffic it gets: 26 of 27 visitors opened a checkout, even if the majority of that traffic was automated noise. What is missing is the denominator. Thirty-one people, in a month, across five domains.

So the CTA fix stays β€” it is correct, it is verified, and it removes a real leak. But it is not the unlock, and I am not going to pretend it was.

What I am doing instead

One entry point per article, one contextual exit, and a number I can actually defend. If you are in the same hole, the order that worked for me is:

  1. Prove the purchase path responds with cs_live_ using a browser UA, before writing anything about conversion.
  2. Compare your funnel count to the payment provider's count. If they disagree, the provider is right.
  3. Only then look at the top of the funnel β€” and accept that "no traffic" is a legitimate diagnosis.

If you want the gate that fails a build when a claimed result is not backed by evidence, the AI Test Loop skill is free and it is the tool I use for exactly this:

AI Test Loop β€” free download

If you would rather read the whole method end to end β€” proving the work was done, in fourteen chapters β€” the ebook is here:

O agente que nΓ£o mente β€” R$ 37

And if your funnel reports a rate above 90% on any step between "page loaded" and "money arrived", go check what fires that event. It is probably not a person.

πŸ“° Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.