All case studies

Case study

3,338 failures in 30 days. Nine in ten raised no error.

AdaptlyPost

Social media scheduling and publishing SaaS

13 July to 13 August 2026

The AdaptlyPost landing page

75,167

recordings analyzed

13 July to 13 August 2026

3,338

real failures

4.4% of everything analyzed

66

distinct causes

1 critical, 7 high, 15 medium, 43 low

90%

raised no error

3,019 of 3,338 had no console or network error

In short

Flowsery analyzed 75,167 session recordings from adaptlypost.com in one month and found 3,338 real failures from 66 distinct causes. Nine in ten of those failures raised no console or network error, and sessions that did carry an error were a real failure 2.8% of the time. Four findings follow, ordered by what they cost rather than how often they fired.

Between 13 July and 13 August 2026, Flowsery analyzed 75,167 session recordings from adaptlypost.com and flagged 3,338 of them as a real failure for the visitor. Grouping by cause collapsed those into 66 distinct bugs: one critical, seven high, fifteen medium, forty-three low.

3,019 of the 3,338 failures carried no console error and no network error. Nine in ten. In the same month, 11,598 sessions did carry an error, and 319 of those were a real failure. An error monitor would have paged on the wrong eleven thousand sessions and slept through the three thousand that mattered.

The four findings below are ordered by what they cost, not by how often they fired.

About AdaptlyPost

AdaptlyPost is a social media scheduler sold on a 7-day trial. It publishes in five languages and has a blog with a glossary that Google indexes. AdaptlyPost and Flowsery have the same founder.

The AdaptlyPost home page
The AdaptlyPost home page.

How the study ran

Session recording had been running on the site for about two months before AI analysis switched on, on 13 July 2026. This study covers exactly one month from that date. The 75,167 recordings are that backlog plus everything live traffic produced while the pipeline ran.

A recording counts as a failure when the visitor tried to do something the page offered and the page did not deliver it. A card decline is not a failure, because a bank saying no is not a bug. A payment button that does nothing when clicked is. Each failure carries a severity, reproduction steps and a link to the recording. Failures with the same cause are grouped, which is how 3,338 became 66.

From recordings to causes
Recordings analyzed75,167
Real failures3,338 · 4.4%
Distinct causes66
66 causes by severity
1 critical7 high15 medium43 low
Grouping by cause turns 3,338 sessions into 66 items.

Finding 1: the checkout blocked payments in five different ways

Seven sessions in the window ended with the site itself stopping a payment, in five separate ways.

What visitors saw at the payment step
1
A server error on the trial button. On the Portuguese locale, the visitor clicks "start free trial" and the request fails on the server. Nothing useful appears on screen. Four retries, then they leave.
2
"Internal server error" on Start Free Trial. The visitor retries, switches billing cycle, tries PayPal instead, and never comes back.
3
A dead PayPal button. Billing details filled in, rapid clicks on "Pay with PayPal", no response, session over.
4
An upgrade refused by a billing rule. An existing customer tries to move to a bigger plan and gets "Payment Failed", because the subscription system will not change the start date of a plan that has already been charged. Five sessions. The longest runs 34 minutes of reopening the payment overlay and clicking before they give up.
5
A 404 on the upgrade page. On one locale the upgrade route did not exist. The visitor wanders through home, dashboard and billing, never finds a way to pay more, and leaves.
Quoted strings are what was on the visitor's screen.

Two of the five, the server errors, would show up in an error tracker. The billing rule is the payment system working as designed, refusing a customer who wants to pay more. The dead PayPal button throws nothing at all. The missing upgrade page is a 404, and 404s are background noise on every site.

The one critical issue was on the French sign-in page. A visitor submitted the form and the page printed "400: Bad Request", most likely because the bot-check widget never rendered. They left. A sign-in form should say "Invalid email or password", not show an HTTP status.

Finding 2: one control swallowed clicks on 17 routes

48 sessions across 17 different routes show the same pattern. A visitor clicks a selector, nothing visible happens, they click again, and again, and then they leave.

It is one component, reused on every page that asks the visitor to pick something.

  • On the German post editor, a signed-in customer opens Pinterest settings and clicks "choose board" repeatedly. The dropdown never opens. They click "post now" anyway. The post never goes out.
  • On the AI post generator, "Select Platform" produces no response across repeated clicks. The visitor gives up and clicks the page title.
  • On the influencer rate calculator, the engagement tier button ignores six seconds of hard clicking before it finally registers.
  • On the username availability checker, three clicks on the platform list do nothing. The visitor never reaches "Check Availability".

None of these throw. Every one is a click handler firing into a component whose visual state never updates, so the visitor cannot tell "ignored" from "broken". Rage clicks are the only signal, and that signal exists only inside a recording.

One selector, one visitor, six seconds
0s6s
10clicks
0screen changes
0errors logged
Ten clicks in six seconds on the engagement tier selector of the influencer rate calculator. Nothing on screen changed and nothing was logged.

Finding 3: the translations that did not load

AdaptlyPost publishes in five languages, and the seams show. Nine sessions in the window, on four routes, ended with the visitor looking at something that was never meant to be text: a translation key, an error page in the wrong language, or a placeholder.

What the visitor sawSessionsWhereError signal
Translation keys as page copy5/en/media-kitNone
A 500 page after switching language2Home pageHTTP 500
Locale JSON files returning 4042Reading level analyzer, a blog postBackground 404s

