The Hockey Play-by-Play Tracker records a game from your team's point of view and follows one player by jersey number. You capture a play with a tap, then add its details when there is time. The same record produces the score, shot statistics, faceoff results, penalties, shifts, and time on ice.

The tracker runs in your browser and saves the current game on that device. You can download the complete game as JSON, reopen it later, and export team or player data for further analysis.

This guide describes the current application, including Unknown faceoff results and penalty entry during pauses. The examples use North Stars, their opponent Windsor, and tracked player #17. The controls display the names you enter for your own game.

Quick start: from setup to a saved game

  1. Open the tracker and enter the game date, opponent, and tracked jersey number. Add your team's name so the controls are easy to identify.
  2. Set the number of periods and each period's duration, then choose Create game.
  3. Choose Start Period 1. The period is active, with its clock paused at the full duration.
  4. Set the tracked player ON ICE if they are on the ice for the opening play.
  5. At puck drop, choose Start clock. This records one faceoff with an Unknown result. Alternatively, choose the winning team's faceoff button to start the clock with a known result.
  6. During play, use Shot, Goal, and Hit under the appropriate team's name. Toggle the tracked player when they enter or leave the ice.
  7. At a whistle, choose a reason under Stop play. Goals pause play automatically. Enter any penalties in the panel that appears while the clock is paused.
  8. When play starts again, choose Resume clock, a named faceoff winner, or Unknown. Each choice records one faceoff and restarts the clocks.
  9. Review the event cards, fill in missing details, and use Summary to inspect team and player statistics.
  10. At the end, choose End game, then open Game files and download the full game JSON. This is the file to keep if you want to reopen the game.

1. Set up the game

The Game settings view contains the information that identifies the game and defines its periods.

Setting How to use it
Game date The calendar date of the game. It also appears in exports.
Game type Choose Regular, Friendly, Tournament, Exhibition, Playoff, or Other. This is a descriptive label; configure period lengths and penalties yourself.
Your team Optional, but useful: this name appears on the scoreboard, recording controls, event cards, and summary. A blank name displays as Your team.
Opponent Required. Enter the name you want to see on the scoreboard and opponent controls.
Tracked player number A jersey number from 0 to 999. The application follows one player throughout this record.
Number of periods Configure between 1 and 20 periods. You can include an additional period if your game needs overtime.
Period lengths Enter each duration as minutes:seconds, such as 15:00, 20:00, or 5:00. Each period can last up to 120 minutes.

The default setup contains three 15-minute periods. Change these before tracking if your competition uses different durations.

Once a period has started, its configured duration is locked. Future periods remain editable. The tracked jersey number locks once the first event has been recorded, including a period-start event. Choose the jersey carefully before starting: recorded on-ice snapshots refer to that player.

If overtime becomes necessary, open Game settings, increase the period count, set the new period's duration, and save. Start that period after ending the preceding one. The tracker records what you configure; it does not decide whether overtime is required or implement a separate shootout workflow.

2. Understand the different times

The tracker records both game-clock time and real-world time. They answer different questions.

Time What it means
Period time remaining The countdown for the current period. It advances during live play and freezes during a stoppage.
Actual game start The real timestamp of the first recorded faceoff that starts play.
Event timestamp The real date and time when you captured that event, including the device's local UTC offset.
Current shift The live-play time accumulated during the player's current shift.
Total TOI The tracked player's accumulated time on ice during live play. TOI means time on ice.

Create game prepares and saves the setup. Start Period creates a timestamped period boundary and leaves the countdown paused. Start clock records the opening faceoff and begins live play. Actual game start is derived from that first faceoff's timestamp.

Capture the opening faceoff when play actually begins if you want an accurate start timestamp. Creating the setup early does not start the clock. If you begin tracking late, the actual-start display reflects your first captured faceoff; the current interface has no separate field for entering an earlier scheduled start.

The real timestamps come from your device. The period countdown is operated manually to follow the rink clock. The app has no connection to the arena's scoreboard. If a tap is late, you can correct the effective period time on its event card while preserving the original capture time.

