MySeatPack Admin Guide

Last updated: March 2026 ยท Everything you need to run the admin portal

What Is This System?

MySeatPack sells blind-box Lakers tickets. Customers pick 3โ€“5 possible games with odds (must total 100%), pay, and after the drop closes, each order is randomly assigned one game using the NIST Randomness Beacon โ€” a government quantum random number source. This makes the assignment verifiable and tamper-proof.

๐ŸŽŸ Drop Packs

Standard packs with pre-set games and odds. Customers choose a tier (100/200/300 level) and quantity (1โ€“4 seats).

โœ๏ธ Custom Packs

Customers build their own pack โ€” pick 3โ€“5 games, set their own odds. Same NIST assignment process.

๐ŸŽฏ Predict & Win

Free prediction game. Guess the combined final score. Closest wins $10 store credit. Leaderboard prize after 20 games.

๐Ÿ“ง Marketing

Email subscriber management with segmentation, tags, blast sending, and template library.

The Order Lifecycle

Pending โ†’ Confirmed โ†’ Assigned โ†’ Delivered

Automatic vs Manual Actions

๐Ÿค– Automatic (cron every hour)
  • NIST assignment (if confirmed order past assignment time)
  • Buyback reminder email at 20hr mark
  • SeatGeek price scraper update
๐Ÿ‘† Manual (you do these)
  • Confirm Pack โ†’ sends confirmation email
  • Assign (NIST) โ†’ force-run assignment now
  • Force (manual override) โ†’ assign specific game
  • Mark Delivered โ†’ enter seat info, sends ticket email
  • Mark Resolved / Issue Refund on buybacks

Buyback Policy

After assignment, customers have 24 hours to request a buyback for store credit. The percentage was shown on the pack page at purchase (typically 85%). At 20 hours, an automatic reminder email goes out. After 24 hours, the pack is considered kept and you deliver the ticket.

โš ๏ธ Always check the Buybacks tab after running assignments โ€” open buyback requests need to be resolved or refunded before you deliver tickets.

Emails โ€” What Gets Sent & When

All transactional emails are sent via Google Apps Script (the Gmail account). Marketing blasts also go through Apps Script.

Admin Tabs Reference

What each tab does and what to watch for

๐Ÿ“ฆ Orders Tab

Main operations hub. Shows all orders with status badges. Click any row to expand and see full details + action buttons.

Action Buttons

๐Ÿšจ Assign and Force actions CANNOT be undone. Double-check the order before clicking.

โ†ฉ๏ธ Buybacks Tab

Shows all buyback requests submitted by customers through their reveal page. Open = needs action. Resolved = done.

โœ๏ธ Custom Packs Tab

Filtered view of orders where source=custom. Same action buttons as Orders tab. Custom packs need extra review since customers set their own game selections.

๐Ÿ’ฐ Revenue Tab

Summary stats (total revenue, pack count, assigned count, avg price) plus a full sortable table. Export to CSV button at top right.

๐ŸŽฏ Predict & Win Tab

Manage prediction challenges.

๐ŸŒŸ Seasonal Tab

Shows seasonal/drop pack orders pulled from the Google Sheet. Read-only view โ€” no action buttons. For reference only.

โญ Credits & Leaderboard Tab

View all store credits and the Predict & Win leaderboard.

๐Ÿ“ฃ Marketing Tab

Full subscriber management + email blast tool.

Complete Order Flow

Step by step from customer purchase to ticket in hand

Step 1 โ€” Customer Places Order

1
Customer builds pack on Shopify

Selects tier, quantity, picks 3โ€“5 games, sets odds totaling 100%.

2
Cloudflare Worker creates Shopify draft order

Stores order data in KV storage (assign_[orderId]). Status = pending. Logs to Google Sheet.

3
Order appears in admin โ†’ Orders tab

Shows as Pending. No email sent yet.

Step 2 โ€” You Confirm the Order

1
Click "โœ“ Confirm Pack" in admin

Worker updates status to confirmed, calls Apps Script webhook.

2
Apps Script sends confirmation email

Branded HTML email with game options, odds breakdown, and assignment time. Goes to customer's email.

3
Order shows as Confirmed

Now eligible for NIST assignment at the scheduled time.

Step 3 โ€” NIST Assignment

1
Cron runs every hour (or you click "Assign")

Worker fetches NIST Beacon pulse for the assignment timestamp.

2
Last 8 hex chars of beacon โ†’ number 1โ€“100

That number falls in one game's range. That game is assigned.

3
Assignment email sent automatically

Customer gets game name, date, tier, beacon proof, buyback info.

4
24-hour buyback window opens

Customer can request buyback via their reveal page. At 20hrs, reminder email auto-sends.

Step 4 โ€” Ticket Delivery

1
After 24hr buyback window closes (or customer confirms attending)

Transfer ticket on Ticketmaster to customer's account.

2
Click "โœ‰ Mark Delivered" in admin

Prompts for Section, Row, Seat(s). Enter the exact seat details.

3
Ticket delivery email sent

