Build-up & Directness
Summary
Per-team-season aggregates describing how teams move the ball forward. The standing pass-accuracy number on the team-stats pages can't tell the difference between a possession side knocking it sideways accurately and a direct side hitting completed long balls — both score high on accuracy. The build-up page splits the question into long-ball share, forward-zone pass share, and a per-match own-to-opposition long-pass rate.
A composite directness index is z-scored within each season (mean of the three rate z-scores) so positive = more direct than the league average for that season. The index is bounded the same way every season, but is not directly comparable across seasons in absolute terms.
The feature lives at /analysis/build-up and the underlying ratios are
also exposed on the team quadrant page (Directness, Forward vs Backward).
Inputs
| Stored column | SDP key | Meaning |
|---|---|---|
total_pass |
totalPass |
Pass attempts. Denominator for accuracy + long-ball share. |
accurate_pass |
accuratePass |
Completed passes. Denominator for fwd-zone share. |
total_long_balls |
totalLongBalls |
Long balls attempted. |
accurate_long_balls |
accurateLongBalls |
Long balls completed. |
long_pass_own_to_opp |
longPassOwnToOpp |
Long passes that crossed the halfway line. |
open_play_pass |
openPlayPass |
Open-play passes (excludes set pieces). |
accurate_fwd_zone_pass |
accurateFwdZonePass |
Completed passes into the forward zone. |
backward_pass |
backwardPass |
Backward passes. |
fwd_pass |
fwdPass |
Forward passes. |
directness_index |
derived | Z-scored composite (within season). See below. |
Sums are over regular-season team-matches only
(matches.is_playoff = 0), matching every other team-season aggregate.
All nine keys are present in every season the feed covers (2019-2025+), so there is no per-season metric availability gap.
Derived rates
Computed server-side on read from the stored counters. None when the
denominator is zero.
- Long-ball share =
total_long_balls / total_pass— share of attempted passes that were long. The headline directness signal. - Long-ball accuracy =
accurate_long_balls / total_long_balls— informational; used to disambiguate "direct and accurate" from "direct and chaotic" on the quadrant. - Forward-zone share =
accurate_fwd_zone_pass / accurate_pass— share of completed passes that went into the forward zone. Read as "how vertical is the build-up". - Own → Opp / match =
long_pass_own_to_opp / matches— long passes that crossed the halfway line, per match. The "switch / over the top" signal. No clean share denominator (see caveats). - Fwd / Back ratio =
fwd_pass / backward_pass— unitless directness check; immune to volume. - Pass accuracy =
accurate_pass / total_pass— exposed for context so users can see the standing pass-accuracy alongside directness on the same page.
Directness index
A composite axis for cross-team comparison within a season:
directness_index = mean(
z(long_ball_share),
z(forward_zone_share),
z(own_to_opp_per_match),
)
Z-scores are computed within each season's cohort (typically 8 teams). Components with a zero standard deviation in a given season (rare) are dropped from that season's average rather than treated as 0, so a team isn't penalised for a flat metric.
Range varies by season but typically [−1.5, +1.5]. Positive = more direct than the league mean for that season.
Data caveats
- Z-scored within season, so not cross-season-comparable in absolute
terms. A team's
directness_indexof +1.0 in 2024 is not "the same" as +1.0 in 2025; both mean "1 SD more direct than that season's league." Same caveat asteam_stylealready documents. Within a season, the ranking is comparable directly. The underlying rates (long-ball share, fwd-zone share) are absolute and cross-season- comparable. longPassOwnToOpphas no clean share denominator. The feed doesn't separate "long passes attempted from own half" from all longs, so we can't compute a "share of own-half longs that crossed halfway" rate. We surface a per-match volume instead. This per-match rate is sensitive to tempo (a team that gets the ball more in their own half will hit more own-to-opp longs), but it's the honest available signal.- Forward-zone share denominator is
accurate_pass, nottotal_pass. SDP only emits the accurate count for fwd-zone passes, so the matching denominator is also accurate-only. This means the two share ratios on the page (long-ball share vs fwd-zone share) live on different denominators — read them independently, not as add-up shares. - Open-play vs all passes.
total_passincludes set-piece deliveries (corners, free-kick crosses), so a team that plays a lot of set pieces will have a slightly inflated long-ball share. The effect is small in CPL (set-pieces account for under 5% of passes most seasons) but worth noting. - 2020 Island Games had 7-11 matches per team in a neutral bubble without travel, rest variance, or crowds. Rows from 2020 are flagged on the page and should not be compared directly to other seasons.
Why this is z-scored but pressing isn't
Pressing has a natural bounded composite ((att − def) / total is
already in [−1, 1]) so z-scoring would hide a clean signal behind a
dimensionless score. Directness has no comparable natural composite —
the three component rates live on different denominators (total_pass,
accurate_pass, matches), so z-scoring is the only honest way to
combine them into a single ranking axis. The trade-off is the loss of
absolute cross-season comparability.