The calculated game seconds in the team JSON summary represent recorded live play. Intermissions and time spent paused contribute no live-play seconds or player TOI. The real timestamps remain available in the archive if you want to analyse elapsed wall-clock time separately.

3. Start and resume play with faceoffs

Every clock start or restart is recorded as a faceoff. There are three possible results:

Result How to record it
Your team won Tap the button showing your team's name followed by won.
Opponent won Tap the corresponding opponent button.
Unknown Tap Unknown, or use Start clock / Resume clock. Unknown is the default for the clock buttons.

All three choices start or resume the period countdown, active penalty clocks, and eligible player TOI. One tap creates one faceoff card. Once play is live, those restart controls are hidden or disabled.

You can optionally enter a faceoff player and zone before restarting. The player field means your team's faceoff taker, regardless of who wins. If #17 takes the draw and Windsor wins, enter 17 and choose Windsor won. This lets the application credit #17 with a faceoff taken and a loss.

The zone options are Offensive, Neutral, and Defensive. Use them from your team's point of view, or leave the zone unrecorded.

Unknown results count toward total faceoffs. The win percentage uses only known results:

Faceoff win % = wins / (wins + losses) × 100

For example, seven wins, three losses, and four unknown results mean 14 recorded faceoffs and a 70% win percentage over the ten known results.

If you learn the result after resuming, edit the existing faceoff card. Change Unknown to the appropriate team and save. This updates the statistics while keeping the original capture. Adding another faceoff for the same draw would count it twice.

4. Track the player on and off the ice

The large jersey-number button shows whether the tracked player is ON ICE or OFF ICE. Tap it whenever the player changes status. Each change creates an event card.

You can change status while play is live or while an active period is paused. During a stoppage, the change is recorded immediately, but it adds no TOI until play resumes.

A shift starts when you mark the player on ice and ends when you mark them off ice or end the period. A whistle pauses its accumulated time. If the player stays on through the whistle, the same shift continues after the next faceoff. If you mark them off and then on during the pause, the application closes the old shift and opens a new one.

Here is an illustrative sequence in a 15-minute period:

Period clock Action Total TOI for #17
15:00 Start the period, mark #17 on ice, and start the clock 0:00
14:35 Record a shot during live play 0:25
14:20 Stop play for icing 0:40
14:20 Mark #17 off, then on again during the pause 0:40
14:20 Resume the clock with an Unknown faceoff 0:40
14:00 Mark #17 off ice 1:00

In this example, the first shift contains 40 seconds of live play and the second contains 20. Any real time spent waiting for the restart adds zero TOI.

The tracker splits TOI into EV, PP, and PK according to its estimated strength during each live interval. A penalty expiring in the middle of a shift can change the strength category without ending that shift.

Ending a period resets the tracked player to off ice. At the start of the next period, mark them on again if appropriate. Open shifts and shifts with zero accumulated live time appear in the shift count, so accidental toggles can affect average shift length even when they add no TOI.

5. Record shots, goals, and hits

The Record a play panel has separate columns for your team and the opponent. Shot, Goal, and Hit capture controls are available during live play.

Shots: capture first, classify afterward

Tap Shot as the attempt happens. The application saves its current period time, real timestamp, team, strength, and tracked-player on-ice status immediately. You can then choose a result in the quick-result panel or on the event card.

Shot result Adds a goal Adds a shot on goal Adds a Corsi attempt Adds a Fenwick attempt
On net No Yes Yes Yes
Missed No No Yes Yes
Blocked No No Yes No
Goal Yes Yes Yes Yes
Needs result No No Yes No, until classified

A shot without a result is marked Needs details. Adding a result later updates the existing card and leaves its original capture time intact.

Use the event editor to add the shooter's jersey number. Recording a North Stars shot while #17 is on ice contributes to the player's on-ice statistics. Entering 17 as the shooter also credits their individual shooting statistics.

Goals: use one record for one attempt

If the goal is clear when it happens, tap Goal under the scoring team's name. The score increases, the attempt counts as one shot on goal, and play pauses automatically. You can add the scorer, primary assist, and secondary assist afterward.

