Every World Cup goal as a point of light. Every shot that missed. The expected goal beneath each one. The rivalries that built the game.
Firestorm — watch goals fall chronologically. Explore — filter, search, compare. Evolution — four eras side by side.
Goal Constellation is the first module of the World Cup Memory Machine, a multi-piece data project on the history of men's FIFA World Cups (1930–2022). This methodology section documents every source, transformation and acknowledged limitation. Transparency is a feature, not a footnote.
Tier A — exact coordinates (390 goals, 88.4%): sourced from StatsBomb Open Data, competition_id 43 (FIFA World Cup), seasons currently published: 1958, 1962, 1970, 1974, 1986, 1990, 2018, 2022. Includes (x, y) location in StatsBomb's 120×80 pitch reference frame, body part, shot type, technique and StatsBomb xG model output where computed.
Tier B — reconstructed zone (51 goals, 11.6%): manually curated from FIFA archival reports, contemporary press footage and Wikipedia structured tables for editions not yet in open data: 1930, 1934, 1938, 1950, 1954, 1966, 1978, 1982, 1994, 1998, 2002, 2006, 2010, 2014. Coordinates approximate the zone where the goal was scored (six-yard box, penalty area, edge of area, midfield, etc.), not the precise pixel. Each entry carries a narrative note traceable to public footage.
Shots (1,958 misses): StatsBomb event data from 2018 + 2022 only (the two tournaments with complete shot coverage). Filtered to outcomes Saved, Saved Off Target, Saved to Post, Post, Off T, Wayward. Blocked shots excluded — too common, less narratively informative.
StatsBomb publishes (x, y) where x ∈ [0, 120] is the length axis (x=120 is opponent goal line) and y ∈ [0, 80] is the width axis. The constellation uses a normalized pitch in percent: x ∈ [0, 100] lateral, py ∈ [0, 100] longitudinal, with py=100 at the attacking goal. Transform: x' = sb_y / 80 × 100, py' = sb_x / 120 × 100. All teams are unified to attack the top goal regardless of original home/away orientation.
scorer + year + minute. Same penalty always renders at the same pixel; never random.Tier A goals: solid white/cool/warm dots according to phase (group/knockout/final), opacity 0.85. Tier B goals: warm-orange translucent dots with diffused halo, opacity 0.55. Posts: red empty rings. Saves: dim blue-grey filled circles, opacity 0.28. Off-target: even dimmer dark grey, opacity 0.18. xG mode overrides phase colouring with a purple-to-warm gradient based on each goal's expected probability.
xG (expected goals) values are from StatsBomb's proprietary model: probability a shot becomes a goal given its location, context, body part, defensive pressure and other factors. Values range 0.001 (impossible) to 0.99 (sitter). 325 of 441 goals in this dataset carry xG — only those from 2018 and 2022 events with explicit statsbomb_xg field. The "Wonder goals" preset filters xG < 0.05 (less than 1-in-20 chance).
Single-file HTML/CSS/JS. No build step, no framework. Canvas 2D for goal rendering with device pixel ratio for retina sharpness. SVG for the pitch geometry (sharp lines at any scale). Web Audio API for goal tones (sine waves, three pitches keyed to phase). URL state encoded in query string; current view fully reproducible from URL alone. ~308 KB total payload including 441 goals + 1,958 misses inline.