The media kit page is the clearest case. Five visitors landed on it and saw "brandFacts.mediaKit.title" and "brandFacts.mediaKit.description" where the headline and copy should be. None of them clicked anything. The page returned 200 with no console error, so nothing flagged it.

What five visitors saw on /en/media-kit
adaptlypost.com/en/media-kit
brandFacts.mediaKit.eyebrow brandFacts.mediaKit.title brandFacts.mediaKit.description brandFacts.mediaKit.assetsDescription
Every string on the page is the key the translation file should have resolved. The page returned 200.

Switching language to Portuguese produced a 500 page reading "Ocorreu um erro inesperado". The retry button loaded the Portuguese home page, and 17 minutes later the same 500 came back. Another visitor got a 500 overlay on the English home page whose retry button read "Intentar otra vez", Spanish on an English page.

The language switcher also requests locale files that do not exist. One session on the reading level analyzer logged 24 background 404s for files like /locales/fr/gdpr.json. Switching a blog post to Spanish did the same.

After the window closed, on 18 August, the Spanish version of the safe-zone guide shipped with the placeholder "Original text" as its main heading.

None of this throws in a way that helps. The raw keys and the placeholder are a page rendering the wrong string. The locale 404s are background requests nobody watches. Only the 500 pages would page anyone, and one of them cleared itself on retry.

Finding 4: the glossary URLs that 404

The biggest finding by session count, and the dullest, which is how it lasted this long.

AdaptlyPost's glossary articles live at /blog/<slug>. At some point they were published, and then indexed, at /blog/glossary-<slug>. The site has no route for the prefixed form.

  • 382 distinct /blog/glossary-* URLs turned up in failures, across 1,287 sessions
  • Most of that traffic arrived straight from a search result
  • Ten sampled slugs checked against the content directory: eight of the ten articles exist, at the unprefixed URL

The articles exist and rank. The URL Google indexed points at nothing, and one redirect rule would fix it.

The glossary 404s in numbers
382distinct /blog/glossary-* URLs returning 404
1,287sessions that landed on one
8 of 10sampled articles exist at the unprefixed URL
1redirect rule to fix it
Most of those sessions arrived straight from a search result.

What error monitoring saw

Of the 75,167 recordings analyzed, 11,598 carried a console or network error. 319 of those were a real, visitor-visible failure. That is 2.8% precision. Open replays filtered by "has errors" and 97 of every 100 will be a blocked tracker or a cancelled fetch.

The other direction is worse. Of the 3,338 real failures, 3,019 carried no error at all. Most of what is above lives in that 90%: the dead PayPal button, the billing rule, the swallowed clicks, the media kit page printing its translation keys.

The error flag as a detector
Flagged sessions that were real failures2.8%
Real failures the flag missed90%
11,598 flagged, 319 real. 3,338 real, 3,019 unflagged. Wrong in both directions.

From a replay to a reviewable change

The day after the window closed, Flowsery's agent picked up the engagement-selector issue from Finding 2, read the recording, and opened a pull request against the AdaptlyPost codebase.

Its diagnosis: tapping an option updated state the visitor could not see, so nothing on screen changed and the recorder caught ten unanswered clicks. The change rewires the control to behave like the selectors on the site that already work. One commit, one file.

From rage click to pull request
Session recorded
Issue deduplicated
Agent reads the replay
Change opened for review
Nobody asked for it and nobody opened the replay.

Where things stand

FindingSessions in windowError signalStatus
Checkout blocked payments, five ways72 of 5 modesFixed
Raw 400 on sign-in1HTTP 400Fixed
Selector swallowed clicks48, on 17 routesNoneFixed
Translations that did not load9, on 4 routes3 of 9Fixed
Glossary URLs returning 4041,287HTTP 404Fixed

What changed in the month is the shape of the backlog. Before 13 July it was whatever somebody happened to notice. After, it is a ranked list where every entry carries a session count, a first-seen date, a severity, reproduction steps and a recording to open.

"We should look at the checkout" loses to a roadmap item. "Seven people tried to pay and the checkout stopped them, in five different ways, and here is the recording of one" does not.

What generalizes

Same month, two views
What the stack saw
  • A 200 with a fully rendered page
  • A 200 carrying an error string
  • A click handler that fired normally
  • 11,598 flagged sessions, 319 of them real
What the recordings saw
  • A headline that reads brandFacts.mediaKit.title
  • A paying customer refused an upgrade
  • Ten unanswered clicks, then the visitor leaving
  • 3,338 real failures, 66 distinct causes
Ninety percent of the right-hand column is invisible to the left.

Rank by cost, not by volume. The glossary 404s touched 1,287 sessions and the checkout bugs touched seven, and the checkout bugs are worth more.

Treat silent controls as bugs with no telemetry. A dead dropdown throws nothing, logs nothing and returns 200. The only evidence it exists is a person clicking the same spot ten times, and that evidence lives in the recording or nowhere.

Read what the page shows, not what the server returned. A headline that says brandFacts.mediaKit.title is a 200 with no console error, and so is a Spanish page whose main heading is "Original text". Neither shows up as a funnel drop, because the visitor never entered the funnel.

See what your error dashboard is missing

The same analysis that ran on AdaptlyPost, on your own site.