If you already tapped Shot for the same attempt, set that shot's result to Goal. That produces the same scoring and stoppage behaviour through one event.

Keep one record per real attempt. A separate Shot and Goal for the same play would produce duplicate shot and attempt counts. Correct the existing shot, or remove the accidental duplicate.

Hits

Tap Hit under the team delivering the hit. A hit leaves play live. Add a jersey number in the editor when available. Your team's hit is credited individually to #17 when their number is assigned to it.

6. Stop play and enter penalties

At a whistle, choose a reason under Stop play: Penalty, Icing, Offside, Goalie freeze, Puck out, Net off, or Other. This creates a stoppage card and freezes the game countdown, player TOI, and active penalty timers.

For a reason outside the quick choices, use Other, then edit the stoppage. The editor includes additional reasons such as injury, timeout, official review, equipment issue, and hand pass. You can also add a note.

Penalty entry appears in the paused-play panel. To record a penalty:

  1. Pause play at the whistle, using Stop play → Penalty or another applicable reason.
  2. Tap the penalty button for the team receiving the penalty.
  3. The application creates a 2-minute minor immediately at the paused game-clock time.
  4. Edit the card to enter the player, reason, duration, and penalty class.
  5. Check Affects team strength and Coincidental penalty to match the situation you are recording.
  6. When play resumes, use Resume clock or a faceoff result. The penalty timer begins advancing with live play.

Enter durations as minutes:seconds: 2:00, 4:00, 5:00, or another duration. The class options are Minor, Double minor, Major, Misconduct, and Other. The application accepts custom durations; selecting a class alone does not choose a league rulebook or automatically replace the entered duration.

Active penalties show the team, optional jersey, class, and remaining time. End penalty creates a manual penalty-end event at the current game-clock time, after confirmation. You can use this during live play or a pause. It does not pause a running clock by itself.

Estimated strength and penalty expiration

The strength display describes your team's situation:

Label Application's estimate
EV — even strength Both teams have the same number of active penalties counted toward strength.
PP — power play The opponent has more active penalties counted toward strength.
PK — penalty kill Your team has more active penalties counted toward strength.

Misconduct penalties, penalties marked Coincidental, and penalties with Affects team strength unchecked are excluded from that comparison. Their penalty timers can still be recorded.

Penalty time advances only during live play and carries across period boundaries. During a pause or intermission, remaining penalty time stays unchanged.

When a team scores with an estimated advantage, the application ends the oldest eligible opposing minor penalty. For a double minor, it ends the current half and leaves the next half active. Major, misconduct, and coincidental penalties are not ended automatically by a goal.

This is a simplified penalty model. The tracker does not maintain complete skater lineups, goalie pulls, delayed-penalty situations, or every competition's rules for matching penalties and manpower limits. Review the strength estimate and use penalty settings or manual endings when the recorded situation requires a correction.

7. End periods and finish the game

At 0:00, the tracker automatically records a period-end event. You can also choose End period before zero and confirm; the remaining clock is recorded, the shift closes, and the tracked player becomes off ice.

Start the next period explicitly, set the player's status, and record its opening faceoff by starting the clock or choosing a result. The application waits for you at each period boundary.

Choose End game when you are finished. After confirmation, it ends an active period if necessary, records the game ending, and opens Summary. New live capture is disabled, but you can still edit the recorded cards and export the game. Return to Live tracker to find the cards' Edit buttons or use Undo after ending a game.

If you ended something accidentally, Undo can reverse the recent change while it remains available in the current session. Download the full archive after completing your corrections.

8. Find events and correct the record

The Play-by-play feed starts with the newest events first. Switch to Oldest first when you want to review the sequence from the opening faceoff.

Filter What it shows
All events Plays, faceoffs, stoppages, player toggles, period boundaries, and other recorded actions.
Team events Shots, goals, hits, penalties, and faceoffs for the game.
Player events Events involving the tracked jersey or captured while that player was on ice.
Player on-ice events Events whose captured on-ice flag is set.
Goals Direct goals and shots whose result is Goal.
Shots Shot and goal events.
Penalties Penalty entries and manual penalty endings.
Needs details Shots that still have no result.

