PM Onboarding & Handoff

Welcome to School Storytellers

You're running bi-weekly marketing reports for private K–12 schools. Most of the work is already automated — your job is the judgment layer: verify, polish, send. Plan on 15–30 minutes per school per cycle.

Day 1 — Get set up

0 of 8 done

The job — your bi-weekly rhythm

  1. Monday morning, open the dashboard. The banner tells you which schools are due this week. Reports are due 4 days after a reporting period closes.
  2. Open the school's report. Stats are already pulled from the ad platforms and GA4, and an AI draft of the overview, channel notes, next steps, and client email is waiting.
  3. Enter the inquiry counts — the one manual stat (lead schools). In the report's Inquiry Reconciliation section, enter how many inquiries each form received this period (log into the school's form dashboard — the link and Loom walkthrough are right there). Cost per inquiry = ad spend ÷ total inquiries, so this number drives the headline metric. Platform "leads" often miss form fills — your verified count is the truth. As soon as you save a count, the cost-per-inquiry on that report updates instantly.
  4. Refresh the AI draft so the words match the numbers. This is the easy step to forget: entering inquiry counts updates the cost-per-inquiry number right away, but the written Key Highlights and summary do not rewrite themselves. Click “Refresh AI draft” in the report (you can type a sentence of guidance first — e.g. "lead with the strong Meta results") and the narrative regenerates from the latest numbers on the spot. Then tighten anything that reads off — your edits are remembered and teach the next draft your style.
  5. Draft the email — don't send it yourself (for now). Compose it as a draft in Janet's inbox using the ready-made email in the report, then ping Janet that it's ready for review. She'll review and send. Don't click Mark sent yet — the dashboard should match reality, so only mark it once Janet confirms the email actually went out. After a few cycles, you'll start sending directly.
  6. After client calls: log any real question the client asked in the Client Questions box at the bottom of the dashboard. Good ones get promoted to Blog Ideas — that list drives our content.
⚡ The "I changed a number but nothing updated" rhythm. Every save travels through GitHub and takes about a minute to go fully live. So when you change an inquiry count: (1) the report you're looking at updates the numbers instantly; (2) click Refresh AI draft to update the written summary (it won't rewrite on its own); (3) the home dashboard card catches up about a minute later. If the hub still shows the old number, that's just the ~1-minute lag — give it a moment and reload. The report in front of you is always current; the hub follows.
Lead schools also get a Landing Page Conversion funnel (sessions on each form's landing page → inquiries). It appears automatically once GA4 is connected for the school — nothing for you to switch on.
Miss a week? Nothing breaks. The pipeline archives the period with final stats anyway (it'll show a "Not sent" badge in Past reports) and rolls to the next period automatically. You can still open the archived snapshot and send late — but the goal is no more "Not sent" badges from here on.

The schools

Read live from each school's file — this list is never hand-edited.

SchoolTypeJudged onCurrent periodReport dueNotes
Loading…

Every period is Monday–Sunday, 14 days, with the report due the Thursday after. A school's first period starts on its campaign start (any weekday) and runs to the Sunday that puts it on the fortnight. Schools may sit on different fortnights; the hub's schedule shows exactly what is due each week.

What's automated (so you don't redo it)

A pipeline runs every morning (~8am ET). It pulls Google Ads, Meta, and GA4 numbers straight from each platform's API (the Coefficient sheet stays on as an automatic backup if an API call fails), updates every stat and comparison on the dashboard, archives finished periods with a permanent snapshot, advances to the next period, and generates the AI draft once a period closes. The ↻ Run pipeline now button at the top of the dashboard runs the same job on demand (give it ~1 minute, then refresh).

If a platform's login expires, the school's card shows a red "<API> token expired — re-authenticate (Janet)" flag. That one's not yours to fix — just text Janet; re-connecting an ad account is account-level work she owns.

You never need to: enter ad stats by hand, compute deltas, create snapshots, or move a school to its next reporting period.

Onboarding a new school

When a new school signs, you're adding one config file — schools/<slug>.json. The pipeline discovers it automatically on its next run and fills in every stat. The only thing that has to be right by hand is the config: is it a Lead or Traffic school, the right ad-account IDs, and (for lead schools) the inquiry-form setup.

Use the “+ Add school” button at the top of the dashboard — it's the easiest way and it builds the config correctly by construction (no copy-paste mistakes). A short form opens:

  1. Fill it in: school name (the web-address slug auto-fills), the campaign objective (generate inquiries · event RSVPs · drive traffic · awareness — it picks the right report template and shows you which metric it'll use), the first report period's start & end dates, location/grades/market, and the optional Notion hub + form-fill Loom links.
  2. Add each inquiry form (lead schools): one row per form — the form name and its landing-page URL. The landing-page URL powers the conversion funnel (GA4 sessions on that page ÷ inquiries). You can always add or retire forms later from the report itself.
  3. Click “Create school.” It writes the config and shows a “Hand to Janet” card with the exact next step.
  4. Janet wires up access (the one step that can't be done in the form, because it's her ad-account credentials): grant GA4/Meta/Google read access, then add the school's account IDs to the Vercel env maps — GOOGLE_ADS_CUSTOMER_IDS, META_AD_ACCOUNTS, GA4_PROPERTY_IDS — each keyed by the new slug.

Until Janet wires access, the new school shows empty stats — that's expected. The next pipeline run (or the ↻ Run pipeline button) pulls its first set of numbers automatically.

Advanced: the command-line scaffolder

The button calls the same builder as this CLI. If you'd rather script it (or hand it to Claude Code in a fresh chat — “onboard a new school”):

node scripts/new-school.mjs --slug=oak-ridge --name="Oak Ridge School" \
     --type=lead --start=2026-09-09 \   # the end is computed (Sun Sep 20)
     --location="Oak Ridge, TN" --grades="K–12" \
     --form="Visit Us|https://www.oakridge.org/admissions/visit-us"   # repeatable, lead only

--type=traffic for cost-per-click schools (no forms/Loom); --hide-traffic to drop the website-traffic section. Then refresh the registry (node scripts/registry.mjs) and commit.

The School Registry (docs/school-registry.md) is the one-page source of truth for every school's config — type, thresholds, sheet/tabs, where each account ID lives, Notion + Loom links.

Tools recap

ToolWhat forAccess
HubstaffTime tracking — timer on for all workEmail invite
The dashboardReports, statuses, guide, content logreports.schoolstorytellers.com — no login
LastPassSchool form-dashboard credentialsSign up free, then Janet shares each school's password to your account
NotionEach school's hub page (linked from its card)Shared to your email — accept the invites
LoomForm-fill walkthroughsLinks above

Who to ask

Janet (hello@jgstudio.co) — anything: access, client context, judgment calls on a report before it goes out, scope questions. Bias toward asking over stewing; a 2-minute question beats an hour of guessing.

Your first cycle, concretely

  1. Check the dashboard banner for what's due this week.
  2. Open that school's report — read the AI draft top to bottom.
  3. Verify form fills against the school's form dashboard.
  4. Draft the client email in Janet's inbox and ping her that it's ready for review.
  5. Wait for Janet's confirmation that it went out — then click Mark sent. Done until the next due date.

What needs attention right now

Nothing to memorise here. The hub keeps the live list: the red Needs attention lane holds any school that is overdue or whose data connection failed, the Last run pill at the top says whether this morning's pipeline was clean, and every past report a school never sent shows a Not sent badge in its Past reports table.

The engineering history — what was wrong with dates and numbers, and what was fixed — is in docs/audit-2026-09-26.md in the repo.