The studio register#
Every campaign the studio makes pieces for, seen from the studio: its key line, the concept pages it comes from, its pieces, and what is still to make. One file, register.json; the page index.html (/marketing/campaigns/) renders it, with the studio queue at the foot.
Opened 2026-10-03 as the full campaign register (EC: "a register of different campaigns that feeds into our marketing and business strategy"). Split 2026-10-04: the campaign itself became a program in relay-marketing, and this file kept the creative (EC: "this lives as a program via marketing repo", "separate, but they can be linked").
Two halves of one campaign, joined on its id#
| What | Lives in |
|---|---|
| The campaign: status, owner, job, audience, the growth-engine objective, metrics, channels and funnel step it serves, related campaigns, gates, open calls | relay-marketing program/campaigns.json (guide: its program/README.md) |
| The creative: the key line, the concept pages, the pieces and their studio status | this register |
| Who receives a send, consent, segments, the send itself | relay-marketing briefs/, segments/, publication/LOG.md |
| A piece's catalog entry (runtime, script, captions, pick, copy pass) | relay-marketing video/<entry>.md (a piece's catalog) |
| The pieces themselves | this repo: marketing/explainer/, marketing/packs/, marketing/invites/ |
| The concept pages | this repo: concepts/ |
The id is the join: it is the same in both files, and it is permanent. This file never restates the program, and the program never restates a piece. main here publishes to creative.relayctx.com, which is the other reason the strategy, statuses and open calls stay in relay-marketing: it never deploys.
Never a named person in this file. A campaign for one person keeps the person in its relay-marketing brief.
Add a campaign#
- Add it to relay-marketing's program first (
program/campaigns.json). That is where it is agreed. - Copy
TEMPLATE.jsonintocampaignshere with the same id. Write theline(the key line the pieces say; Ada passes the copy). - List its
concepts(pages underconcepts/) and itspieces. A piece not made yet has"path": nulland"status": "to-make". That puts it in the studio queue, here and in relay-marketing'sTRACKER.md. - Run
python3 marketing/campaigns/check.pywith relay-marketing checked out beside this repo, then the twelve checkers, and add a line tomarketing/CHANGELOG.md.
A concept page labelled as a campaign (a status pill starting Campaign) must be listed by an entry's concepts. The check fails otherwise, so a campaign concept can't sit outside both halves. Connecting the Dots was the one that had.
Piece status#
The studio's facts only: to-make → in-progress → made, or retired. Whether Erik picked a piece, Ada passed its copy, or it was sent is the catalog's (relay-marketing video/), not this file's.
The check#
python3 marketing/campaigns/check.py [--summary]: the schema, unique ids, every piece path and concept page exists, a piece with no path is to-make, every campaign concept page is listed. With relay-marketing beside this repo, every id must be in the program and every catalog entry must exist; without it, those two are skipped, not failed. relay-marketing's tools/program.py --check checks the other direction.
Gates#
The pieces keep the estate's gates: stealth (nothing public before the provisional is filed; named people only), campaign codes on hold, outcome level only, draw only what relay-docs states, Ada passes the copy, no third-party names until EC clears each. The full list, and each campaign's own, is in the program.
Not built yet#
- The check in CI.
check.pyruns locally. Wiring it into.github/workflows/manifest-check.ymlmakes it a gate (CI runs without relay-marketing, so it would check this half only). - A piece declares its campaign, so a render can stamp it on the end card.