Needs details currently identifies missing shot results. Unknown faceoffs and goals without a scorer remain visible through other filters and should be reviewed separately.

What the editor changes

Choose Edit on a card to change its effective period and game-clock time, team, type, player numbers, notes, and relevant details. Goal cards support a scorer and two assists; penalty cards support class and duration; faceoff cards support winner and zone.

The editor displays the original capture and preserves its recorded period, recorded period time, and real timestamp. The corrected period and time determine where the event belongs during replay. An updated timestamp records when the card was last changed.

Use time remaining, such as 12:37, rather than elapsed period time. Events are replayed in period order, then from larger to smaller remaining time. Their original sequence breaks ties at the same effective time.

Changing the time or type of a stoppage, faceoff, penalty, or player toggle can affect later clocks and statistics. Review the surrounding cards and summary after making such a correction. If a period boundary is missing after an edit or deletion, the replay may infer a boundary from the remaining activity and show a warning; it does not invent unrecorded final play time.

Correct on-ice events and TOI separately

The editor's Tracked player was on ice checkbox describes that particular event. It controls whether a shot or goal contributes to the player's on-ice statistics.

Shift duration and TOI follow the Player on ice and Player off ice event timeline. If you forgot to mark #17 off at 10:00, correcting a later shot's checkbox will fix that shot's attribution, but it will not end the shift at 10:00. Correct the relevant toggle's time or type as well, and review snapshots on affected plays.

Undo and deletion

Undo reverses the most recent recorded change, including a new event, edit, or deletion. The application keeps up to 100 recent changes in memory. This history resets when you reload, restore, import, or start a new game.

Deleting a card requires confirmation and removes it from the raw event log. Statistics are recalculated afterward. The archive preserves original capture fields for surviving events, but it does not contain a permanent history of every edit or deleted card. Earlier downloaded backups retain the versions that existed when you saved them.

9. Read the team and player statistics

The Summary view has Team and Tracked player tabs. Team statistics describe your team's recorded performance against the opponent. Player statistics distinguish individual involvement from events that happened while the player was on the ice.

Common terms

Statistic Meaning in this tracker
GF / GA Goals for / goals against.
SF / SA Shots on goal for / against. On net shots and goals count.
CF / CA Corsi attempts for / against: all recorded shots and goals, including missed, blocked, and shots awaiting a result.
Fenwick for / against Unblocked classified attempts: on net shots, misses, and goals.
Corsi % CF / (CF + CA) × 100.
Corsi differential CF − CA.
Fenwick % Unblocked attempts for divided by total unblocked attempts, multiplied by 100.
On-ice GF % GF / (GF + GA) × 100, using goals captured while the player was on ice.
On-ice shots for % SF / (SF + SA) × 100, using shots on goal captured while the player was on ice.
Player shooting % Individual goals divided by individual shots on goal, multiplied by 100.
Points Goals plus primary and secondary assists credited to the player.
Penalty minutes The sum of entered penalty durations, expressed in minutes. An early ending changes active time but does not reduce the assessed duration used here.
TOI Recorded live-play seconds while the tracked player is on ice, shown as minutes:seconds.
EV / PP / PK TOI TOI split by the estimated strength during each live interval.

The team summary includes score, shots, attempts, hits, faceoffs, penalties, and estimated special teams, with a period table. The player summary adds shifts, individual scoring and shooting, on-ice results, strength splits, and advanced rates.

Jersey numbers matter for individual statistics. A goal while #17 is on ice contributes to their on-ice GF. It becomes their individual goal when 17 is entered as the scorer for your team. An opponent wearing 17 is not credited to your tracked player. Similarly, being on ice for a faceoff does not establish that #17 took the draw; enter their number as your team's taker.

Advanced player statistics

Open Advanced player statistics for additional percentages and rates. Per-60 values scale the recorded count to an hour of tracked-player TOI:

