Skip to content

Brand match and question sponsorships

The page at /admin/brand-sponsorships lets you assign a brand to matches in two independent ways: whole-match sponsor, and/or per-question sponsorships. You can set a match sponsor without configuring any question sponsorships.

Concepts

Kind Storage Claim / edit
Whole-match sponsor Match.sponsor_brand_id Brand Sponsorships page or match detail
Question sponsorships question_sponsorships rows Pre-allocated; claimed at issue time onto QuestionIssuance

Each question sponsorship has a strategy, optional target, optional best_effort (period only), and optional question definition pin:

Strategy Target Claim rule
question_number 1-based sequence string ("3") Exact match on next issuance sequence
period Period label ("1", "1:T") First unused for that issued_in_period; best_effort defaults on
period + best_effort: false Same Exact period only (no fallback after the period is past)
random null Next unused random sponsorship

Optional question definition: when the slot would claim next, the listener forces that definition (still subject to allowlists / active / triggers). If it cannot issue, no question is issued for that event. The brand is stamped only when the issued definition matches the pin.

Claim order at issue: question_number → period (exact) → period (best effort, target already past) → random. Capacity: sponsored_slot_count <= match.question_max_count.

Data source

  • Match sponsor: PATCH /api/matches/{id} with sponsor_brand_id
  • Question sponsorships write: POST /api/brands/{brand_id}/question-sponsorships
  • Question sponsorships read: GET /api/brands/{brand_id}/question-sponsorships (optional match_ids); match detail also includes all brands’ question_sponsorships

Edits require the match to be scheduled with no listener (same as question overrides). The matches list only shows those editable matches.

Workflow

  1. Open Manage → Brand Sponsorships. From the Matches board, the Question sponsorships count deep-links here with match_id, local calendar day, and league. When the match is editable (scheduled, no listener), it is auto-selected and filtered into view. If it cannot be selected (wrong day/league, already started, or load error), a toast explains why and the page loads normally for that day.
  2. Select a Brand and filter/check matches (day range, league, search, Match sponsor Any/None/by brand, Question sponsorships comparison like >= 1 or =0 on total count). Use Clear filters to reset search, league, sponsor, and sponsorship-count filters (does not clear the selected brand or day range). Only unstarted (scheduled) matches with no listener appear. Sponsor shows the whole-match sponsor brand (highlighted when it is the selected brand). Sponsorships is always a clickable count (selected brand’s when a brand is chosen; otherwise the match total). Click opens the modal (search/filter and column sort for strategy, target, best effort, brand).
  3. Whole-match sponsor (optional, standalone):
  4. Set as match sponsor — PATCHes selected matches with this brand
  5. Clear match sponsor — clears sponsor_brand_id on selected matches
  6. Question sponsorships (optional, standalone):
  7. Configure rows (strategy + target; Best effort on by default for period) → Apply question sponsorships
  8. Random share — enter 1–100% → Apply random share replaces this brand’s slots on each selected match with round(question_max_count × % / 100) random slots (count can differ per match). Claimed when no more-specific unused slot matches.
  9. Clear this brand’s sponsorships sends empty slots with replace

Match detail also edits the match sponsor and shows a read-only question sponsorships table. For test clones, set sponsor and slots on Clone Past Match (listener starts immediately).