# Campaigns ## User Perspective A Campaign represents a time-bounded promotional window (e.g. a sponsor deal running from June 1 to June 30). Description blocks can be linked to a campaign. While the campaign is active, those blocks are automatically appended to every video description — without the user needing to add them to each video's block order manually. ### Campaign Fields - Name - Start date (`startAt`) - End date (`endAt`, optional — ongoing campaigns have no end date) - Status (active / inactive) - Notes ### Auto-inclusion A CAMPAIGN block is auto-appended to the rendered description when: - The block's linked campaign has `status = "active"` - `campaign.startAt ≤ now ≤ campaign.endAt` (or no endAt) If a campaign expires (endAt in the past), any video with that campaign block will trigger the `DESC_OUTDATED_SPONSOR_COPY` lint error. ## Developer Perspective ### Backend - **Module**: `backend/src/modules/campaigns/` - CAMPAIGN blocks are fetched separately from `blockOrder` in `VideoRenderService` and appended at the end of the render output ### API surface `GET /campaigns` returns a read-only listing of all campaigns for the team. Create, update, and delete are not exposed through the REST API — campaign management currently requires direct database access. See [[15 - Campaigns API]] and the **Campaign CRUD API** entry in [[01 - Technical Debt and Future Work]]. ### Lint Integration `DescOutdatedSponsorRule` checks whether any CAMPAIGN blocks in `VideoConfig.blockOrder` reference an expired or inactive campaign. This produces a `DESC_OUTDATED_SPONSOR_COPY` ERROR. ## Related - [[02 - Description Engine]] - [[03 - Metadata Linting]] - [[15 - Campaigns API]]