Skip to content
WielandTech

← All work 04

Piss Poor Idea

A restroom QR ad network. Venues host stickers, patrons scan, and ad revenue is split across venues by traffic.

0raw IPs stored

Role
Sole developer: product, build, ops
Year
2026
Status
Live
A QR code next to bars showing each venue's share of revenue.

Problem

Bars and cafés have a captive audience in their restrooms and no easy way to make money from it. Advertisers want local reach without the creepiness of tracked ads. Making a two-sided network work for a handful of venues means being fair about the revenue split, and private about the people scanning.

Approach

  1. Signed agreement

    no contract, no stickers

  2. Sticker scan

    permanent short code

  3. Daily visitor hash

    HMAC · rotates daily

  4. Revenue period

    traffic-weighted split

  5. Venue payout

    shown on the venue board

Fig. From a sticker on a wall to a fair payout. Visitor identity is a per-day hash, never a raw IP.
  • Two faces, one app. A straight-laced agency site for venues and advertisers, and a playful guerrilla site for patrons. The request’s host picks the face, and short codes work on both.
  • Fair split. Revenue for a period is shared in proportion to each venue’s de-duplicated traffic. A visitor’s identity is a daily HMAC of request attributes plus a one-day cookie, so repeat scans don’t inflate a share and no raw IP is ever stored.
  • Operations built in. Patrons can rate a restroom or report a problem. Staff get a push alert (deduplicated per sticker and issue), and notifications can never break the request that triggered them.

Hard parts

  • A leaderboard that never shames. The “cleanest restroom” ranking lists only venues that opted in and have enough ratings, ranked by a Bayesian average. The network-wide mean includes unlisted venues, so opting in can’t shift the bar.
  • Legal text that can’t silently drift. Venue agreements and advertiser terms are versioned files pinned by hash. Changing the text means a new version, not an edit.
  • Real-browser-only bugs. A strict referrer policy made browsers send Origin: null on the page’s own form posts, which failed CSRF checks. The test client never sends an Origin header, so a regression test now guards it.

Outcome

  • Live, with the venue onboarding, sticker printing, scan, feedback and payout flows in place.
  • Every printed code is permanent, and the system is built around that constraint.

Stack

  • Django
  • PostgreSQL
  • ntfy
  • Kubernetes