Customer gets seat details, game info, and instructions to open Ticketmaster app.

4
Order shows Delivered

Button changes to a green "โœ“ Ticket Delivered" indicator. Done.

๐Ÿ’ก You can have multiple orders at different stages simultaneously. Check the admin daily around game time to make sure assigned orders don't expire without delivery.

Technical Reference

Architecture overview โ€” URLs, files, and what lives where

System Architecture

How the pieces connect

Shopify (storefront) โ†’ Cloudflare Worker (API + JS serving) โ†’ Google Apps Script (emails + sheet logging) โ†’ KV Storage (order data)

Cloudflare Worker

URL: https://msp-custom-pack.nameless-forest-4d91.workers.dev

Worker name: msp-custom-pack ยท Account: 745f6810...

The worker serves JS files, handles all API routes, and stores order data in KV. Deploys via Cloudflare dashboard.

JS Files Served by Worker

FileWhat it does
/admin-part2a.jsLogin, Orders tab, Buybacks tab, Custom Packs, Revenue, Predict & Win, Seasonal, Credits/Leaderboard logic
/admin-part2b.jsMarketing tab โ€” subscriber list, tags, bulk ops, blast sending, sent log
/admin-part2c.jsMarketing templates โ€” 9 starter templates, preview modal, template editor, save/load

API Routes

RouteMethodWhat it does
/admin-ordersGETReturns all orders from KV
/admin-buybacksGETReturns all buyback requests
/confirm-orderPOSTSets status=confirmed, triggers confirmation email via Apps Script
/assign-gamePOSTRuns NIST assignment (or manual_game override)
/deliver-ticketPOSTSets ticketDelivered=true, triggers ticket email
/request-buybackPOSTCustomer-facing โ€” creates buyback_[orderId] in KV
/resolve-buybackPOSTMarks buyback resolved
/refund-orderPOSTShopify refund + marks resolved
/marketing-listGETFetches subscribers from Apps Script sheet
/send-blastPOSTSends marketing email blast via Apps Script
/templatesGETFetches saved templates from Apps Script sheet
/save-templatePOSTSaves/updates a template in Apps Script sheet
/subscribePOSTAdds email to marketing list
/unsubscribePOSTRemoves email from marketing list
/pricesGETReturns cached SeatGeek prices from KV

KV Storage Keys

Key patternWhat it stores
assign_[orderId]Full order data โ€” status, games, ranges, assignment, beacon, seat info
buyback_[orderId]Buyback request data โ€” email, game, status, timestamps
public_assignmentsArray of all public assignment records (for reveal page)
seatgeek_pricesCached game prices from SeatGeek scraper
shopify_access_tokenOAuth token for Shopify API

Cron Jobs (run every hour)

Google Apps Script

Sheets Webhook: AKfycbwv3nWQ... (see worker constants)

Reveal Webhook: AKfycbxTPx7J... (see worker constants)

Handles all email sending (transactional + marketing) and Google Sheet logging. Deployed as Web App โ€” must re-deploy after any changes.

Apps Script Actions (doPost routing)

actionWhat it does
send_confirmation_emailSends pack confirmation with game odds to customer
send_assignment_emailSends game assignment result with NIST proof
send_buyback_reminder_emailSends 20hr buyback window closing reminder
send_ticket_delivered_emailSends ticket delivery with seat details
send_marketing_blastSends bulk marketing email to recipient list
add_to_marketingAdds email to subscribers sheet
bulk_add_marketingBatch adds emails to subscribers sheet
unsubscribeMarks subscriber as unsubscribed in sheet
update_tagsUpdates tags column for a subscriber
save_template / delete_templateCRUD for email templates sheet
new_order / assignment / buyback_requestedLogging rows to orders sheet

Shopify

Store: myseatpack.com ยท Admin: myseatpack.myshopify.com

Orders are created as Draft Orders (not regular orders). Admin page is a custom Liquid page (msp-admin). The page loads the worker JS files as external scripts.

Shopify Liquid Pages

PageHandleWhat it does
Admin Portalmsp-adminFull admin dashboard โ€” loads part2a/b/c JS from worker
Reveal PagerevealCustomer-facing game reveal + buyback request
Predict & Winpredict-and-winCustomer prediction entry form
Custom Pack Buildercustom-packCustomer-facing pack configurator

Admin Auth

Password: msp2026admin ยท Header: X-Admin-Key

Login function: window.mspAdminLogin() and window.doAdmLogin() (aliases)

โš ๏ธ The login div has id="admLogin" โ€” never assign window.admLogin as a function or it will collide with the DOM element and crash the script.

Debug Snapshot

Copy and paste this to Claude when you need help troubleshooting

When something breaks, copy the block below and paste it at the start of your message to Claude. It gives full context so we can debug faster without re-explaining everything.