Rate per 60 = count × 3,600 / player TOI in seconds

Two shots in 600 seconds of TOI produce 12 shots per 60. This is a scaled rate from the recorded sample, not a prediction that the player will take 12 shots in another game.

On-ice shooting percentage uses your team's goals and shots on goal while the player was on ice. On-ice save percentage uses opponent shots on goal minus opponent goals, divided by opponent shots on goal, over the same captured on-ice events. PDO adds those two percentages, so this tracker displays it on a scale around 100.

Estimated +/− adds one for an on-ice goal by your team at EV or PK and subtracts one for an opponent goal at EV or your team's PP. It uses the recorded on-ice snapshots and estimated or overridden event strength.

Percentages and per-60 rates with no valid denominator display a dash, and JSON exports use null. For example, an all-unknown faceoff record has a total count but no win percentage yet. With no recorded shifts, undefined shift averages and extremes currently display as 0:00. Missing results, jersey numbers, or toggles reduce what the statistics can describe.

Special-team opportunities are estimated intervals

A continuous PP or PK stretch counts as one opportunity in this implementation. An overlapping penalty, a second half of a double minor, or a period boundary may leave the same opportunity open while the estimated advantage continues.

PP percentage is PP goals divided by estimated PP opportunities, multiplied by 100. Multiple goals during one major-penalty advantage can make this value exceed 100%. PK percentage is the share of estimated PK opportunities with no goal against. An open, goal-free PK is counted as successful at that moment, so live values are provisional.

These definitions explain the displayed estimates. They can differ from another system that counts opportunities using a competition's full penalty rules.

The editor's Strength override changes the classification of that event for event-based statistics. Penalty timers, automatic minor release, and EV/PP/PK TOI still follow the penalty timeline. Correct the penalty record when the underlying strength interval is wrong.

10. Save, recover, and transfer a game

The tracker automatically saves after successful changes and approximately once per second during live play. It also attempts to save when the page is hidden or closed. Saved on this device reports successful local saving; if saving is unavailable, download the full game JSON to keep a copy.

There is one current-game slot in this browser for this site. Starting a new game or importing another one replaces that current record after the relevant confirmation. Save each completed game to a file if you want a collection of games. Use one tracker tab for the active record to avoid competing updates to the same slot.

Browser storage belongs to the device, browser profile, and site address. Games do not automatically appear on another phone or computer. Clearing site data can remove the saved record. Full JSON files provide portable backups independent of that browser slot.

Recovery after a reload

When a saved record is found, the page offers Resume saved game, Download saved backup, and Discard saved game.

Resuming a formerly live game restores its last saved clock and adds a recovery stoppage. It waits for you to restart play. Time spent with the page closed is not added to the game clock, penalty timers, or TOI. Use Resume clock to capture the restart as an Unknown faceoff, or choose a known result.

A crash can lose time since the last successful save. After recovery, compare the recorded clock with the rink situation and review recent cards before continuing.

Offline use

The app caches its page and required assets through a service worker when browser support and the site's connection allow it. Load the tracker while online and let that first load complete before relying on it at the rink. Once cached successfully, the tracking screen, local recovery, calculations, and downloads can work offline.

An offline session still saves locally. Reconnecting does not upload game records to a server or create a cloud backup. Keep the tracker visible while recording and check that its countdown follows the rink clock, especially after a device lock or interruption.

11. Choose the right download

Open Game files for five export choices.

Download Contents Typical use
Full game JSON Setup, configured periods, all raw events, original capture fields, and a current clock checkpoint. Keep a backup, reopen a game, or transfer it to another device.
Team JSON Game information, calculated team summary, enriched event history, strength intervals, and estimated PP/PK opportunities. Analyse team performance with the calculated summary available.
Player JSON Game information, calculated player summary, relevant events and involvement, shifts, and the player's on-ice strength intervals. Analyse individual and on-ice performance.
Team CSV One row per replayed event, with game information, times, team, players, results, strength, and score after the event. Work with the event log in a spreadsheet or script.
Player CSV Rows for events involving the tracked player or captured while they were on ice, with involvement and on-ice flags. Filter or analyse the player's event history in a spreadsheet.

