ad blockerscancellation flowscript blockingcompliance

uBlock Origin and Brave Both Block Tracking Scripts by Default. Some Cancellation Flows Look Exactly Like One.

EasyPrivacy ships on by default in uBlock Origin and Brave. It's built to block third-party tracking scripts — and a cancel-flow widget can look like one.

XY
26 October 2026 · 8 min read

Somewhere between 30% and 38% of your subscribers are running something that blocks third-party scripts by pattern, not by hand-picked blocklist — and for a chunk of them, it's not an extension they chose, it's the browser they're already using. If your cancellation flow is a JavaScript widget loaded from a vendor's domain, that's worth sitting with for a minute, because a cancel-flow widget and a tracking script look identical to the software deciding which one to block.

Key stat
38%
Of active desktop internet users run an ad- or tracker-blocking tool — and two of the most common ones enable tracking-script blocking by default, not as an opt-in
Source: AudienceProject, 2026 ad-blocking penetration data (desktop); GWI, 2026 global internet user survey (31.5% blended)

Most teams that build or buy a cancellation flow test it the way they test everything else: logged in, extensions off, on a clean browser profile. That's exactly the condition under which it will always work. It's also not the condition a meaningful share of your actual subscribers are browsing in, and the failure that shows up when a blocker is running doesn't look like a bug report. It looks like nothing — a button that doesn't do anything, on a page that otherwise looks fine.

Why a cancel-flow widget gets caught by a tracking filter

Filter lists don't read intent. EasyList and EasyPrivacy — the two lists that ship enabled by default in uBlock Origin, the most-installed ad-blocking extension on Chrome and Firefox, and in Brave's built-in Shields, on by default for every Brave install with no extension required — work by matching request patterns against a maintained ruleset. A request to a domain that isn't the page's own, carrying a payload that resembles an analytics beacon or a tracking pixel, gets blocked whether it's selling you something or helping you leave.

A cancellation flow built as a third-party embed checks several of those boxes by design, not by accident. It typically loads from a vendor's own domain or subdomain rather than the merchant's. It often fires an event back to that domain recording which retention offer the subscriber saw and which reason they picked — functionally indistinguishable, to a pattern-matching filter list, from a conversion-tracking pixel. None of that is nefarious. It's also exactly the shape EasyPrivacy exists to catch.

This isn't a hypothetical risk specific to cancellation widgets — it's a documented pattern across almost every third-party overlay tool that works the same way. Intercom's own support team attributes most of its chat-widget blocking directly to EasyList inclusion, and says plainly that it's caught by the tracking-style functionality in its JavaScript, not by anything resembling an ad. Survicate, a survey-widget vendor whose product renders an overlay on a customer's page in essentially the same way a cancellation flow does, states in its own help documentation that ordinary ad blocking doesn't stop its surveys — but EasyPrivacy specifically does, because EasyPrivacy "blocks all software that uses a tracking script," a category it says also catches Google Analytics, Segment, and Google Tag Manager in the same sweep.

Filter layerDefault statusWhat it actually blocks
EasyListOn by default — uBlock Origin, Brave ShieldsAd creative and ad-serving domains; rarely catches a cancel widget directly
EasyPrivacyOn by default — uBlock Origin, Brave ShieldsThird-party tracking-pattern scripts and requests — analytics, pixels, and widgets with the same request shape
Annoyances / Popup OverlaysOptional, not enabled by default, but commonly added by privacy-focused usersCosmetically hides DOM elements matching generic overlay/popup/modal class or id patterns, even if the script already ran
Safari Intelligent Tracking PreventionOn by default in Safari, no extension neededPartitions or restricts cross-site storage for third-party scripts, which can break session continuity for an embedded flow even when it still loads