## MySeatPack System Context ### Architecture - **Storefront:** Shopify (myseatpack.com) - **API + JS serving:** Cloudflare Worker (msp-custom-pack) - **Worker URL:** https://msp-custom-pack.nameless-forest-4d91.workers.dev - **Email + logging:** Google Apps Script (v6, deployed as Web App) - **Order storage:** Cloudflare KV (TOKENS namespace) ### Admin Portal - **URL:** https://myseatpack.com/pages/msp-admin - **Liquid page handle:** msp-admin - **Login function:** window.mspAdminLogin() / window.doAdmLogin() - **Login div id:** admLogin (NOT used as window property โ€” DOM collision risk) - **Admin key:** msp2026admin (header: X-Admin-Key) ### JS Files (served by Cloudflare Worker) - **/admin-part2a.js** โ€” Login, Orders, Buybacks, Custom Packs, Revenue, Predict & Win, Seasonal, Credits/Leaderboard - **/admin-part2b.js** โ€” Marketing subscriber list, tags, blast sending - **/admin-part2c.js** โ€” Email templates (9 starters + custom save/load) ### Order Flow Pending โ†’ Confirmed (manual) โ†’ Assigned (NIST cron or manual) โ†’ Delivered (manual) ### Cron Jobs (hourly) - processAssignments() โ€” NIST beacon assignment - updateSeatGeekPrices() โ€” price scraper - processBuybackReminders() โ€” 20hr buyback reminder email ### KV Key Patterns - assign_[orderId] โ€” full order data - buyback_[orderId] โ€” buyback requests - public_assignments โ€” public reveal data - seatgeek_prices โ€” cached prices - shopify_access_token โ€” Shopify OAuth token ### Google Apps Script Webhooks - Sheets: AKfycbwv3nWQS7KxuSGgPCxAkmbfT3vwTSUXPUGEhE2U6PJjGJkInYlEYwjY5kwjlKzGAbjDcw/exec - Reveal: AKfycbxTPx7Ji4SoDZxdb_R-KTmCJWiA5EFE3Hy8gVg6E9DyCEj5xn1VdtlEQpC3Sp7NkZiX/exec ### Transactional Emails (via Apps Script) - send_confirmation_email โ€” on Confirm Pack click - send_assignment_email โ€” on NIST assignment - send_buyback_reminder_email โ€” auto at 20hr after assignment - send_ticket_delivered_email โ€” on Mark Delivered click ### Shopify - Store: myseatpack.myshopify.com - Orders created as Draft Orders - API version: 2026-01 ### Known Gotchas 1. window.admLogin collides with DOM element id="admLogin" โ€” never assign it as a function 2. Literal newlines inside JS strings crash the script โ€” always use \n escape sequences 3. Admin JS is served by the Worker, not a static file โ€” must edit worker.js and redeploy to change admin behavior 4. Apps Script must be re-deployed (new version) after any changes or old code runs 5. Login function defined at line ~14 of admin-part2a.js โ€” any syntax error anywhere in the file prevents login --- **Issue I'm reporting:** [DESCRIBE YOUR ISSUE HERE]

Common Issues & Fixes

๐Ÿ”ด Login not working / password not accepted

Almost always a JS syntax error in admin-part2a.js that crashes the script before the login function is defined. Open browser DevTools (F12) โ†’ Console tab. Look for "Uncaught SyntaxError". Note the line number and fix that line in the worker.

๐Ÿ”ด Orders not loading / "Connection failed" toast

Worker API route failed. Check: (1) Worker is deployed and active in Cloudflare. (2) X-Admin-Key header matches the ADMIN_KEY env var. (3) KV namespace "TOKENS" is bound to the worker.

๐Ÿ”ด Emails not sending

Apps Script issue. Check: (1) Script is deployed as Web App with "Anyone" access. (2) Webhook URL in worker constants matches the deployed version URL. (3) Open Apps Script โ†’ Executions tab to see errors.

๐Ÿ”ด NIST assignment not running automatically

Check: (1) Order status is "confirmed" (not pending). (2) Assignment time has passed. (3) Worker cron is configured in wrangler.toml or Cloudflare dashboard under Triggers. (4) NIST beacon URL is reachable (occasionally down briefly).

๐Ÿ”ด Changes to worker not taking effect

You must click "Deploy" in the Cloudflare editor after making changes โ€” saving the file is not enough. Also clear browser cache or hard-refresh (Ctrl+Shift+R) the admin page.

๐Ÿ”ด Marketing list not loading

Apps Script GET route for get_marketing_list may be timing out or returning an error. Check the mktDebug element in the Marketing tab (it shows the fetch status). Also verify the PRED_SHEET URL in the worker constants is the correct deployed Apps Script URL.

Code Backups

Full source backups for all 3 components โ€” update after every change

๐Ÿšจ IMPORTANT โ€” TO ANYONE MAKING CHANGES: After deploying any update, paste the new code into the correct section below, update the date, and click Save. Cloudflare has NO auto-backup. This is the only copy.
Last updated: March 5, 2026

File: worker.js ยท Deployed at: Cloudflare Dashboard โ†’ Workers โ†’ msp-custom-pack

๐Ÿ’ก Backups are saved in your browser's local storage. They persist between sessions on this device, but are not shared across devices. For extra safety, also keep a copy in a Google Doc or text file.