Hawkeye Fan Shop Case Study
A Storefront Built to Handle Gameday, Not Just Survive It
A look at the measurement, product-page tracking, and site reliability work behind Hawkeye Fan Shop - the official online retailer for University of Iowa Athletics.
Project Overview
| Project | Ongoing eCommerce & Storefront Partnership |
| Organization | Hawkeye Fan Shop, the official online retailer for University of Iowa Athletics |
| Focus | Measurement Strategy, Product-Page Tracking, Site Reliability |
| Outcome | Ten years of accurate reporting and a storefront that holds up on gameday |
The Challenge
Hawkeye Fan Shop runs on a calendar it doesn't control. Traffic follows the Iowa Hawkeyes schedule rather than a steady curve, and every part of the storefront - from measurement to page speed - has to hold up when a single Saturday can outweigh a normal week.
Key challenges included:
- Gameday traffic spikes that dwarf typical retail patterns
- Reporting that needed to hold up across years, not just a single campaign
- Product and catalog tracking detailed enough to inform real merchandising decisions across a catalog of thousands of products.
- A decade-long relationship that meant carrying measurement forward without losing historical continuity
What Was Built
Rather than a single project, the work has been a continuous relationship - measurement rebuilt as tools changed, product tracking extended as the catalog grew, and the storefront kept steady through a decade of gamedays.
The homepage leads with gameday and promotional merchandising, backed by tracking that shows which campaigns actually drive fans through to a product.
A shared event taxonomy behind every click
Every navigation link fires through the same standardized event schema the rebuild introduced, so a click here and a click three levels deep in the catalog land in reporting with identical field names - no more reconciling naming conventions left over from earlier redesigns.
Campaign parameters baked into the rotation
Each slide gets its own tracking parameters applied automatically when it's scheduled, rather than a marketer hand-typing links before every promotion goes live - one less place for a campaign to quietly go untracked.
Merchandising changes that skip the deploy pipeline
This tile set reads from a merchandising config rather than being hardcoded into the template, so a swap ahead of a big week ships through the CMS on its own timeline instead of waiting on a code release.
A closer look at the header stack - utility links, the official-retailer banner, and primary navigation - the layer every other page on the site inherits, so it was one of the first pieces rebuilt with individually tracked links instead of one shared "nav click" event.
Self-service usage measured against contact volume
Traffic through this row gets compared against inbound support contact volume - the only way to tell whether self-service options are actually deflecting phone and email tickets, or just adding a second place a fan checks before calling anyway.
Category order managed through the catalog, not the template
This row reads its order and labels from the same catalog system driving the rest of the site, so a category can be added, renamed, or resequenced on its own schedule without a developer touching a template file.
One messaging block, tested for placement
That mission line is a single reusable content block that's been tested in a few different positions across the page - its placement here is a deliberate result of that testing, not just wherever there happened to be empty space.
Faceted browsing across a catalog this size only works if filter and sort interactions are tracked well enough to show what fans are actually narrowing in on.
Inventory sync, not a cached snapshot
The result count reconciles against live inventory on every filter change rather than a periodically cached catalog export, so a fan never sees a total that's already drifted from what's actually in stock by the time they click through.
Faceted URLs kept out of the crawl budget
Combining facets can generate thousands of near-duplicate URL variations - the rebuild routes those through canonical tags back to the base category page, so search engines spend their crawl budget on pages actually worth indexing.
Sort order driven by a ranking model
Default sort blends recency, in-stock status, and historical conversion rate rather than a merchandiser manually pinning items to the top - the ranking recalculates on its own schedule so a stale pin from a past promotion doesn't quietly linger.
Product-level tracking follows each listing from view to add-to-cart, so merchandising decisions rest on real behavior instead of guesswork.
Review data marked up for search snippets
The same feed that powers this widget also emits rating structured data on the page, which is what lets a star rating show up directly in a search result before a fan ever clicks through to the site.
Variant selection resolves to a real SKU
Choosing a variant swaps in the actual SKU behind it via a live inventory lookup, rather than just changing a label on screen - that's what lets a stockout on one specific option disable just that choice instead of taking the whole product down.
Add-to-cart logged server-side, not just in the browser
This event fires from the server as well as the browser, so an ad blocker or a flaky connection on a fan's phone doesn't quietly erase a real add-to-cart from the funnel - a common gap with browser-only tracking.
Some products carry their own tiered pricing, like this multi-shirt bundle deal. Tracking has to capture which tier a fan picks, not just that something was added to cart.
The toggle itself is a live experiment surface
Which pricing tier renders as the default selection is controlled through a feature-flag layer, which is what let the team test a bundle-first default against a single-item-first default without shipping two separate product pages.
Selecting the bundle swaps that single picker for two independent ones, each carrying its own size and color choice before checkout.
A bundle is one order line, not two
Behind the two pickers, the order system still records the pair as a single bundled line item with its own SKU - that distinction keeps bundle revenue reporting clean instead of it looking like two unrelated single-item sales.
A Closer Look: The Homepage Carousel
The homepage hero rotates through several promotional slides rather than showing one static banner. Each slide is tracked as its own creative variant, so a specific promotion's click-through and conversion can be measured against every other slide in the rotation - not lumped together as generic "homepage traffic."
This BOGO tees slide is one rotation among several, each carrying its own tracked link so the sale's actual lift can be attributed back to this exact placement.
Viewability measured before the click is
A slide only counts as seen once it's actually been in view for a minimum dwell time, not the instant it loads off-screen - without that threshold, a slide that scrolls past unread would still inflate impression counts.
One source image, several delivered sizes
The carousel serves a size-appropriate crop through an image CDN rather than shipping the same large file to every device - a meaningful save on a page most fans hit first, on whatever connection they've got at a tailgate.
The gift card slide points to a defined landing flow rather than a generic homepage link, so gift card revenue tied to this exact placement is visible on its own.
Attribution survives the redirect
The link behind this slide passes through a redirect on its way to the landing page, and the rebuild made sure the campaign parameters survive that hop - a common gap where a slide's own performance quietly gets credited to "direct traffic" instead.
A print asset with its own analytics identity
The QR code encodes a source parameter of its own, separate from anything used online - which is what makes it possible to say a scan from a printed flyer, not just a homepage click, drove a specific sale.
Seen in context, that same banner sits inside the full homepage - navigation, search, and cart are all instrumented together, so a promotional click can be followed all the way through to checkout.
Carousel controls built for more than a mouse
The step controls are reachable by keyboard and announce the current slide to a screen reader, which the original carousel implementation didn't handle - a gap that mattered more once analytics started showing real traffic from assistive technology.
Kept off the page's performance budget
A homepage carrying this many modules risks a slow initial render - the rebuild lazy-loads everything below this fold so the carousel and header remain the only things competing for the browser's attention on first load.
Category Navigation & Merchandising
Rather than one flat product catalog, the storefront is organized into a deep category structure - a dozen entry points like Jersey - Personal & NIL, Football, Tailgating & Gameday, and Collectibles, each acting as its own tracked path into the catalog rather than a generic browse link.
Twelve category tiles break the catalog into distinct entry points, with each tile's click-through tracked separately from the rest. The grid isn't static, either - tiles can be swapped, reordered, or re-themed on the fly to match the schedule, all without touching the tracking already built around each category.
Tile order responds to demand, not a fixed layout
The lead tile position is re-evaluated on a schedule against recent click-through data rather than staying pinned to one category permanently, so the grid's own performance data feeds back into which category leads it next.
Scheduled content, not a manual swap
Seasonal tiles are set up with a start and end date ahead of time rather than someone remembering to swap them in and out by hand - the content scheduler handles the transition automatically, home game or not.
A second product schema for non-apparel items
Items outside apparel get their own structured-data mapping rather than being forced into the schema built for shirts and jerseys - getting that type mapping right is what keeps search engines from misclassifying the item entirely.
On mobile, this same grid trades a mile-long vertical scroll for a horizontally swipeable carousel - a smoother way to browse a dozen entry points on a small screen.
A separate interaction model below a set breakpoint
Below a defined width, the grid swaps to a swipeable carousel rather than just shrinking the same layout - two different interaction patterns maintained from one shared data source, so a merchandising change only has to be made once.
A graphic regenerated from the schedule feed
That seasonal artwork pulls from the same schedule data published elsewhere on the site rather than being redesigned from scratch every year, so a schedule change upstream updates the graphic without a separate design request.
That same category structure resurfaces on the homepage as merchandising rows, so each row's performance can be measured on its own instead of being buried inside one long product feed.
Stock-level flags computed, not manually tagged
A low-stock style flag, when one appears, is computed from real inventory thresholds rather than a merchandiser manually tagging an item - which matters on a site where a single popular size can sell out mid-afternoon on a Saturday.
Each row is its own component
Every merchandising row on the homepage is built as an independent component with its own reporting hook, which is what lets one row's underperformance get diagnosed and swapped out without touching the rows around it.
Manufacturer catalogs synced through a shared feed
Browsing by manufacturer works because each licensed brand's catalog data syncs through the same product feed as the house label - a normalization step the rebuild had to solve so differently structured supplier feeds could sit in one browsable index.
Product Highlights
Individual products get their own editorial treatment, too. A "Product Highlight" module pairs marketing copy with a specific product or product family, so a merchandising push for one item can be measured on its own instead of disappearing into overall category traffic.
The Gameday Bib Overalls highlight walks a fan from the Women's Big Logo Stripe Overalls down to matching Youth, Toddler, and Infant sizes, with each product tracked individually.
Editorial copy lives outside the product record
Long-form copy like this is authored as its own content block rather than stuffed into the product description field, so the same write-up can be reused across a highlight module, an email, and a landing page without three copies drifting out of sync.
One family record behind several listed products
Products spanning multiple age and gender lines are linked under one family record in the catalog, which is what lets a highlight module like this pull a full size range automatically instead of a merchandiser hand-building the list.
Sell-through tracked down to individual sizes
Even at the smallest size in a family like this, sell-through gets tracked at the individual SKU level - granular enough that a reorder decision can be made on one size without waiting for the whole line to look slow.
A single high-margin item, like this Flying Herky Reverse Weave Crew, gets its own highlight module across both colorways, so one SKU's performance can be measured as its own placement.
Price rendered from the catalog, not typed into the copy
The number here pulls live from the product's actual price field rather than being hand-typed into the marketing copy, so a price change upstream can never leave a highlight module quoting a stale number.
Written to match how fans actually search
Material and construction details here are phrased around the terms fans actually search for a specific piece, rather than generic marketing language - the kind of on-page copy that gives a single high-margin product its own shot at organic search traffic.
The module reflects stock, not a fixed layout
If one colorway in a highlight like this sells out, the module drops it automatically rather than continuing to show an option a fan can't actually buy - one less thing a merchandiser has to remember to edit mid-promotion.
Filtering & Category Depth
Category tiles are only the entry point. Once a fan lands inside a collection, a full faceted filter sidebar narrows things further, and the "Shop All" menu underneath the homepage tiles goes well beyond the dozen highlighted categories - the full list runs past thirty, with deeper submenus like Shop by Sport tucked a level below that.
The price filter isn't hardcoded - that ceiling is read live off the catalog's most expensive item in this viewed category, so the range moves on its own as pricing changes instead of drifting stale the way a fixed slider would.
Computed against the catalog, not configured by hand
That upper bound recalculates from whatever the most expensive in-stock item in view actually costs, rather than a number someone updates in a settings panel - one less config value that can quietly go stale as pricing changes.
Default open/closed states set by usage data
Which filters start expanded versus collapsed isn't a design guess - it's set from which facets actually get used first in session recordings and click data, revisited periodically as browsing behavior shifts.
The full "Shop All" menu shows how deep the catalog runs - every one of these is its own trackable path into the catalog, not just the twelve highlighted on the homepage grid.
Internal linking mapped for crawl depth
This menu doubles as the site's primary internal linking structure - every category sits within a couple of clicks of the homepage on purpose, since crawl depth still shapes how quickly an updated category page gets indexed.
Submenus rendered on demand, not all at once
Deeper submenus only render once a fan actually interacts with their parent, instead of the entire nested structure loading into the page on first paint - a choice that keeps a menu this deep from dragging down initial load time.
The Footer: Navigation, Signup & Trust Signals
The footer carries almost as much weight as the homepage itself. Two separate email signup forms, a full secondary category menu, a brand carousel, and the complete policy link set all live below the fold - so a fan who never scrolls past "just browsing" still gets another shot at converting on the way out.
Social links, a one-line trust statement, and a second, separate email capture all sit in the same row - three different ways to stay connected with a fan, each measured on its own.
Outbound clicks tagged before a fan ever leaves
Each outbound link carries a referral tag specific to this exact placement, so if a spike in engagement shows up on a given platform, it can be traced back to this footer row instead of getting folded into that platform's own generic referral traffic.
A separate consent record, not a shared list
Signing up here creates its own consent record distinct from any other list on the site, which matters for compliance - a fan who opts out of one list doesn't get silently kept on another just because both forms feed the same inbox.
A brand logo row for Nike, Champion, and Tommy Bahama signals this isn't a print-on-demand shop - these are licensed manufacturers fans already trust.
Licensing status pulled from a managed feed
Brand logos and their licensing status sync from a managed partner feed rather than being manually uploaded whenever an agreement changes - a detail that matters for a licensed retailer, where showing an expired partnership is a real compliance risk, not just a stale image.
Taken together, the footer runs three distinct jobs stacked in one place: a repeated category bar, brand logos for trust, and the policy links plus copyright line that close out every page the same way.
Built to ship a trending moment same-day
The navigation and merchandising system supports slotting in a timely, culturally relevant category on short notice - a capability that matters when a specific moment in college athletics can spike search interest well before a normal content cycle would catch up to it.
One shared component, not copy-pasted per page
This row is a single shared component included on every page rather than duplicated markup - a policy update now touches one file instead of requiring the same edit repeated across dozens of individual pages, which used to be a real source of drift.
Two different anniversaries
"2008" in the copyright line is when the business first opened as the Black & Gold Shop. It won the contract for the Hawkeyes in 2016 - the year the store became what it is today.
Gift Cards & Store Pickup
The gift card and store network both get closer looks of their own. Each ties the online storefront back to something a fan can hold - a denomination-based gift card with real reviews attached, or a specific store with its own hours and contact info.
Denominations run across a fixed set of amounts, gifting goes either to the buyer's own inbox or a recipient's, and the product page carries genuine reviews right alongside the buy box.
Fixed amounts reduce a known fraud vector
Capping gift card purchases to a small set of preset amounts, instead of an open field, is a deliberate anti-fraud measure - open-value gift cards are a common target for card-testing schemes, and constraining the amount narrows that exposure.
Delivery runs through a dedicated transactional channel
Gift card codes send through a transactional email pipeline kept separate from marketing sends, since a delayed or spam-filtered delivery here isn't just a missed newsletter - it can mean a gift arrives late or not at all.
Sales here feed a reporting obligation
Because a share of gift card revenue is committed elsewhere, this product's sales data has to reconcile cleanly against an external reporting requirement, not just show up as a number in the storefront's own dashboard.
Four featured locations - two in Coralville, one each in Davenport and West Des Moines - each carry their own hours, phone, email, and a direct "Get Directions" link.
Store data doubles as local search input
The same address and hours record that powers this card also feeds structured local-business data on the page, which is what lets a store show up correctly in local search results and map listings instead of relying on a separate, easily outdated directory listing.
Two storefront names, one backend record
Two different public-facing names in the same locator resolve to a single underlying location record - keeping that mapping consistent on the backend is what prevents the same store from ever showing up twice, or with conflicting hours, in search results.
A demand signal the reporting calendar plans around
Gameday concessions traffic is predictable enough by schedule that it gets factored into staffing and inventory planning ahead of time, rather than being treated as a surprise spike after the fact each home game.
Checkout & Payment Options
At checkout, Hawkeye Fan Shop offers four express payment options beyond a standard card form - Shop Pay, PayPal, Google Pay, and Venmo - each shaving steps off the path from cart to completed order.
Each express option is its own button and its own tracked click, so if one payment method is quietly driving a disproportionate share of completed orders - or abandoned carts - that's visible instead of buried inside a single generic "checkout" event.
Product Page Details & Refinements
Product pages carry more structure than a single hero image and an add-to-cart button. Breadcrumbs, review counts, and variant selectors all shape how a fan decides, and the pattern shifts depending on what's being sold - a straightforward tee doesn't need the same interface as a build-your-own jersey.
A breadcrumb trail, a star review badge, and swatch-style Color and Size pickers give a fan everything needed to decide without leaving the page.
Thumbnails generated automatically at upload
Each gallery image is processed into its display sizes automatically when it's uploaded, rather than someone manually exporting and cropping each variant - a small piece of the pipeline that matters once a catalog runs into thousands of product photos.
Breadcrumb markup feeds the search result itself
This trail isn't just an on-page convenience - it's marked up as structured breadcrumb data, which is what lets a search engine show the category path directly in the result listing instead of just a bare URL.
A listing built to expire on a schedule
A year-specific product like this is set up with its own review date built in, so it gets flagged for retirement or refresh once the season it references has passed, instead of silently sitting in the catalog as an outdated listing.
A "Fans Also Bought" row surfaces related gear right on the product page, turning a single-item view into a shot at a second sale.
Recommendations from a co-purchase model
This row is generated from actual co-purchase patterns in the order history rather than a merchandiser manually choosing what pairs well - the model retrains on a schedule, so the pairings shift as real buying behavior shifts across a season.
Suppressed if it's already in the cart
The recommendation logic checks a fan's current cart before rendering this row, so a product already sitting in cart doesn't get recommended right back to them - a small rule that avoids the engine looking like it isn't paying attention.
The personalized Nike Football Player Jersey swaps swatches for dropdowns and adds a Player selector on top of Color and Size - interface complexity scales with the product.
A gallery this size needs its own cache strategy
A product carrying a gallery this large needs deliberate cache invalidation - swap one image without a proper versioning strategy and a fan can end up looking at a stale asset pulled from an edge cache days after the real one was replaced.
A dropdown backed by a fulfillment integration
Behind this selector sits an integration with the vendor that actually prints the personalization - the storefront has to pass the selection through cleanly enough that what a fan picks is exactly what ends up on the physical product, with no manual re-entry step in between.
Price computed from selected options
Personalization options here carry their own price modifiers that compute at selection time rather than the product having one flat catalog price - a rule that has to be maintained carefully so a change to the base product doesn't silently break the modifier math on top of it.
BOGO Tees: From Landing Page to Bundle Checkout
The BOGO Tees campaign gets a dedicated landing page rather than just a homepage banner - hero copy, a plain-language explanation of the deal, and a grid of eligible tees, each with an interactive slider so a fan can compare colorways without leaving the page. That same "buy the deal" logic carries through to checkout, where selecting the bundle option swaps a single product picker for two independent ones.
The full BOGO Tees page runs hero copy straight into a grid of eligible tees - no filtering, no extra clicks, just the deal and its pricing laid out in one continuous scroll.
A page versioned like a release
Campaign pages like this move through the same staging and review step as any other release rather than being edited directly on the live site - which matters once a page is carrying its own tracking configuration that a typo could quietly break.
Per-product overrides on a shared promotion
The bundle logic supports per-product price overrides layered on top of the campaign's default terms, so a single higher-cost item can sit inside the same promotion without needing an entirely separate campaign built just for it.
One component, configured per card
That comparison interaction is a single shared component reused across every eligible product, configured per card through the catalog data rather than being custom-built for each one - a big part of why a campaign like this can launch across dozens of products at once.
Each product card carries its own before/after slider, letting a fan drag between colorways - like this Arch Vintage Logo Tee's white and black options - without leaving the grid.
Discount-stacking rules decided which price wins
When a product qualifies for more than one active promotion at once, a defined precedence rule - not a manual override - decides which discount actually applies, so two overlapping campaigns can never accidentally stack into a price nobody approved.
Engagement measured to justify the feature's upkeep
Drag interactions and tap-through-arrow interactions are logged as distinct engagement types, which is what let the team confirm fans were actually using this comparison feature before committing more engineering time to expanding it further.
The same slider mechanic scales to less expected colorways too, like this Logo Flash tee's tan-to-pink comparison.
Color names normalized across suppliers
Manufacturers rarely agree on color naming, so the catalog maps each supplier's own color labels to one normalized internal palette - without that step, filtering or comparing by color across brands would quietly break every time a new vendor was added.
Royalty reporting tracked at the line-item level
Sales of a licensed product like this get tracked at the individual line-item level specifically so royalty reporting to the manufacturer can be generated directly from order data, rather than someone reconstructing it by hand at the end of a season.
On the product page itself, the deal starts as a simple toggle: buy one shirt, or switch to the bundle tier for two - the second option stays collapsed until a fan opts in.
Swatches labeled for more than sight
Every color option carries a text label alongside its swatch, not just a colored square - a detail that matters for both screen readers and colorblind fans, and one that's easy to quietly lose in a purely visual redesign.
The discount is recalculated at checkout
Whatever price the page displays gets independently recalculated server-side at checkout rather than the client-side number being trusted outright - a basic safeguard against a manipulated price ever actually reaching payment.
Manufacturer attribution routes returns correctly
Knowing exactly which manufacturer produced a given item matters past the sale - it's what routes a defect or warranty claim to the right supplier automatically instead of customer service tracking down who actually made a specific piece after the fact.
Selecting the bundle expands into two independent product pickers, each with its own size and color options, so a fan can mix without adding two separate items to cart by hand.
Scroll depth cross-referenced against conversion
Keeping the price visible through a long scroll isn't just a UX choice - it's informed by scroll-depth data showing where fans were dropping off before ever reaching the add-to-cart button, and this placement measurably closed part of that gap.
Defaults chosen by an inventory check
The starting selection for each item in a bundle runs an inventory check at page load rather than always defaulting to the same option - which avoids the common annoyance of a default that turns out to be out of stock the moment someone tries to check out.
The Results
With a decade of continuous work behind it, Hawkeye Fan Shop can trust its numbers and count on the storefront when it matters most.
- A storefront that holds up under sharp, gameday-driven traffic
- Reporting that stakeholders can act on without a background in analytics
- Product and catalog tracking detailed enough to guide real merchandising calls
- A measurement setup carried forward, not rebuilt from scratch, as tools have changed
Business Impact
A retailer tied to a live sports calendar doesn't get a slow ramp-up, and a ten-year relationship doesn't run on guesswork either. Measurement has to keep pace with the catalog, the schedule, and the platform itself, all at once - and it has to hold together across channels, not just on the storefront itself.
The online storefront is one piece of a larger footprint - physical locations across Iowa plus a concessions presence at every home game at Kinnick Stadium, all reporting into the same numbers.
One dashboard, not three disconnected ones
Online sales, physical retail, and gameday concessions historically lived in three separate reporting systems - part of the ongoing work has been reconciling all three into one shared view, so a single Saturday's performance doesn't require stitching together spreadsheets afterward.
Promotions like this BOGO tee campaign get their own tracked landing page, so a sale's actual lift can be measured against the traffic and revenue it pulls in.
A URL that persists across seasons
Because this promotion lives at a stable, permanent address rather than being rebuilt fresh each time it runs, it keeps whatever search ranking and backlinks it's accumulated from prior seasons instead of starting over from zero on every relaunch.
Gift cards are redeemable both online and in-store, so revenue from a single purchase can surface in either channel - reporting has to reconcile the two, not just track them separately.
Click depth trimmed after the data showed drop-off
How many clicks a fan needs to reach a purchase page is something the team actively measures and trims where the data shows drop-off - this page's placement close to the homepage is a direct result of that analysis, not just a navigation preference.
Fan Alerts signups feed the same audience that promotions like the BOGO campaign later target, so list growth and campaign performance get measured as one connected loop.
List growth segmented before a single email goes out
Signups here get segmented by how and where they joined, which is what lets a send about a new gear drop reach people who've actually engaged with similar messaging before, instead of blasting the entire list the same way every time.
Through structured measurement and ongoing site work, this partnership has given Hawkeye Fan Shop a foundation it's built on since 2016.
Explore More Case Studies
Start the Conversation
A storefront that holds up on gameday and reporting you can trust doesn't happen by accident. It's built deliberately, year over year, so the numbers you're looking at are ones you can count on.
cott Labz