From Machine Learning Research: Cost-Aware Tracker Blocking in Firefox

Data Exploration and Visualization

The Prediction Gap

Firefox’s Enhanced Tracking Protection blocks third-party tracker requests before they complete. At block time, the browser observes a feature vector xXpre\mathbf{x} \in \mathcal{X}_{\text{pre}}: the request URL, resource type, initiator, priority, and other metadata available from the network stack. The response quantities --- transfer size, download duration, server timing --- are structurally unobservable. They never arrive. The product goal is to predict transfer size yR0y \in \mathbb{R}_{\geq 0} from x\mathbf{x} alone, so the privacy dashboard can report concrete bandwidth savings rather than a flat count of blocked requests.

This is not a missing-data problem. The response is not censored, dropout, or partially observed --- it is prevented by design. It is not counterfactual estimation: we are not asking what would have happened under a different treatment assignment. And it is not standard domain adaptation: the training and deployment distributions differ in P(X)P(X) but share P(YX)P(Y \mid X), since transfer size is server-determined. The same URL returns the same payload whether Chrome or Firefox issues the request. Training on HTTP Archive data (collected by Chrome) and deploying in Firefox constitutes covariate shift, not concept drift.

The formal task:

y^=f(x),xXpre,yR0\hat{y} = f(\mathbf{x}), \quad \mathbf{x} \in \mathcal{X}_{\text{pre}}, \quad y \in \mathbb{R}_{\geq 0}

where ff is learned from completed requests in the HTTP Archive and applied to requests that Firefox blocks before completion.

Why Per-Domain Scoring Fails

CPU cost vs network cost scatter plot showing target independence
CPU cost vs network cost across requests. The two targets are largely independent.

The naive approach assigns each tracker domain a static cost score based on aggregated HTTP Archive data. This has a structural limitation: the same domain serves resources of vastly different sizes. googletagmanager.com/gtag/js returns a 93KB script bundle; googletagmanager.com/collect returns a 0-byte beacon. A domain-level median cannot distinguish between these.

Within-domain transfer size variance
Within-domain transfer size variance.

The within-domain coefficient of variation for transfer_size quantifies this heterogeneity: median 0.94, 90th percentile 3.00. Most tracker domains exhibit order-of-magnitude variation in transfer size across their request populations. By contrast, TTFB and load_time show low within-domain variance (CV 0.38), indicating these quantities are network-dominated and not URL-predictable. Transfer size is the right target for a URL-conditioned model.

Lookup Table Ceiling

Before introducing a model, we establish the accuracy ceiling of progressively more granular lookup tables on the test set.

LUT accuracy by granularity vs model
Lookup-table accuracy by granularity, compared against the model.
LUT granularitySizeMAE (bytes)
Global median<1 B19,905
Domain median88 KB9,008
Domain + resource type114 KB6,802
Domain + URL path187 MB4,326

Domain identity alone roughly halves the error. Adding resource type sharpens it further to a 114KB table that is the strongest deployable lookup. Adding the exact URL path pushes MAE down to 4,326, but the table balloons to 187MB at full scale --- and 75% of unique test paths are unseen in training, even within the same crawl month. A path-level table is infeasible in production and immediately stale as tracker SDKs update their URL structures. The model reaches a 4,246 MAE --- a 37.6% reduction over the deployed domain+type LUT, and within 2% of the non-deployable path table at a fraction of its size. A model must generalize from URL structure rather than memorize specific paths.

Data

Transfer size distribution and breakdown by resource type
Transfer size distribution and breakdown by resource type.

Training data is drawn from the HTTP Archive June 2024 crawl (mobile client). The source table httparchive.crawl.requests covers third-party tracker requests in five Disconnect list categories: advertising, analytics, social, tag-manager, and consent-provider.

We extract a deterministic sample via hash bucketing:

txt
MOD(ABS(FARM_FINGERPRINT(page || url)), 100) = 0

This yields 3,490,824 requests across 3,723 domains, covering 92.5% of requests and 98.6% of bytes in the trained categories. Deterministic sampling ensures reproducibility and avoids selection bias --- any request whose (page, URL) pair hashes to bucket 0 is included, regardless of domain or category.

Target distribution. The transfer size distribution is bimodal: 39.5% of requests are exact zeros (beacons returning empty responses), with a secondary mode around 90KB (JavaScript bundles). The median is 43 bytes, the mean 13,607 bytes, and the maximum 14MB. This zero-inflation and extreme right skew motivate the Tweedie loss explored in Article 2.

Bytes concentrate where requests do not. The categories that dominate request counts are not the ones that dominate bytes. A 26-domain tag-manager category carries 41% of blocked bytes from just 6% of requests, while advertising --- 66.5% of requests --- accounts for only 17.8% of bytes. A flat per-request count badly mis-estimates the bandwidth a user actually saves, which is exactly why the dashboard needs a per-request size model rather than a category tally.

Train/val/test split. 70/15/15 by random row sampling. Row-level splitting matches the deployment scenario: Firefox will have HTTP Archive statistics for all Disconnect list domains at inference time, so domain identity is a known feature at prediction time. There is no need for domain-level holdout.

Feature Engineering

Eighty-five features organized into five groups, all observable at Firefox’s block time.

Domain identity (2 features)

Target-encoded statistics from training data: the domain’s median transfer_bytes, and the (domain, resource_type) pair’s median transfer_bytes. These replace the domain name with a meaningful numeric signal --- integer encoding is inappropriate because tree models would treat domain codes as ordinal. Target encoding is recomputed per cross-validation fold to prevent leakage.

URL structure (12 features)

Path depth (number of / segments), total URL length, query parameter count, file extension (grouped: js, gif, png, jpg, html, php, json, css, other, none), path length, and query string length. These capture coarse structural properties of the URL without memorizing specific paths.

URL content via TF-IDF + SVD (50 features)

The URL path is tokenized on delimiters (/, ., ?, &, =, -, _) and camelCase boundaries. We fit a TF-IDF vectorizer with sublinear term frequency, unigram + bigram vocabulary (50K terms, minimum document frequency 5), then reduce to 50 dimensions via truncated SVD, explaining 54.5% of total variance.

The leading SVD components are semantically interpretable. Component 1 separates /collect endpoints (beacons, near-zero transfer) from script-serving paths. Component 2 captures /gtag/js and analytics.js patterns (large JavaScript bundles). This decomposition gives the model a continuous representation of URL semantics without requiring exact path matching.

Request metadata (10 features)

Resource type (one-hot: script, image, other, html, text, css, video, xml, font), initiator type (one-hot: script, parser, other, preflight), Chrome priority (ordinal 0—4), HTTP method, HTTP version, waterfall index, and HTTPS flag.

Regex pattern indicators (6 features)

Binary indicators from regular expressions applied to the URL path, encoding known tracker URL conventions:

FeaturePatternSignal
path_has_js\.js|sdk|gtm|gtagJavaScript bundles
path_has_collectcollect|beacon|pixel|trackBeacons (zero-byte)
path_has_image\.gif|\.png|pixel|1x1Tracking pixels
path_has_syncsync|match|cookieCookie-syncing
path_has_ad/ad/|adserver|pageadAd serving
path_has_apiapiAPI endpoints

These act as coarse priors that the tree model can refine. They are redundant with the TF-IDF representation by design: the regex features provide explicit signal for known patterns, while TF-IDF captures the long tail.

Target. Raw transfer_bytes with no log transform. Predictions are clipped to 0\geq 0.


The next article covers model selection, Tweedie loss, and evaluation, where these features are combined with ten model architectures and assessed on both per-request accuracy and the aggregation accuracy that matters for the product.