World Cup 2026 Shopify Reward Game
A World Cup 2026 promotional game built for a Shopify storefront where mini-game scores unlock unique, single-use, time-limited discount codes, backed by a Node/Express and PostgreSQL service running behind a signed Shopify App Proxy.
// Architecture flow
Overview
For Mike Sport's FIFA World Cup 2026 campaign, I built a two-part promotional game system: a set of Liquid storefront mini-games (a keepy-uppy ball-juggling game, a penalty shootout, and a "predict the streak" tournament picker) themed around the tournament, paired with a standalone Node/Express and PostgreSQL backend designed to turn game performance into real, single-use Shopify discount codes. The backend is deployed with Docker Compose behind nginx and is designed to sit behind a Shopify App Proxy so the storefront can call it as a trusted first-party endpoint.
Problem
Mike Sport wanted a World Cup-themed engagement mechanic that felt like an arcade game rather than a plain "spin to win" popup, while still producing something commercially useful: real, redeemable, abuse-resistant discount codes tied to Shopify's native discount system rather than a static universal code shared across all players.
Approach
I split the work into a storefront experience and a reward service:
- On the storefront side, I built three self-contained Liquid mini-game sections (Keepy-Uppy, Penalty Shootout, Predictor Streak), each with its own canvas/SVG-based physics or animation, score tracking, local best-score persistence, and an end-of-game reward panel, all assembled into a single page template alongside a hero, predictor, bundle, product, and nations section.
- On the backend side, I built a dedicated Express API (session start, reward claim, admin claims, health) that validates a signed Shopify App Proxy request, enforces a set of anti-abuse rules, and calls the Shopify Admin GraphQL API to mint a real, time-limited, single-use discount code, persisting every session and claim in PostgreSQL for auditability.
- Reward tiers are score-gated, with higher scores unlocking better rewards (free shipping, then percentage discounts), each code expiring a couple of hours after issuance and usable once.
The mini-game sections currently compute their own local score thresholds and display a static demo code with an on-site email capture, so the score-to-live-code path is the backend's designed integration point (via the App Proxy) rather than something wired end-to-end in the Liquid files reviewed. The backend itself is fully built and deployed to generate and track real codes.
Architecture
- Storefront (Shopify Liquid): three independent mini-game sections, each with inline CSS/JS, canvas or SVG rendering, and an email-capture reward panel; a separate WebGL/Three.js cinematic scroll landing page; a shared scroll-driven pitch/ball background snippet; a page template assembling hero, predictor, the three mini-games, bundle, products, and nations sections into one page.
- Backend (Node/Express + PostgreSQL):
src/app.jswires up helmet, CORS, rate limiting, and routes;src/middleware/shopifyProxy.jsverifies the Shopify App Proxy HMAC signature (sha256 over sorted query params) with a dev escape hatch;src/routes/session.jsandsrc/routes/reward.jsimplement session issuance and reward claiming;src/services/discount.jsmaps score to reward tier and calls a thin wrapper around the Shopify Admin GraphQL discount-code mutations. - Data: a SQL migration defines
sessions(one per game play, session id plus IP plus expiry) andclaims(one per successful reward, score, reward type, generated code, Shopify discount node id, expiry), intentionally not foreign-keyed so claim history survives session cleanup. - Deployment: Dockerized app plus Postgres via docker-compose, migrations run automatically on first container start, fronted by nginx/certbot for HTTPS, with a test console and an admin claims endpoint for operational visibility.
Tech stack
- Shopify Liquid, HTML5 Canvas/SVG, vanilla JS, Three.js (landing page only)
- Node.js, Express 4, express-rate-limit, helmet, morgan, cors
- PostgreSQL (pg driver, raw SQL migrations)
- Shopify Admin GraphQL API (discount code mutations), Shopify App Proxy (HMAC-signed requests)
- Docker / Docker Compose, nginx plus certbot for TLS
Engineering highlights
- HMAC-SHA256 verification of Shopify App Proxy requests using a constant-time compare to prevent timing attacks, with sorted-query-param message construction matching Shopify's signing scheme exactly.
- Layered anti-abuse controls: one reward claim per session (409 on repeat), a DB-level rolling 24-hour IP claim cap checked inside the transaction, and separate HTTP-level rate limits for session start and reward claims.
- Score-tiered reward mapping that always resolves to the highest tier earned, with codes generated via cryptographically strong random bytes and prefixed per tier for easy identification in Shopify admin.
- Every discount code is created with a usage limit of one and a starts-at/ends-at window directly in the Shopify Admin GraphQL mutation, so enforcement lives in Shopify's own discount engine rather than the app.
- Full claim/session audit trail in PostgreSQL, exposed through a paginated, admin-secret-gated claims endpoint and a browser-based test console for manual QA of the discount-generation flow.
- Three distinct mini-game implementations (physics-based ball juggling, an aim-and-power penalty shootout with a reactive goalkeeper, and a probabilistic tournament predictor with ranking-weighted outcomes) built as self-contained Liquid sections that degrade gracefully under
prefers-reduced-motion.
Want to dig deeper?
Ask my AI agent anything about how this was built, what tradeoffs I made, or how it could fit your team.
Ask my AI →// related projects
Dynamic Bundle Builder
An embedded Shopify app that mines a store's real order history for co-purchase patterns and automatically surfaces "frequently bought together" bundles on the storefront, with Claude writing the shopper-facing names and pitches under a hard spend cap.
Homepage Curating Agent for Shopify
A planned Shopify app that rebuilds the storefront homepage and merchandising every morning around live demand and inventory, using a Perceive, Decide, Act, Learn loop with a staged autonomy ramp from shadow proposals to autonomous publishing.
Shopify Product Label App
A private, single-store Shopify app that shows rule-driven marketing labels on product cards in collection and search pages, built first for the Crocs/mikesport store and then cloned and re-skinned as an isolated app for MikeSport Lebanon.