Notice that two of the four rows need no user action at all. A subscriber doesn't have to know what EasyPrivacy is, seek out an extension, or make any deliberate privacy choice to be running it — they just need to have installed uBlock Origin for the ordinary reason most people do (fewer ads), or to be using Brave, or to be on Safari, which covers a meaningful share of iPhone traffic on its own. None of that correlates with being a sophisticated or adversarial user. It correlates with being an extremely normal one.

Ad- and tracker-blocking adoption, 2026
Desktop (active PC users)38%
Mobile29%
Global blended32%

Source: AudienceProject (desktop), GWI via Backlinko 2026 update (mobile, blended global average).

Two different failures, and they look nothing alike to a developer

A blocked network request and a cosmetically hidden element break a cancellation flow in different ways, and conflating them is how teams end up fixing the wrong one. If EasyPrivacy blocks the script request itself, the flow never initializes at all — there's no error visible to the subscriber, because nothing partially rendered to be visibly broken. The cancel link or button a subscriber clicks simply does nothing, because the event handler that was supposed to attach to it never ran.

If, instead, an optional cosmetic filter is active — the kind bundled in "Annoyances" lists that a meaningful slice of privacy-conscious users add deliberately — the script can run completely successfully, build the entire overlay, and have it hidden anyway, because the filter list matched the container's class name or id against a known pattern for popups and modals. This is the same mechanism that hides a newsletter signup overlay or a cookie-consent banner a user has decided they're tired of seeing. A cancellation modal is a visually similar object to every one of those things, and a generic class name like modal, popup, or overlay gives a cosmetic filter nothing to distinguish it by.

The community-maintained nature of these lists adds a third failure mode that's genuinely outside your control: collateral damage from an unrelated update. Sendbird, a chat infrastructure provider, had its WebSocket domain accidentally added to EasyList in a filter-list update, which broke real-time connections for every user running an EasyList-based blocker — not because Sendbird did anything differently, but because a volunteer-maintained list changed underneath it. The fix was getting the entry removed, not changing anything in Sendbird's own code. There's no engineering practice that fully insures against this one; the best available defense is monitoring for it, which is the same reason any production system watches error rates instead of assuming a dependency never changes.

Why this is worse than an ordinary bug

A normal broken button generates a support ticket, because the subscriber usually tries again, gets frustrated, and tells someone. A blocked cancellation script often doesn't, for a specific reason: a subscriber running a privacy-focused setup is statistically more likely to simply leave and try something else — email support, dig for a different cancel link, or in the worst case, just stop paying attention to the subscription and let a future failed payment or a dispute do the work instead. None of those outcomes route back to you labeled "cancellation flow broken." They route back as a support ticket about something unrelated, a chargeback, or silence.

There's a compliance dimension sitting directly underneath this too. We've written about the FTC's click-to-cancel requirements and California's CARL amendments, both of which require cancellation to be at least as easy as sign-up, in the same medium the subscriber used to enroll. A cancel button that silently fails to do anything for a meaningful share of visitors isn't a UX nitpick under either standard — it's a subscriber who signed up online and, through no fault of their own browsing setup, cannot complete an online cancellation at all. That's a materially different problem than a flow that's merely annoying to use, which is the gap most of the dark-patterns research on cancellation flows is measuring — this failure mode produces the same outcome (a trapped subscriber) with zero intent behind it.

Building a flow that survives being blocked

