The Box Tracker: Software for CrossFit Gyms
In 2010, I built the management website for CrossFit Full Strength, a gym in Phoenix, Arizona. I worked alongside the gym’s owner and coaches, around what they did every day: write the day’s workout, record everyone’s scores, fill classes, pay coaches and collect dues. I then rebuilt it as The Box Tracker (archive), a hosted product that many gyms could share. The first 2 gyms were onboarded in April 2011 and, at its peak, 15 CrossFit gyms ran on the platform.
Effect Media, CrossFit Full Strength and I owned The Box Tracker together. Effect Media designed the visuals and page layout. I built the architecture and the code, and ran the hosting.
What It Did
- Programming. Coaches wrote workouts days or weeks ahead. Each one went live at midnight in the gym’s own time zone and could be edited until then. Kids, teens and competitors had their own tracks, and the whole history was searchable.
- Athlete results. Athletes or coaches logged times, loads and benchmark scores every day, building a record from each athlete’s first workout. Athletes could compare their results with the rest of the gym, and coaches could follow individuals and groups.
- Classes and check-in. A recurring class schedule with a set number of spots, online reservations, a check-in screen for the front desk, and attendance by time slot and weekday.
- Coaches and payroll. Coaches were assigned to classes and could swap them. Their hours added up for payroll, and the system checked that every class was covered.
- Memberships and billing. Recurring dues, a virtual terminal for card payments at the front desk, refunds and subscription changes. Members updated their own payment details.
- Member accounts and a store. Members could load money onto an account and leave their wallets at home. The gym store handled sizes, colors, taxes, coupons, and shipping or pickup at the gym.
- An owner dashboard. Revenue by membership type against the previous period, projected income, alerts for failed payments, and a CSV export for accounting.
- Email. Reminders for upcoming and overdue dues, warnings before a saved card expired, and bulk email by membership type, from templates each gym could edit.
How It Was Built
- One codebase for every gym. Every row in the database carried a site ID, so all the gyms shared one set of tables. Each gym had its own header, footer, styles and images. A new gym installed itself on its first page load.
- A database that upgraded itself. Each module described the tables it needed. When a module loaded, it compared that description with the live MySQL schema and created or changed tables to match. Shipping a feature to every gym meant deploying code, with no migrations to write or run by hand.
- Six ways to pay, behind one checkout. Authorize.net (including its stored customer profiles), PayPal Pro, PayPal Standard, GMS e-checks and cash all worked through the same cart. Checkout, recurring billing and refunds behaved the same whichever processor a gym used.
- Careful recurring billing. A scheduled job charged dues on every gateway and sent the reminders. It stopped cleanly before the server’s time limit, and a switch could pause e-check billing if the processor had problems. Failed ACH payments rolled back for an automatic retry the next day, and no member was charged more than once per billing cycle.
- Midnight in the gym’s own time zone. A table of daylight-saving offsets, refreshed every year, let the SQL queries work in each gym’s local time, Arizona included.
- An API. An OAuth 2 server let a gym’s existing website pull its daily workout, and every gym had an RSS feed of its workouts.
- Security. Bcrypt password hashing, HTTPS with HSTS, protection against framing, and an audit log for each user. Admins could act on a member’s behalf to help them, but payments always ran under the account that owned them. I security-tested it for 2 years with Burp Suite and fuzzing.
- Tests. About 35 PHPUnit test files covered the cart, coupons, subscriptions, every payment gateway, OAuth and the workout logic. Selenium tests drove login and registration in a real browser.
The Box Tracker ran on PHP, MySQL, jQuery and Apache. I wrote about 36,000 lines of PHP classes for it, comments included. I documented the code thoroughly so that phpDocumentor could generate full API docs from the source.