The CSV files contain event rows. Aggregate statistical summaries and structured shift data are available in the corresponding JSON extracts and the on-screen Summary.

For an example game dated 8 October 2026 against Windsor, the full archive is named game_2026-10-08_vs_windsor.json. Extract names add a team or player suffix.

To reopen or transfer a game:

  1. Download Full game JSON from the current device.
  2. Open the tracker on the destination device or in a later session.
  3. Go to Game files and choose Import game JSON. You can access this before creating a new game.
  4. Select the full archive and confirm replacement if another game is already active.
  5. Review the restored record. A formerly live game is paused at its saved checkpoint until you restart it.

Import accepts full game archives and validates their format. Team/player JSON extracts and CSV files are analysis downloads and cannot be used to restore the complete game. The importer accepts files up to its 10 MB limit.

12. How the application works internally

The application stores one authoritative record containing the game configuration and raw events. The following is an illustrative faceoff event excerpt; a full archive also contains the game, the surrounding events, and additional metadata.

{
  "id": "evt_example_faceoff",
  "sequence": 3,
  "type": "faceoff",
  "period": 1,
  "recorded_period": 1,
  "recorded_period_time": 900,
  "period_time_remaining": 900,
  "real_timestamp": "2026-10-08T19:00:00-04:00",
  "team": "us",
  "winner": "unknown",
  "player_number": 17,
  "tracked_player_on_ice": true,
  "strength": "EV",
  "players": [],
  "notes": ""
}

Times and durations in the data are numerical seconds and may contain fractions. The interface formats them as clock times. Team identifiers stay as us and them in the data; the game configuration supplies the displayed team and opponent names. The faceoff winner is us, them, or unknown.

When an action is recorded or corrected, the browser replays the event log to derive the game state:

  1. Put events in effective period and game-clock order.
  2. Apply period starts, faceoffs, stoppages, player changes, penalties, goals, and endings.
  3. Accumulate live-play intervals and player TOI, splitting intervals when penalties expire.
  4. Recalculate score, strength, shifts, and estimated opportunities.
  5. Calculate team and player statistics from those events and intervals.

This is why editing an earlier penalty can change later PP/PK classification and time splits, or changing a shot result can update both score and shooting statistics. Original captured period/time and the real timestamp remain available alongside the corrected effective time. An event's on-ice flag initially records its captured status; editing that checkbox updates the stored flag without retaining a separate original copy.

The running browser clock measures elapsed time between updates. A separately saved checkpoint preserves the current countdown even when no new play has been recorded recently. It is included in a full archive so a live export can be restored at the downloaded time.

Flask serves the page and its JavaScript and CSS. Tracking, calculations, JSON parsing, and file generation happen in the browser. The tracker has no server-side game database or user accounts, and the game record is not uploaded by the application. It is stored in browser localStorage and in the files you download. New calculations and event entries do not require restarting the Flask server.

Older records from the play-by-play version that used separate clock-resume events are interpreted as Unknown faceoffs during replay. Their original raw fields remain in the full archive until a card is edited. A backup from the earlier shift-tracker application uses a different format and can be downloaded for reference rather than imported as a current play-by-play game.

13. A practical review before archiving

Before saving the final version, work through the record in order:

  1. Check period starts, endings, and the final score against your notes.
  2. Use Needs details to classify unfinished shots.
  3. Review Unknown faceoffs and fill in results you can establish.
  4. Add scorer, assist, shooter, and penalty jersey numbers where known.
  5. Check player on/off events and snapshots around any missed toggle.
  6. Confirm penalty classes, durations, coincidental flags, and manual endings.
  7. Review TOI, shifts, shot counts, and the estimated strength breakdown in Summary.
  8. Download the full game JSON, then any team or player extracts you need.

The value of the tracker comes from a clear record of what you observed. Capture the action promptly, preserve Unknown when you do not know a result, and use the editable cards to make corrections you can support. That gives you a game you can review, transfer, and analyse after leaving the rink.