None of this means abandoning a JavaScript-powered flow — the reason-routed, offer-matched mechanics we've covered in our pause vs. discount vs. downgrade guide genuinely do lift save rates, and that requires a real interactive layer. It means the interactive layer has to be an enhancement on top of something that already works, not the only path that exists.

  • Ship a working fallback link in the initial HTML. A plain, server-rendered cancel link or form that completes the cancellation — without the retention offer, without the reason survey — needs to exist in the page before any JavaScript runs. If the enhanced flow never initializes, the subscriber still has a way out.
  • Host the flow on your own domain, not a vendor subdomain, where you can. A request to your own domain is far less likely to match a third-party-tracking pattern than one to a separate vendor's hostname, even if the code behind it is identical.
  • Avoid generic container names. Naming your overlay's wrapper modal, popup-container, or overlay gives cosmetic annoyance filters an easy match. A specific, product-named class is both better engineering practice and quietly safer here.
  • Test with blockers on, not just with them off. Run your actual cancellation flow in a fresh profile with uBlock Origin's default lists enabled, and separately in Brave with Shields at its default setting. If the cancel action doesn't complete in either case, you've found the gap before a subscriber did.
  • Watch flow-initialization rate as its own metric, separate from completion rate. A completion-rate dashboard only tells you about subscribers the flow successfully loaded for. The gap between "visited the cancel page" and "the flow actually mounted" is where blocked requests hide, and most teams aren't instrumenting that gap at all.

This is the same build philosophy behind the accessibility gaps we've written about in cancellation flows generally: a flow that only works under one specific, idealized set of browsing conditions is going to silently fail for a predictable, non-trivial share of the people who reach it, and the fix in both cases is the same — a plain, functional baseline that an enhanced experience sits on top of, not a single JavaScript-dependent path with no way out if any part of it doesn't execute. If you're running a cancellation flow as a third-party embed today, the fastest way to find out if this is already costing you something is the oldest trick in web development: open it in a fresh browser profile with an ad blocker turned on, and see whether the button still works. For a meaningful share of your subscribers, that's not a hypothetical test — it's the browser they already have open.

Frequently asked questions

Can ad blockers actually break a cancellation flow?+

Yes, through two different mechanisms. A network-level filter list like EasyPrivacy can block the script request outright before it ever loads, which means the flow never initializes. A cosmetic filter — the kind bundled in optional "Annoyances" lists — can hide the rendered overlay with CSS even after the script runs, if its container matches a generic class or id pattern like modal, popup, or overlay. Survicate's own help documentation confirms the first case directly: its survey widget, which runs the same way a cancellation overlay does, doesn't show up for users who've enabled EasyPrivacy.

Is EasyPrivacy actually on by default, or do users have to turn it on?+

It's on by default in both of the two most common ways people get ad blocking without actively hunting for a specific extension. uBlock Origin — the most-installed ad-blocking extension on both Chrome and Firefox — ships with EasyList, EasyPrivacy, Peter Lowe's list, and its own lists enabled out of the box, with no setup required. Brave, a browser rather than an extension, applies filter lists from the EasyList and EasyPrivacy projects as part of Shields, on by default for every installation. Neither requires a user to know what a tracking script is or to opt into blocking one.

Why would a cancellation widget get caught by a tracking filter list in the first place?+

Filter lists like EasyPrivacy don't inspect what a script does for the customer — they match patterns: a third-party domain that isn't the page's own, a request shape that resembles an analytics beacon, a script loaded asynchronously from a vendor's CDN rather than the merchant's own domain. A cancellation flow that loads from a vendor's subdomain, tracks which offer a subscriber saw, or reports back which reason they picked, matches several of those patterns even though none of it is advertising. Intercom's own support team gives the same explanation for why its chat widget gets caught: it's not that Intercom serves ads, it's that the JavaScript looks structurally like tracking code to a list built to catch tracking code.

What should actually happen when the script fails to load?+

The subscriber should still be able to cancel. That means the cancel action can't depend entirely on JavaScript executing successfully — there needs to be a real, working link or form in the page's initial HTML that completes the cancellation (even without a retention offer) if the enhanced flow never initializes. Treating the JS-powered flow as a progressive enhancement on top of a working fallback, rather than the only path to cancelling, is what keeps a blocked script from turning into a subscriber who can't get out — which is its own compliance problem under click-to-cancel rules, not just a lost save opportunity.

Try CancelFlow

Stop losing subscribers today

One script tag. One function call. A live cancellation flow in under 10 minutes.

Start free trial →
← All postsHome