Admin SOPs
Admin-only runbook: how to run the shop's community features.
🔒 Admins only · Standard operating procedures
Dogedin shop — admin runbook
How to run the community features from inside the Shopify store: advertising, the local guide, dog registrations, and housekeeping. Gated to admin accounts.
Loading…
Jump to: Admin access · Business ads · Guide listings · Inquiries · Dogs & lost tags · Page map · Housekeeping · Safety
1 · Admin access
You are an admin if your email is in the app_admins table in Supabase. Admin consoles ask you to sign in with that email (same account and password you use to register a dog — create one if needed).
To add another admin, open the Supabase dashboard → SQL editor and run:
insert into public.app_admins (email) values ('newadmin@example.com');That person then signs in on any admin console with that email. Removing an admin is the same delete from public.app_admins where email = '…';.
2 · Business ads — end to end
Ads live in the advertisers table and rotate through two slots in the shop. An ad only ever shows when its status is “active” and today is inside its run dates.
2.1 · Where the two ad slots appear
| Placement | Exact size | Max file | Where it shows |
|---|---|---|---|
| Banner | 728×90 (+ optional 320×100 mobile) | 150 KB | Strip across the shop homepage |
| Ribbon | 1200×120 | 120 KB | “Presented by” strip above Community Favorites |
Format must be JPG, PNG or WebP, at the exact pixel size (the application form checks this before it accepts an upload).
2.2 · The three ways an ad gets in
- A business applies at
/pages/advertise: picks a spot, uploads its banner, adds a link and dates. This files anappliedrow — it does not show yet. - A business inquires (no artwork) via the “No banner yet?” form on the same page. That’s a lead — see §4.
- You add one manually in the ads console (§2.3) — goes live immediately.
2.3 · Approving & managing ads — /pages/ads-admin
- Open
/pages/ads-adminand sign in with your admin email. - Applications waiting show at the top with a 🔔. For each you can:
- Approve & publish ▶ — flips it to
active; it starts rotating right away. - Approve, hold — marks it
approvedbut keeps it dark until you hit Activate ▶ (use this if you’re collecting payment first). - Reject ✕ — deletes it.
- Approve & publish ▶ — flips it to
- For a live ad: Pause ⏸ takes it out of rotation; Wt sets its rotation weight (higher = shown more often when a slot has several ads); Delete removes it.
- Add an ad manually: expand “➕ Add an ad manually”, paste an image URL + link, pick the spot, set weight and optional run dates, Add. It’s live at once.
Status flow: applied → approved → active ⇄ disabled. Only active rows inside their run dates ever render. Ads with an end date drop out on their own.
2.4 · Reading the numbers
Each ad card shows lifetime 👁 impressions and 👆 clicks, plus a 30-day per-slot breakdown with CTR. Impressions only count after an ad is 50% visible for a full second — the same honest rule the website uses — so the figures you quote a renewing advertiser are real.
2.5 · Pricing reference
These are the daily rates the website uses; billing in the shop is handled by you (invoice, in person, or a Shopify order — the shop doesn’t auto-charge).
| Placement | Daily | ≈ Monthly |
|---|---|---|
| Ribbon | $6/day | ≈ $180 |
| Banner | $4/day | ≈ $120 |
2.6 · Selling ad space as a Shopify product
Ad slots are also sold as regular products (“Homepage Banner Ad”, “Community Favorites Ribbon Ad”) with duration variants, so a business can pay at normal checkout. The flow is two steps, on purpose — the same shape as the website’s paid path:
- The business applies with its creative at
/pages/advertise(this is what uploads the banner and files theappliedrow). - The business buys the matching ad product using the same email. Checkout collects the money.
Fulfilment = activating the ad. When the order comes in, open /pages/ads-admin, find the application whose email matches the order, set the run dates, and hit Approve & publish ▶. That’s the whole fulfilment step.
Optional automation: the repo ships an edge function (shopify-ad-activate) that does this for you — on orders/paid it finds the matching applied advertiser and activates it for the days purchased. It’s off until you deploy it (Supabase → deploy the function with --no-verify-jwt, set WEBHOOK_SECRET, and register the Shopify orders/paid webhook to its URL with ?secret=…). Product SKUs follow AD-BANNER-28 / AD-RIBBON-7 (placement + days) so the function knows what to activate. Until it’s deployed, the manual step above is the fulfilment.
3 · Guide listings (Dog-friendly Dunedin)
Businesses add themselves at /pages/list-business (category, hours, address, card photo). Each arrives as pending and is invisible until you approve it.
- Open
/pages/admin-deskand sign in. - Under Guide listings, pending submissions show first with a 🔔.
- Approve ▶ puts it live in the guide; Deny hides it. You can Hide a live listing or Restore a denied one later.
Approved listings appear wherever the Dog-friendly Dunedin guide section is placed, with tap-to-call, directions, and website links — and every tap is counted for the business.
4 · Advertising inquiries
The “No banner yet?” form files leads into ad_inquiries. Read them at the bottom of /pages/admin-desk (business, contact, email, message, whether an email nudge went out). Reply by email; when a deal is agreed, set the ad up in the ads console (§2.3).
5 · Dogs & lost-dog tags
- Register:
/pages/register-your-dog— an owner creates an account, adds a photo and fun fact (auto-moderated), and gets a unique tag code. - Manage:
/pages/account— the owner edits or deletes their own dogs and copies each tag code. Everything is scoped to them by the database. - Look up a found dog:
/pages/found— anyone types a tag code (or the dog’s name) and reaches the owner if the owner opted in to sharing contact. A QR on a physical tag can link straight to/pages/found?tag=CODE. - Moderation: fun-fact text runs through the same AI moderation as the website. Nothing else about a dog is admin-gated — owners self-serve.
6 · Page map
| Page | Who | What |
|---|---|---|
/pages/advertise | Business | Apply for an ad or send an inquiry |
/pages/list-business | Business | Submit a guide listing |
/pages/register-your-dog | Owner | Register a dog, get a tag code |
/pages/account | Owner | Manage their dogs |
/pages/found | Anyone | Look up a lost-dog tag |
/pages/ads-admin | Admin | Approve & manage ads |
/pages/admin-desk | Admin | Review guide listings + read inquiries |
/pages/admin-sops | Admin | This runbook |
7 · Housekeeping
- Start clean: the wipe script is in the repo at
supabase/reset.sql— run it in the Supabase SQL editor to clear dogs, users, businesses, ads and inquiries. Storage buckets (dog-photos,business-photos,ad-creatives) are emptied separately from the dashboard (each bucket → “Empty bucket”), because SQL can’t delete storage objects. - Photos & creatives live in those three public-read buckets; deleting a dog or rejecting an ad from the consoles removes its row, and dog deletion also removes its photo.
- Emails (welcome-business, ad-inquiry nudges, password resets) are sent by Supabase Edge Functions and work regardless of which storefront submitted the form.
8 · Safety notes
- These consoles are safe in a public theme only because row-level security gates every read and write to admin accounts. Don’t remove those checks.
- The Supabase anon key in the theme is public by design. The service-role key is not — never paste it into the theme, a page, or a chat. Use it only in the Supabase dashboard yourself.
- All of this is on the draft theme. Don’t publish the live theme or edit it directly; test changes on the draft preview first.
- This runbook holds no passwords or keys, by design.