Project
Preem — a major Swedish fuel brand — runs self-service car washes and wanted a fast, on-brand way to hand new customers a free trial code, captured as a marketing lead. We designed and built a mobile-first landing page and a full admin portal that turns a simple Excel list of wash codes into a tracked, GDPR-compliant acquisition funnel the client operates entirely on their own.
The Challenge
The brief looked simple — “hand out a discount code” — but hid real complexity underneath.
Exactly One Code, Ever
Codes live in an Excel/CSV file. The site must hand out exactly one per person and never the same code twice — even under simultaneous traffic at the pump.
A Campaign, Not a Form
Every step had to feed Meta and TikTok ads for retargeting and conversion optimisation — but under strict Swedish/EU GDPR, so nothing could fire without consent.
A Non-Technical Client
They needed to upload new code batches, see how many are left/used, and change pixel IDs or the email provider themselves — without touching code or redeploying.
It Had to Feel Like an App
A sub-30-second flow, on mobile, at the station — locked zoom, no rubber-band scroll, resume-on-return, app-like OTP entry.
What We Built
One Next.js application in two halves — a three-step customer journey and a self-serve control room — faithfully matched to Preem's brand (deep green / amber, custom Preem Sans).
Email Capture
A mobile-first, single-field entry with step animations, back-button memory and localStorage resume — the lead is captured the moment they start.
6-Digit Email Verification
A confirmation code is emailed and verified on screen with an app-like OTP input — paste support, auto-advance, hashed + expiring codes.
Instant One-Time Wash Code
A unique code is issued (and emailed as backup) with a “screenshot this” prompt, confetti, and directions to the nearest station.
Code Management
Drag-and-drop CSV or Excel upload with automatic de-duplication and per-batch reporting — no developer in the loop.
Live Dashboard
Real-time counts of registrations, delivered codes and codes remaining, plus a registration list with CSV export.
Self-Serve Tracking & Email
Paste Meta / TikTok / Cookiebot IDs (injected live, no redeploy) and configure any SMTP provider with one-click presets + a real “Test connection” handshake.
Engineering Highlights
The parts that make a “simple code hand-out” actually production-safe.
Guaranteed One-Time Codes, Concurrency-Safe
The core risk was two people claiming the same code at once. We solved it with a single atomic Postgres claim inside a transaction — FOR UPDATE SKIP LOCKED means simultaneous requests each grab a different row. No duplicates, no double-delivery, ever. Each email maps to exactly one code, and the result is idempotent — a refresh returns the same code.
UPDATE wash_codes SET status='delivered', delivered_to_email=$1
WHERE id = (SELECT id FROM wash_codes WHERE status='available'
ORDER BY id LIMIT 1 FOR UPDATE SKIP LOCKED)
RETURNING code;Consent-Gated Tracking
Rather than trusting cookie auto-blocking (which misses dynamically-injected scripts), pixels are explicitly withheld until the visitor grants marketing consent via Cookiebot — and the server-side Meta CAPI respects that same flag, de-duplicated against the browser pixel via a shared event_id.
Provider-Agnostic Infra
Tracking IDs and SMTP settings live in the database, editable from the admin UI. The client swapped email providers (Brevo → Microsoft 365 → one.com) themselves, guided by the built-in connection tester — without a single deploy.
Secure by Default
Hashed, expiring OTPs with send-rate limiting and attempt caps, bcrypt admin passwords, JWT sessions in httpOnly cookies, middleware-protected admin routes, and a first-run setup that locks itself after the first account is created.
Challenges → Solutions
No duplicate / no double-spent codes under load
Atomic FOR UPDATE SKIP LOCKED claim inside a transaction
Track for ads and stay GDPR-compliant
Consent-gated pixel injection + consent-aware server-side CAPI
Non-technical client autonomy
DB-backed, admin-editable tracking + SMTP with a live connection tester
Lost browser session losing the code
Code emailed at delivery + idempotent re-issue on refresh
“App” feel on mobile Safari
Viewport + CSS + iOS gesture handlers to lock zoom and rubber-banding
Outcome
A production-ready, self-managed acquisition funnel: the client uploads a spreadsheet of codes and instantly has a branded, trackable, GDPR-compliant campaign that captures leads, delivers unique offers and feeds Meta/TikTok — all observable from a live dashboard and adjustable without engineering. Containerised with Docker for one-click deployment to Vercel or a self-hosted Coolify server.
// Redemption & lead-volume metrics to be layered in once the campaign has run.
Stack & Tooling