Bounce tracking (A → B → A)

A stateless redirect bounce, for exercising Firefox's Bounce Tracking Protection (BTP) against the Navigational Tracking Mitigations draft. You click a link on site A, site B sends you straight back to A, and B never sees a click of its own — so B is an intermediary in a short-lived redirect and gets added to the bounce tracker candidate list.

A ? → click → B ? → 302 → A ?

1. Bounce

How B bounces you back

Start bounce

Clicking is just the convenient way in, not a requirement — an extended navigation opens on any top-level navigation with no record already running, so a scripted unactivated hop from A gets B classified too. Repeat as often as you like — B stays a candidate, and the round trip count only confirms the loop is working. What you must not do is click or type anything on site B: user interaction there exempts it for 45 days.

2. Verify in Firefox

Site B gets classified as soon as the extended navigation ends, and the web console on this page logs a warning naming it. To inspect and force the purge, paste these into the Browser Toolbox (Ctrl/Cmd+Alt+Shift+I), not the page console. Run the first one first; the rest reuse its btp.

Not critical, but recommended: use a throwaway profile (about:profilesCreate a New ProfileLaunch profile in new browser). Forcing the purge sets mode to 1, which takes that profile out of dry-run and has BTP purge real cookies and site data for every bounce tracker it classifies, not just this demo's — until you run the reset at the end.

Get the service
var btp = Cc["@mozilla.org/bounce-tracking-protection;1"]
  .getService(Ci.nsIBounceTrackingProtection);
Is site B classified? — it should be in here
btp.testGetBounceTrackerCandidateHosts({}).map(e => e.siteHost)
Is site B exempt? — it must NOT be in here
btp.testGetUserActivationHosts({}).map(e => e.siteHost)
Force the purge now
// Purging skips any candidate still inside its grace period, and only mode 1
// writes the purge log, so set both or the last line quietly returns nothing.
Services.prefs.setIntPref(
  "privacy.bounceTrackingProtection.bounceTrackingGracePeriodSec", 0);
Services.prefs.setIntPref("privacy.bounceTrackingProtection.mode", 1);

await btp.testRunPurgeBounceTrackers();
btp.testGetRecentlyPurgedTrackers({}).map(e => e.siteHost)
Reset — clears state and restores both prefs
btp.clearAll();

// clearUserPref, not a hardcoded value: the defaults differ per channel.
Services.prefs.clearUserPref(
  "privacy.bounceTrackingProtection.bounceTrackingGracePeriodSec");
Services.prefs.clearUserPref("privacy.bounceTrackingProtection.mode")

Verbose per-navigation logging is available by launching with MOZ_LOG=BounceTrackingProtection:5 (:3 for classification and purging only).

The privacy.bounceTrackingProtection.* prefs, and how their defaults differ per channel, are documented under Preferences in the BTP docs.