Home / Blog / Testing consent blocking in CI: catching tracker leaks before they deploy

Testing consent blocking in CI: catching tracker leaks before they deploy

Tracker leaks are regressions, so they should be caught the way regressions are caught: in CI. A test that loads the site under a "reject all" consent state, records every network request, and fails the build when an unconsented tracker fires will catch the leaks that manual audits miss. It takes an afternoon to set up and it runs on every deploy forever.

What the test does

The core loop is simple. Launch a headless browser against the deploy preview, set the consent cookie or local storage to the "reject all" state before the first page load, navigate through the key templates, and collect all network requests. Then compare the request hostnames against an allowlist of trackers mapped to consent categories. Any request to a known tracker that lacks a category, or fires while its category is declined, fails the test.

Setting the consent state before load

The trick is getting the state in place before any tracking code runs. The reliable approach is to seed the consent storage directly: set the cookie or localStorage key your CMP uses in the browser context before navigation. That avoids racing the banner. If the CMP reads consent asynchronously on boot, the test should also wait for the banner's initialization to settle before navigating, or the test will report false passes on the first paint.

The allowlist, not a denylist

Denyists rot. New trackers appear constantly, and a test that only blocks known-bad hostnames will pass a leak to a tracker added last week. The allowlist approach inverts the logic: the test knows the trackers the site is supposed to have and their categories, and anything else firing under "reject all" is a failure. Unknown hostnames get flagged for review. The allowlist is the tracker inventory from the consent documentation, kept in the same repo as the test.

What to navigate

Cover the templates, not every page: homepage, a content page, a conversion page, and one page with each heavy embed. Lazy-loaded components are the classic leak source, so scroll the full page and wait for idle network before asserting. If the site is a single-page app, also navigate between routes in the same session, because route changes are where consent state most often gets dropped.

Making failures actionable

A failing test should name the hostname, the page where it fired, and the consent category it should have waited for. "tracker.example.net fired on /pricing under reject-all, expected category: marketing" is a ticket someone can close in ten minutes. "consent test failed" is a ticket that gets ignored until the sprint ends. Wire the test into the deploy pipeline as a blocking check and consent stops being something the team audits quarterly and starts being something the build enforces daily.

Keeping the test from going flaky

Network-based tests are flaky by nature: third-party scripts time out, CDNs hiccup, and a test that fails randomly gets disabled by the team within a month. Harden the consent test the way you harden any integration test. Retry transient network failures once before failing, set generous timeouts for third-party script loads, and distinguish infrastructure flakes from real violations in the output. A test that cries wolf about a slow ad server will be ignored when it reports a real leak.

Run the consent test against the deploy preview rather than production, so it gates the deploy instead of reporting on it after the fact. Keep the allowlist in the same repository as the site code so tracker additions go through code review, where someone can ask whether the new tool has a consent category. The test is only as good as the inventory it checks against, and the inventory is only as good as the process that updates it. Put both in version control and the whole system maintains itself.

Get a free consent audit of your website

Free consent audit